xref: /petsc/src/mat/impls/aij/seq/aij.c (revision fff043a9ba80b41dfd98b650d7c193a11a8e53a5)
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;
95*fff043a9SJunchao Zhang   const MatScalar *aa;
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;
102*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1036ce1633cSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1046ce1633cSBarry Smith   diag = a->diag;
1056ce1633cSBarry Smith   for (i=0; i<m; i++) {
106b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1076ce1633cSBarry Smith       cnt++;
1086ce1633cSBarry Smith     }
1096ce1633cSBarry Smith   }
110785e854fSJed Brown   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
1116ce1633cSBarry Smith   cnt  = 0;
1126ce1633cSBarry Smith   for (i=0; i<m; i++) {
113b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1146ce1633cSBarry Smith       rows[cnt++] = i;
1156ce1633cSBarry Smith     }
1166ce1633cSBarry Smith   }
117f1f41ecbSJed Brown   *nrows = cnt;
118f1f41ecbSJed Brown   *zrows = rows;
119*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
120f1f41ecbSJed Brown   PetscFunctionReturn(0);
121f1f41ecbSJed Brown }
122f1f41ecbSJed Brown 
123f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
124f1f41ecbSJed Brown {
125f1f41ecbSJed Brown   PetscInt       nrows,*rows;
126f1f41ecbSJed Brown   PetscErrorCode ierr;
127f1f41ecbSJed Brown 
128f1f41ecbSJed Brown   PetscFunctionBegin;
1290298fd71SBarry Smith   *zrows = NULL;
130f1f41ecbSJed Brown   ierr   = MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);CHKERRQ(ierr);
131ce94432eSBarry Smith   ierr   = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr);
1326ce1633cSBarry Smith   PetscFunctionReturn(0);
1336ce1633cSBarry Smith }
1346ce1633cSBarry Smith 
135b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
136b3a44c85SBarry Smith {
137b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
138b3a44c85SBarry Smith   const MatScalar *aa;
139b3a44c85SBarry Smith   PetscInt        m=A->rmap->n,cnt = 0;
140b3a44c85SBarry Smith   const PetscInt  *ii;
141b3a44c85SBarry Smith   PetscInt        n,i,j,*rows;
142b3a44c85SBarry Smith   PetscErrorCode  ierr;
143b3a44c85SBarry Smith 
144b3a44c85SBarry Smith   PetscFunctionBegin;
1452e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
146f4259b30SLisandro Dalcin   *keptrows = NULL;
147b3a44c85SBarry Smith   ii        = a->i;
148b3a44c85SBarry Smith   for (i=0; i<m; i++) {
149b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
150b3a44c85SBarry Smith     if (!n) {
151b3a44c85SBarry Smith       cnt++;
152b3a44c85SBarry Smith       goto ok1;
153b3a44c85SBarry Smith     }
1542e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
155b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
156b3a44c85SBarry Smith     }
157b3a44c85SBarry Smith     cnt++;
158b3a44c85SBarry Smith ok1:;
159b3a44c85SBarry Smith   }
1602e5835c6SStefano Zampini   if (!cnt) {
1612e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
1622e5835c6SStefano Zampini     PetscFunctionReturn(0);
1632e5835c6SStefano Zampini   }
164854ce69bSBarry Smith   ierr = PetscMalloc1(A->rmap->n-cnt,&rows);CHKERRQ(ierr);
165b3a44c85SBarry Smith   cnt  = 0;
166b3a44c85SBarry Smith   for (i=0; i<m; i++) {
167b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
168b3a44c85SBarry Smith     if (!n) continue;
1692e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
170b3a44c85SBarry Smith       if (aa[j] != 0.0) {
171b3a44c85SBarry Smith         rows[cnt++] = i;
172b3a44c85SBarry Smith         break;
173b3a44c85SBarry Smith       }
174b3a44c85SBarry Smith     }
175b3a44c85SBarry Smith   }
1762e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
177b3a44c85SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr);
178b3a44c85SBarry Smith   PetscFunctionReturn(0);
179b3a44c85SBarry Smith }
180b3a44c85SBarry Smith 
1817087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
18279299369SBarry Smith {
18379299369SBarry Smith   PetscErrorCode    ierr;
18479299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
18599e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
18699e65526SBarry Smith   const PetscInt    *diag;
1872e5835c6SStefano Zampini   MatScalar         *aa;
18899e65526SBarry Smith   const PetscScalar *v;
189ace3abfcSBarry Smith   PetscBool         missing;
19079299369SBarry Smith 
19179299369SBarry Smith   PetscFunctionBegin;
19209f38230SBarry Smith   if (Y->assembled) {
1930298fd71SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr);
19409f38230SBarry Smith     if (!missing) {
19579299369SBarry Smith       diag = aij->diag;
19699e65526SBarry Smith       ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr);
1972e5835c6SStefano Zampini       ierr = MatSeqAIJGetArray(Y,&aa);CHKERRQ(ierr);
19879299369SBarry Smith       if (is == INSERT_VALUES) {
19979299369SBarry Smith         for (i=0; i<m; i++) {
20079299369SBarry Smith           aa[diag[i]] = v[i];
20179299369SBarry Smith         }
20279299369SBarry Smith       } else {
20379299369SBarry Smith         for (i=0; i<m; i++) {
20479299369SBarry Smith           aa[diag[i]] += v[i];
20579299369SBarry Smith         }
20679299369SBarry Smith       }
2072e5835c6SStefano Zampini       ierr = MatSeqAIJRestoreArray(Y,&aa);CHKERRQ(ierr);
20899e65526SBarry Smith       ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr);
20979299369SBarry Smith       PetscFunctionReturn(0);
21079299369SBarry Smith     }
211acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
21209f38230SBarry Smith   }
21309f38230SBarry Smith   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
21409f38230SBarry Smith   PetscFunctionReturn(0);
21509f38230SBarry Smith }
21679299369SBarry Smith 
2171a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
21817ab2063SBarry Smith {
219416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
220dfbe8321SBarry Smith   PetscErrorCode ierr;
22197f1f81fSBarry Smith   PetscInt       i,ishift;
22217ab2063SBarry Smith 
2233a40ed3dSBarry Smith   PetscFunctionBegin;
224d0f46423SBarry Smith   *m = A->rmap->n;
2253a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
226bfeeae90SHong Zhang   ishift = 0;
22753e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2282462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
229bfeeae90SHong Zhang   } else if (oshift == 1) {
2301a83f524SJed Brown     PetscInt *tia;
231d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2323b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
233854ce69bSBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr);
2341a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2351a83f524SJed Brown     *ia = tia;
236ecc77c7aSBarry Smith     if (ja) {
2371a83f524SJed Brown       PetscInt *tja;
238854ce69bSBarry Smith       ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr);
2391a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2401a83f524SJed Brown       *ja = tja;
241ecc77c7aSBarry Smith     }
2426945ee14SBarry Smith   } else {
243ecc77c7aSBarry Smith     *ia = a->i;
244ecc77c7aSBarry Smith     if (ja) *ja = a->j;
245a2ce50c7SBarry Smith   }
2463a40ed3dSBarry Smith   PetscFunctionReturn(0);
247a2744918SBarry Smith }
248a2744918SBarry Smith 
2491a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2506945ee14SBarry Smith {
251dfbe8321SBarry Smith   PetscErrorCode ierr;
2526945ee14SBarry Smith 
2533a40ed3dSBarry Smith   PetscFunctionBegin;
2543a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
255bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
256606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
257ecc77c7aSBarry Smith     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
258bcd2baecSBarry Smith   }
2593a40ed3dSBarry Smith   PetscFunctionReturn(0);
26017ab2063SBarry Smith }
26117ab2063SBarry Smith 
2621a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2633b2fbd54SBarry Smith {
2643b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
265dfbe8321SBarry Smith   PetscErrorCode ierr;
266d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
26797f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2683b2fbd54SBarry Smith 
2693a40ed3dSBarry Smith   PetscFunctionBegin;
270899cda47SBarry Smith   *nn = n;
2713a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2723b2fbd54SBarry Smith   if (symmetric) {
2732462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
2743b2fbd54SBarry Smith   } else {
275b9e7e5c1SBarry Smith     ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
276854ce69bSBarry Smith     ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
277b9e7e5c1SBarry Smith     ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
2783b2fbd54SBarry Smith     jj   = a->j;
2793b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
280bfeeae90SHong Zhang       collengths[jj[i]]++;
2813b2fbd54SBarry Smith     }
2823b2fbd54SBarry Smith     cia[0] = oshift;
2833b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2843b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2853b2fbd54SBarry Smith     }
286580bdb30SBarry Smith     ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
2873b2fbd54SBarry Smith     jj   = a->j;
288a93ec695SBarry Smith     for (row=0; row<m; row++) {
289a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
290a93ec695SBarry Smith       for (i=0; i<mr; i++) {
291bfeeae90SHong Zhang         col = *jj++;
2922205254eSKarl Rupp 
2933b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2943b2fbd54SBarry Smith       }
2953b2fbd54SBarry Smith     }
296606d414cSSatish Balay     ierr = PetscFree(collengths);CHKERRQ(ierr);
2973b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
2983b2fbd54SBarry Smith   }
2993a40ed3dSBarry Smith   PetscFunctionReturn(0);
3003b2fbd54SBarry Smith }
3013b2fbd54SBarry Smith 
3021a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
3033b2fbd54SBarry Smith {
304dfbe8321SBarry Smith   PetscErrorCode ierr;
305606d414cSSatish Balay 
3063a40ed3dSBarry Smith   PetscFunctionBegin;
3073a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
3083b2fbd54SBarry Smith 
309606d414cSSatish Balay   ierr = PetscFree(*ia);CHKERRQ(ierr);
310606d414cSSatish Balay   ierr = PetscFree(*ja);CHKERRQ(ierr);
3113a40ed3dSBarry Smith   PetscFunctionReturn(0);
3123b2fbd54SBarry Smith }
3133b2fbd54SBarry Smith 
3147cee066cSHong Zhang /*
3157cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3167cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
317040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3187cee066cSHong Zhang */
3197cee066cSHong 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)
3207cee066cSHong Zhang {
3217cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3227cee066cSHong Zhang   PetscErrorCode ierr;
3237cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
324071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3257cee066cSHong Zhang   PetscInt       *cspidx;
326071fcb05SBarry Smith   const PetscInt *jj;
3277cee066cSHong Zhang 
3287cee066cSHong Zhang   PetscFunctionBegin;
3297cee066cSHong Zhang   *nn = n;
3307cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
331625f6d37SHong Zhang 
332b9e7e5c1SBarry Smith   ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
333854ce69bSBarry Smith   ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
334b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
335b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr);
3367cee066cSHong Zhang   jj   = a->j;
3377cee066cSHong Zhang   for (i=0; i<nz; i++) {
3387cee066cSHong Zhang     collengths[jj[i]]++;
3397cee066cSHong Zhang   }
3407cee066cSHong Zhang   cia[0] = oshift;
3417cee066cSHong Zhang   for (i=0; i<n; i++) {
3427cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3437cee066cSHong Zhang   }
344580bdb30SBarry Smith   ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
3457cee066cSHong Zhang   jj   = a->j;
3467cee066cSHong Zhang   for (row=0; row<m; row++) {
3477cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3487cee066cSHong Zhang     for (i=0; i<mr; i++) {
3497cee066cSHong Zhang       col         = *jj++;
350071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
351071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
352071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3537cee066cSHong Zhang     }
3547cee066cSHong Zhang   }
3557cee066cSHong Zhang   ierr   = PetscFree(collengths);CHKERRQ(ierr);
356071fcb05SBarry Smith   *ia    = cia;
357071fcb05SBarry Smith   *ja    = cja;
3587cee066cSHong Zhang   *spidx = cspidx;
3597cee066cSHong Zhang   PetscFunctionReturn(0);
3607cee066cSHong Zhang }
3617cee066cSHong Zhang 
3627cee066cSHong 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)
3637cee066cSHong Zhang {
3647cee066cSHong Zhang   PetscErrorCode ierr;
3657cee066cSHong Zhang 
3667cee066cSHong Zhang   PetscFunctionBegin;
3675243ef75SHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
3687cee066cSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
3697cee066cSHong Zhang   PetscFunctionReturn(0);
3707cee066cSHong Zhang }
3717cee066cSHong Zhang 
37287d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
37387d4246cSBarry Smith {
37487d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
37587d4246cSBarry Smith   PetscInt       *ai = a->i;
376*fff043a9SJunchao Zhang   PetscScalar    *aa;
37787d4246cSBarry Smith   PetscErrorCode ierr;
37887d4246cSBarry Smith 
37987d4246cSBarry Smith   PetscFunctionBegin;
380*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
381*fff043a9SJunchao Zhang   ierr = PetscArraycpy(aa+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr);
382*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
38387d4246cSBarry Smith   PetscFunctionReturn(0);
38487d4246cSBarry Smith }
38587d4246cSBarry Smith 
386bd04181cSBarry Smith /*
387bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
388bd04181cSBarry Smith 
389bd04181cSBarry Smith       -   a single row of values is set with each call
390bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
391bd04181cSBarry Smith       -   the values are always added to the matrix, not set
392bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
393bd04181cSBarry Smith 
3941f763a69SBarry Smith      This does NOT assume the global column indices are sorted
395bd04181cSBarry Smith 
3961f763a69SBarry Smith */
397bd04181cSBarry Smith 
398af0996ceSBarry Smith #include <petsc/private/isimpl.h>
399189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
400189e4007SBarry Smith {
401*fff043a9SJunchao Zhang   PetscErrorCode ierr;
402189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4031f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
4041f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
4051f763a69SBarry Smith   PetscInt       lastcol = -1;
406*fff043a9SJunchao Zhang   MatScalar      *ap,value,*aa;
407189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
408189e4007SBarry Smith 
409*fff043a9SJunchao Zhang   PetscFunctionBegin;
410*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
411f38dd0b8SBarry Smith   row  = ridx[im[0]];
4121f763a69SBarry Smith   rp   = aj + ai[row];
4131f763a69SBarry Smith   ap   = aa + ai[row];
4141f763a69SBarry Smith   nrow = ailen[row];
415189e4007SBarry Smith   low  = 0;
416189e4007SBarry Smith   high = nrow;
417189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
418189e4007SBarry Smith     col = cidx[in[l]];
419f38dd0b8SBarry Smith     value = v[l];
420189e4007SBarry Smith 
421189e4007SBarry Smith     if (col <= lastcol) low = 0;
422189e4007SBarry Smith     else high = nrow;
423189e4007SBarry Smith     lastcol = col;
424189e4007SBarry Smith     while (high-low > 5) {
425189e4007SBarry Smith       t = (low+high)/2;
426189e4007SBarry Smith       if (rp[t] > col) high = t;
427189e4007SBarry Smith       else low = t;
428189e4007SBarry Smith     }
429189e4007SBarry Smith     for (i=low; i<high; i++) {
430189e4007SBarry Smith       if (rp[i] == col) {
4311f763a69SBarry Smith         ap[i] += value;
432189e4007SBarry Smith         low = i + 1;
4331f763a69SBarry Smith         break;
434189e4007SBarry Smith       }
435189e4007SBarry Smith     }
436189e4007SBarry Smith   }
437*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
438f38dd0b8SBarry Smith   return 0;
439189e4007SBarry Smith }
440189e4007SBarry Smith 
44197f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
44217ab2063SBarry Smith {
443*fff043a9SJunchao Zhang   PetscErrorCode ierr;
444416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
445e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
44697f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
447e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
448ce496241SStefano Zampini   MatScalar      *ap=NULL,value=0.0,*aa;
449ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
450ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
45117ab2063SBarry Smith 
4523a40ed3dSBarry Smith   PetscFunctionBegin;
453*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
45417ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
455416022c9SBarry Smith     row = im[k];
4565ef9f2a5SBarry Smith     if (row < 0) continue;
457cf9c20a2SJed 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);
458720833daSHong Zhang     rp   = aj + ai[row];
459876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
46017ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
461416022c9SBarry Smith     low  = 0;
462c71e6ed7SBarry Smith     high = nrow;
46317ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4645ef9f2a5SBarry Smith       if (in[l] < 0) continue;
465cf9c20a2SJed 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);
466bfeeae90SHong Zhang       col = in[l];
467071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
468071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
46936db0b34SBarry Smith 
4702205254eSKarl Rupp       if (col <= lastcol) low = 0;
4712205254eSKarl Rupp       else high = nrow;
472e2ee6c50SBarry Smith       lastcol = col;
473416022c9SBarry Smith       while (high-low > 5) {
474416022c9SBarry Smith         t = (low+high)/2;
475416022c9SBarry Smith         if (rp[t] > col) high = t;
476416022c9SBarry Smith         else low = t;
47717ab2063SBarry Smith       }
478416022c9SBarry Smith       for (i=low; i<high; i++) {
47917ab2063SBarry Smith         if (rp[i] > col) break;
48017ab2063SBarry Smith         if (rp[i] == col) {
481876c6284SHong Zhang           if (!A->structure_only) {
4820c0d7e18SFande Kong             if (is == ADD_VALUES) {
4830c0d7e18SFande Kong               ap[i] += value;
4840c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4850c0d7e18SFande Kong             }
48617ab2063SBarry Smith             else ap[i] = value;
487720833daSHong Zhang           }
488e44c0bd4SBarry Smith           low = i + 1;
48917ab2063SBarry Smith           goto noinsert;
49017ab2063SBarry Smith         }
49117ab2063SBarry Smith       }
492dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
493c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
494e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
495720833daSHong Zhang       if (A->structure_only) {
496876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
497720833daSHong Zhang       } else {
498fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
499720833daSHong Zhang       }
500c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
501416022c9SBarry Smith       /* shift up all the later entries in this row */
502580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
50317ab2063SBarry Smith       rp[i] = col;
504580bdb30SBarry Smith       if (!A->structure_only) {
505580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
506580bdb30SBarry Smith         ap[i] = value;
507580bdb30SBarry Smith       }
508416022c9SBarry Smith       low = i + 1;
509e56f5c9eSBarry Smith       A->nonzerostate++;
510e44c0bd4SBarry Smith noinsert:;
51117ab2063SBarry Smith     }
51217ab2063SBarry Smith     ailen[row] = nrow;
51317ab2063SBarry Smith   }
514*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
5153a40ed3dSBarry Smith   PetscFunctionReturn(0);
51617ab2063SBarry Smith }
51717ab2063SBarry Smith 
51819b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
51919b08ed1SBarry Smith {
52019b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
52119b08ed1SBarry Smith   PetscInt       *rp,k,row;
52219b08ed1SBarry Smith   PetscInt       *ai = a->i;
52319b08ed1SBarry Smith   PetscErrorCode ierr;
52419b08ed1SBarry Smith   PetscInt       *aj = a->j;
525*fff043a9SJunchao Zhang   MatScalar      *aa,*ap;
52619b08ed1SBarry Smith 
52719b08ed1SBarry Smith   PetscFunctionBegin;
52819b08ed1SBarry Smith   if (A->was_assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
52919b08ed1SBarry 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);
530*fff043a9SJunchao Zhang 
531*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
53219b08ed1SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
53319b08ed1SBarry Smith     row  = im[k];
53419b08ed1SBarry Smith     rp   = aj + ai[row];
53519b08ed1SBarry Smith     ap   = aa + ai[row];
53619b08ed1SBarry Smith 
53719b08ed1SBarry Smith     ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
53819b08ed1SBarry Smith     if (!A->structure_only) {
53919b08ed1SBarry Smith       if (v) {
54019b08ed1SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
54119b08ed1SBarry Smith         v   += n;
54219b08ed1SBarry Smith       } else {
54319b08ed1SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
54419b08ed1SBarry Smith       }
54519b08ed1SBarry Smith     }
54619b08ed1SBarry Smith     a->ilen[row] = n;
54719b08ed1SBarry Smith     a->imax[row] = n;
54819b08ed1SBarry Smith     a->i[row+1]  = a->i[row]+n;
54919b08ed1SBarry Smith     a->nz       += n;
55019b08ed1SBarry Smith   }
551*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
55219b08ed1SBarry Smith   PetscFunctionReturn(0);
55319b08ed1SBarry Smith }
55419b08ed1SBarry Smith 
55519b08ed1SBarry Smith /*@
55619b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
55719b08ed1SBarry Smith 
55819b08ed1SBarry Smith   Input Parameters:
55919b08ed1SBarry Smith +  A - the SeqAIJ matrix
56019b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
56119b08ed1SBarry Smith 
56219b08ed1SBarry Smith   Level: advanced
56319b08ed1SBarry Smith 
56419b08ed1SBarry Smith   Notes:
56519b08ed1SBarry 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.
56619b08ed1SBarry Smith     Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used
56719b08ed1SBarry Smith     as always with multiple matrix assemblies.
56819b08ed1SBarry Smith 
56919b08ed1SBarry Smith .seealso: MatSetOption(), MAT_SORTED_FULL, MatSetValues(), MatSeqAIJSetPreallocation()
57019b08ed1SBarry Smith @*/
57119b08ed1SBarry Smith 
57219b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal)
57319b08ed1SBarry Smith {
57419b08ed1SBarry Smith   PetscErrorCode ierr;
57519b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
57619b08ed1SBarry Smith 
57719b08ed1SBarry Smith   PetscFunctionBegin;
57819b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
57919b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
58019b08ed1SBarry Smith   a->maxnz  = nztotal;
58119b08ed1SBarry Smith   if (!a->imax) {
58219b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->imax);CHKERRQ(ierr);
58319b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
58419b08ed1SBarry Smith   }
58519b08ed1SBarry Smith   if (!a->ilen) {
58619b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->ilen);CHKERRQ(ierr);
58719b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
58819b08ed1SBarry Smith   } else {
58919b08ed1SBarry Smith     ierr = PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
59019b08ed1SBarry Smith   }
59119b08ed1SBarry Smith 
59219b08ed1SBarry Smith   /* allocate the matrix space */
59319b08ed1SBarry Smith   if (A->structure_only) {
59419b08ed1SBarry Smith     ierr = PetscMalloc1(nztotal,&a->j);CHKERRQ(ierr);
59519b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&a->i);CHKERRQ(ierr);
59619b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt));CHKERRQ(ierr);
59719b08ed1SBarry Smith   } else {
59819b08ed1SBarry Smith     ierr = PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i);CHKERRQ(ierr);
59919b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
60019b08ed1SBarry Smith   }
60119b08ed1SBarry Smith   a->i[0] = 0;
60219b08ed1SBarry Smith   if (A->structure_only) {
60319b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
60419b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
60519b08ed1SBarry Smith   } else {
60619b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
60719b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
60819b08ed1SBarry Smith   }
60919b08ed1SBarry Smith   a->free_ij         = PETSC_TRUE;
61019b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
61119b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
61219b08ed1SBarry Smith   PetscFunctionReturn(0);
61319b08ed1SBarry Smith }
61419b08ed1SBarry Smith 
615071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
616071fcb05SBarry Smith {
617071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
618071fcb05SBarry Smith   PetscInt       *rp,k,row;
619071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
620071fcb05SBarry Smith   PetscErrorCode ierr;
621071fcb05SBarry Smith   PetscInt       *aj = a->j;
622*fff043a9SJunchao Zhang   MatScalar      *aa,*ap;
623071fcb05SBarry Smith 
624071fcb05SBarry Smith   PetscFunctionBegin;
625*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
626071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
627071fcb05SBarry Smith     row  = im[k];
62819b08ed1SBarry 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);
629071fcb05SBarry Smith     rp   = aj + ai[row];
630071fcb05SBarry Smith     ap   = aa + ai[row];
631071fcb05SBarry Smith     if (!A->was_assembled) {
632071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
633071fcb05SBarry Smith     }
634071fcb05SBarry Smith     if (!A->structure_only) {
635071fcb05SBarry Smith       if (v) {
636071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
637071fcb05SBarry Smith         v   += n;
638071fcb05SBarry Smith       } else {
639071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
640071fcb05SBarry Smith       }
641071fcb05SBarry Smith     }
642071fcb05SBarry Smith     ailen[row] = n;
643071fcb05SBarry Smith     a->nz      += n;
644071fcb05SBarry Smith   }
645*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
646071fcb05SBarry Smith   PetscFunctionReturn(0);
647071fcb05SBarry Smith }
648071fcb05SBarry Smith 
649a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
6507eb43aa7SLois Curfman McInnes {
651*fff043a9SJunchao Zhang   PetscErrorCode ierr;
6527eb43aa7SLois Curfman McInnes   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
65397f1f81fSBarry Smith   PetscInt       *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
65497f1f81fSBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
655*fff043a9SJunchao Zhang   MatScalar      *ap,*aa;
6567eb43aa7SLois Curfman McInnes 
6573a40ed3dSBarry Smith   PetscFunctionBegin;
658*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
6597eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
6607eb43aa7SLois Curfman McInnes     row = im[k];
661e32f2f54SBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
662e32f2f54SBarry 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);
663bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
6647eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6657eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
666e32f2f54SBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
667e32f2f54SBarry 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);
668bfeeae90SHong Zhang       col  = in[l];
6697eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
6707eb43aa7SLois Curfman McInnes       while (high-low > 5) {
6717eb43aa7SLois Curfman McInnes         t = (low+high)/2;
6727eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6737eb43aa7SLois Curfman McInnes         else low = t;
6747eb43aa7SLois Curfman McInnes       }
6757eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
6767eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6777eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
678b49de8d1SLois Curfman McInnes           *v++ = ap[i];
6797eb43aa7SLois Curfman McInnes           goto finished;
6807eb43aa7SLois Curfman McInnes         }
6817eb43aa7SLois Curfman McInnes       }
68297e567efSBarry Smith       *v++ = 0.0;
6837eb43aa7SLois Curfman McInnes finished:;
6847eb43aa7SLois Curfman McInnes     }
6857eb43aa7SLois Curfman McInnes   }
686*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
6873a40ed3dSBarry Smith   PetscFunctionReturn(0);
6887eb43aa7SLois Curfman McInnes }
6897eb43aa7SLois Curfman McInnes 
6903ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
69117ab2063SBarry Smith {
6923ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ*)mat->data;
693c898d852SStefano Zampini   const PetscScalar *av;
6943ea6fe3dSLisandro Dalcin   PetscInt          header[4],M,N,m,nz,i;
6953ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
6966849ba73SBarry Smith   PetscErrorCode    ierr;
69717ab2063SBarry Smith 
6983a40ed3dSBarry Smith   PetscFunctionBegin;
6993ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
7002205254eSKarl Rupp 
7013ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
7023ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
7033ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
7043ea6fe3dSLisandro Dalcin   nz = A->nz;
705416022c9SBarry Smith 
7063ea6fe3dSLisandro Dalcin   /* write matrix header */
7073ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
7083ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
7093ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,header,4,PETSC_INT);CHKERRQ(ierr);
710416022c9SBarry Smith 
7113ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
7123ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(m,&rowlens);CHKERRQ(ierr);
7133ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
7143ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT);CHKERRQ(ierr);
7153ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
7163ea6fe3dSLisandro Dalcin   /* store column indices */
7173ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT);CHKERRQ(ierr);
718416022c9SBarry Smith   /* store nonzero values */
719c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(mat,&av);CHKERRQ(ierr);
720c898d852SStefano Zampini   ierr = PetscViewerBinaryWrite(viewer,av,nz,PETSC_SCALAR);CHKERRQ(ierr);
721c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(mat,&av);CHKERRQ(ierr);
722b37d52dbSMark F. Adams 
7233ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
7243ea6fe3dSLisandro Dalcin   ierr = MatView_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
7253a40ed3dSBarry Smith   PetscFunctionReturn(0);
72617ab2063SBarry Smith }
727416022c9SBarry Smith 
7287dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
7297dc0baabSHong Zhang {
7307dc0baabSHong Zhang   PetscErrorCode ierr;
7317dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
7327dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
7337dc0baabSHong Zhang 
7347dc0baabSHong Zhang   PetscFunctionBegin;
7357dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
7367dc0baabSHong Zhang   for (i=0; i<m; i++) {
7377dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
7387dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
7397dc0baabSHong Zhang       ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr);
7407dc0baabSHong Zhang     }
7417dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
7427dc0baabSHong Zhang   }
7437dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
7447dc0baabSHong Zhang   PetscFunctionReturn(0);
7457dc0baabSHong Zhang }
7467dc0baabSHong Zhang 
74709573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
748cd155464SBarry Smith 
749dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
750416022c9SBarry Smith {
751416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
752c898d852SStefano Zampini   const PetscScalar *av;
753dfbe8321SBarry Smith   PetscErrorCode    ierr;
75460e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
755e060cb09SBarry Smith   const char        *name;
756f3ef73ceSBarry Smith   PetscViewerFormat format;
75717ab2063SBarry Smith 
7583a40ed3dSBarry Smith   PetscFunctionBegin;
7597dc0baabSHong Zhang   if (A->structure_only) {
7607dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
7617dc0baabSHong Zhang     PetscFunctionReturn(0);
7627dc0baabSHong Zhang   }
76343e49210SHong Zhang 
764b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
7652e5835c6SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
7662e5835c6SStefano Zampini 
767c898d852SStefano Zampini   /* trigger copy to CPU if needed */
768c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
769c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
77071c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
77197f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
77260e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
773c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
774d00d2cf4SBarry Smith       nofinalvalue = 1;
775d00d2cf4SBarry Smith     }
776d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
777d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
77877431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
779fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
780fbfe6fa7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
781fbfe6fa7SJed Brown #else
78277431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
783fbfe6fa7SJed Brown #endif
784b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
78517ab2063SBarry Smith 
78617ab2063SBarry Smith     for (i=0; i<m; i++) {
78760e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
788aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
789a9bf72d8SJed 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);
79017ab2063SBarry Smith #else
79160e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
79217ab2063SBarry Smith #endif
79317ab2063SBarry Smith       }
79417ab2063SBarry Smith     }
795d00d2cf4SBarry Smith     if (nofinalvalue) {
796c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
797c337ccceSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
798c337ccceSJed Brown #else
799d0f46423SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
800c337ccceSJed Brown #endif
801d00d2cf4SBarry Smith     }
802317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
803fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
804d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
805fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
806d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
80744cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
80877431f27SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
80960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
810aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
81136db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
81260e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
81336db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
81460e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
81536db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
81660e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
8176831982aSBarry Smith         }
81844cd7ae7SLois Curfman McInnes #else
81960e0710aSBarry Smith         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
82044cd7ae7SLois Curfman McInnes #endif
82144cd7ae7SLois Curfman McInnes       }
822b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
82344cd7ae7SLois Curfman McInnes     }
824d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
825fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
82697f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
827d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
828854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
829496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
830496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
83160e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
832496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
833aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
83436db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
835496be53dSLois Curfman McInnes #else
836496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
837496be53dSLois Curfman McInnes #endif
838496be53dSLois Curfman McInnes         }
839496be53dSLois Curfman McInnes       }
840496be53dSLois Curfman McInnes     }
8412e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
84277431f27SBarry Smith     ierr    = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
8432e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
8442205254eSKarl Rupp       if (i+4<m) {
8452205254eSKarl 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);
8462205254eSKarl Rupp       } else if (i+3<m) {
8472205254eSKarl 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);
8482205254eSKarl Rupp       } else if (i+2<m) {
8492205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
8502205254eSKarl Rupp       } else if (i+1<m) {
8512205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
8522205254eSKarl Rupp       } else if (i<m) {
8532205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
8542205254eSKarl Rupp       } else {
8552205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);
8562205254eSKarl Rupp       }
857496be53dSLois Curfman McInnes     }
858b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
859606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
860496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
86160e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
86277431f27SBarry Smith         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
863496be53dSLois Curfman McInnes       }
864b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
865496be53dSLois Curfman McInnes     }
866b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
867496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
86860e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
869496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
870aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
87136db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
87260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
8736831982aSBarry Smith           }
874496be53dSLois Curfman McInnes #else
87560e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
876496be53dSLois Curfman McInnes #endif
877496be53dSLois Curfman McInnes         }
878496be53dSLois Curfman McInnes       }
879b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
880496be53dSLois Curfman McInnes     }
881d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
882fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
88397f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
88487828ca2SBarry Smith     PetscScalar value;
88568f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
88668f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
88768f1ed48SBarry Smith 
88868f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
88968f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
89068f1ed48SBarry Smith         realonly = PETSC_FALSE;
89168f1ed48SBarry Smith         break;
89268f1ed48SBarry Smith       }
89368f1ed48SBarry Smith     }
89468f1ed48SBarry Smith #endif
89502594712SBarry Smith 
896d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
89702594712SBarry Smith     for (i=0; i<m; i++) {
89802594712SBarry Smith       jcnt = 0;
899d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
900e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
90102594712SBarry Smith           value = a->a[cnt++];
902e24b481bSBarry Smith           jcnt++;
90302594712SBarry Smith         } else {
90402594712SBarry Smith           value = 0.0;
90502594712SBarry Smith         }
906aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
90768f1ed48SBarry Smith         if (realonly) {
90860e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
90968f1ed48SBarry Smith         } else {
91060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
91168f1ed48SBarry Smith         }
91202594712SBarry Smith #else
91360e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
91402594712SBarry Smith #endif
91502594712SBarry Smith       }
916b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
91702594712SBarry Smith     }
918d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9193c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
920150b93efSMatthew G. Knepley     PetscInt fshift=1;
921d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
9223c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
92319303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
9243c215bfdSMatthew Knepley #else
92519303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
9263c215bfdSMatthew Knepley #endif
927d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
9283c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
92960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
9303c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
931a9a0e077SKarl 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);
9323c215bfdSMatthew Knepley #else
933150b93efSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
9343c215bfdSMatthew Knepley #endif
9353c215bfdSMatthew Knepley       }
9363c215bfdSMatthew Knepley     }
937d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9383a40ed3dSBarry Smith   } else {
939d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
940d5f3da31SBarry Smith     if (A->factortype) {
94116cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
94216cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
94316cd7e1dSShri Abhyankar         /* L part */
94460e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
94516cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
94616cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
94760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
94816cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9496712e2f1SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
95016cd7e1dSShri Abhyankar           } else {
95160e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
95216cd7e1dSShri Abhyankar           }
95316cd7e1dSShri Abhyankar #else
95460e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
95516cd7e1dSShri Abhyankar #endif
95616cd7e1dSShri Abhyankar         }
95716cd7e1dSShri Abhyankar         /* diagonal */
95816cd7e1dSShri Abhyankar         j = a->diag[i];
95916cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
96016cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
96160e0710aSBarry 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);
96216cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9636712e2f1SBarry 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);
96416cd7e1dSShri Abhyankar         } else {
96560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
96616cd7e1dSShri Abhyankar         }
96716cd7e1dSShri Abhyankar #else
96860e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
96916cd7e1dSShri Abhyankar #endif
97016cd7e1dSShri Abhyankar 
97116cd7e1dSShri Abhyankar         /* U part */
97260e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
97316cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
97416cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
97560e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
97616cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
97722ab088eSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
97816cd7e1dSShri Abhyankar           } else {
97960e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
98016cd7e1dSShri Abhyankar           }
98116cd7e1dSShri Abhyankar #else
98260e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
98316cd7e1dSShri Abhyankar #endif
98416cd7e1dSShri Abhyankar         }
98516cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
98616cd7e1dSShri Abhyankar       }
98716cd7e1dSShri Abhyankar     } else {
98817ab2063SBarry Smith       for (i=0; i<m; i++) {
98977431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
99060e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
991aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
99236db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
99360e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
99436db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
99560e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
9963a40ed3dSBarry Smith           } else {
99760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
99817ab2063SBarry Smith           }
99917ab2063SBarry Smith #else
100060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
100117ab2063SBarry Smith #endif
100217ab2063SBarry Smith         }
1003b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
100417ab2063SBarry Smith       }
100516cd7e1dSShri Abhyankar     }
1006d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
100717ab2063SBarry Smith   }
1008b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
10093a40ed3dSBarry Smith   PetscFunctionReturn(0);
1010416022c9SBarry Smith }
1011416022c9SBarry Smith 
10129804daf3SBarry Smith #include <petscdraw.h>
1013dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
1014416022c9SBarry Smith {
1015480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
1016416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1017dfbe8321SBarry Smith   PetscErrorCode    ierr;
1018383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
1019383922c3SLisandro Dalcin   int               color;
1020b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1021b0a32e0cSBarry Smith   PetscViewer       viewer;
1022f3ef73ceSBarry Smith   PetscViewerFormat format;
1023*fff043a9SJunchao Zhang   const PetscScalar *aa;
1024cddf8d76SBarry Smith 
10253a40ed3dSBarry Smith   PetscFunctionBegin;
1026480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
1027b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1028b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1029383922c3SLisandro Dalcin 
1030416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
1031*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1032fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1033383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10340513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
1035b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
1036416022c9SBarry Smith     for (i=0; i<m; i++) {
1037cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1038bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1039bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1040*fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) >=  0.) continue;
1041b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1042cddf8d76SBarry Smith       }
1043cddf8d76SBarry Smith     }
1044b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
1045cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1046cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1047bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1048bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1049*fff043a9SJunchao Zhang         if (aa[j] !=  0.) continue;
1050b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1051cddf8d76SBarry Smith       }
1052cddf8d76SBarry Smith     }
1053b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1054cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1055cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1056bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1057bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1058*fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) <=  0.) continue;
1059b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1060416022c9SBarry Smith       }
1061416022c9SBarry Smith     }
1062383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10630513a670SBarry Smith   } else {
10640513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10650513a670SBarry Smith     /* first determine max of all nonzero values */
1066b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1067383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
1068b0a32e0cSBarry Smith     PetscDraw popup;
10690513a670SBarry Smith 
10700513a670SBarry Smith     for (i=0; i<nz; i++) {
1071*fff043a9SJunchao Zhang       if (PetscAbsScalar(aa[i]) > maxv) maxv = PetscAbsScalar(aa[i]);
10720513a670SBarry Smith     }
1073383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1074b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
107545f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
1076383922c3SLisandro Dalcin 
1077383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10780513a670SBarry Smith     for (i=0; i<m; i++) {
1079383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1080383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1081bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1082383922c3SLisandro Dalcin         x_l = a->j[j];
1083383922c3SLisandro Dalcin         x_r = x_l + 1.0;
1084*fff043a9SJunchao Zhang         color = PetscDrawRealToColor(PetscAbsScalar(aa[count]),minv,maxv);
1085b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
10860513a670SBarry Smith         count++;
10870513a670SBarry Smith       }
10880513a670SBarry Smith     }
1089383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10900513a670SBarry Smith   }
1091*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
1092480ef9eaSBarry Smith   PetscFunctionReturn(0);
1093480ef9eaSBarry Smith }
1094cddf8d76SBarry Smith 
10959804daf3SBarry Smith #include <petscdraw.h>
1096dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
1097480ef9eaSBarry Smith {
1098dfbe8321SBarry Smith   PetscErrorCode ierr;
1099b0a32e0cSBarry Smith   PetscDraw      draw;
110036db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1101ace3abfcSBarry Smith   PetscBool      isnull;
1102480ef9eaSBarry Smith 
1103480ef9eaSBarry Smith   PetscFunctionBegin;
1104b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1105b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1106480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1107480ef9eaSBarry Smith 
1108d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1109480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
1110b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1111832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1112b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
11130298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1114832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
11153a40ed3dSBarry Smith   PetscFunctionReturn(0);
1116416022c9SBarry Smith }
1117416022c9SBarry Smith 
1118dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1119416022c9SBarry Smith {
1120dfbe8321SBarry Smith   PetscErrorCode ierr;
1121ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1122416022c9SBarry Smith 
11233a40ed3dSBarry Smith   PetscFunctionBegin;
1124251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1125251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1126251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1127c45a1595SBarry Smith   if (iascii) {
11283a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
11290f5bd95cSBarry Smith   } else if (isbinary) {
11303a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
11310f5bd95cSBarry Smith   } else if (isdraw) {
11323a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
113311aeaf0aSBarry Smith   }
11344108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
11353a40ed3dSBarry Smith   PetscFunctionReturn(0);
113617ab2063SBarry Smith }
113719bcc07fSBarry Smith 
1138dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
113917ab2063SBarry Smith {
1140416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
11416849ba73SBarry Smith   PetscErrorCode ierr;
1142580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1143d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
114454f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
11453447b6efSHong Zhang   PetscReal      ratio  = 0.6;
114617ab2063SBarry Smith 
11473a40ed3dSBarry Smith   PetscFunctionBegin;
11483a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1149071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1150b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1151b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
1152b215bc84SStefano Zampini     ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
1153b215bc84SStefano Zampini     PetscFunctionReturn(0);
1154b215bc84SStefano Zampini   }
115517ab2063SBarry Smith 
115643ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
115717ab2063SBarry Smith   for (i=1; i<m; i++) {
1158416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
115917ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
116094a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
116117ab2063SBarry Smith     if (fshift) {
1162bfeeae90SHong Zhang       ip = aj + ai[i];
1163bfeeae90SHong Zhang       ap = aa + ai[i];
116417ab2063SBarry Smith       N  = ailen[i];
1165580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1166580bdb30SBarry Smith       if (!A->structure_only) {
1167580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
116817ab2063SBarry Smith       }
116917ab2063SBarry Smith     }
117017ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
117117ab2063SBarry Smith   }
117217ab2063SBarry Smith   if (m) {
117317ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
117417ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
117517ab2063SBarry Smith   }
11767b083b7cSBarry Smith 
117717ab2063SBarry Smith   /* reset ilen and imax for each row */
11787b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1179396832f4SHong Zhang   if (A->structure_only) {
1180071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1181071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1182396832f4SHong Zhang   } else { /* !A->structure_only */
118317ab2063SBarry Smith     for (i=0; i<m; i++) {
118417ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
11857b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
118617ab2063SBarry Smith     }
1187396832f4SHong Zhang   }
1188bfeeae90SHong Zhang   a->nz = ai[m];
118965e19b50SBarry 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);
119017ab2063SBarry Smith 
119109f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1192d0f46423SBarry 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);
1193ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1194ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
11952205254eSKarl Rupp 
11968e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1197dd5f02e7SSatish Balay   a->reallocs         = 0;
11986712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
119936db0b34SBarry Smith   a->rmax             = rmax;
12004e220ebcSLois Curfman McInnes 
1201396832f4SHong Zhang   if (!A->structure_only) {
120211e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1203396832f4SHong Zhang   }
12044108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
12053a40ed3dSBarry Smith   PetscFunctionReturn(0);
120617ab2063SBarry Smith }
120717ab2063SBarry Smith 
120899cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
120999cafbc1SBarry Smith {
121099cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
121199cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12122e5835c6SStefano Zampini   MatScalar      *aa;
1213acf2f550SJed Brown   PetscErrorCode ierr;
121499cafbc1SBarry Smith 
121599cafbc1SBarry Smith   PetscFunctionBegin;
12162e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
121799cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
12182e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1219acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
122099cafbc1SBarry Smith   PetscFunctionReturn(0);
122199cafbc1SBarry Smith }
122299cafbc1SBarry Smith 
122399cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
122499cafbc1SBarry Smith {
122599cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
122699cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12272e5835c6SStefano Zampini   MatScalar      *aa;
1228acf2f550SJed Brown   PetscErrorCode ierr;
122999cafbc1SBarry Smith 
123099cafbc1SBarry Smith   PetscFunctionBegin;
12312e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
123299cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
12332e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1234acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
123599cafbc1SBarry Smith   PetscFunctionReturn(0);
123699cafbc1SBarry Smith }
123799cafbc1SBarry Smith 
1238dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
123917ab2063SBarry Smith {
1240dfbe8321SBarry Smith   PetscErrorCode ierr;
1241*fff043a9SJunchao Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1242*fff043a9SJunchao Zhang   MatScalar      *aa;
12433a40ed3dSBarry Smith 
12443a40ed3dSBarry Smith   PetscFunctionBegin;
1245*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayWrite(A,&aa);CHKERRQ(ierr);
1246*fff043a9SJunchao Zhang   ierr = PetscArrayzero(aa,a->i[A->rmap->n]);CHKERRQ(ierr);
1247*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayWrite(A,&aa);CHKERRQ(ierr);
1248acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12493a40ed3dSBarry Smith   PetscFunctionReturn(0);
125017ab2063SBarry Smith }
1251416022c9SBarry Smith 
1252dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
125317ab2063SBarry Smith {
1254416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1255dfbe8321SBarry Smith   PetscErrorCode ierr;
1256d5d45c9bSBarry Smith 
12573a40ed3dSBarry Smith   PetscFunctionBegin;
1258aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1259d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
126017ab2063SBarry Smith #endif
1261e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
12626bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
12636bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
126405b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1265d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1266071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1267071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1268846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
126971f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
127005b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
12716bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
127205b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
1273cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
1274a30b2313SHong Zhang 
12754108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1276bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1277901853e0SKris Buschelman 
12786718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12796718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12806718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
12816718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
12826718818eSStefano Zampini      due to different matrix sizes */
12836718818eSStefano Zampini   ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr);
12846718818eSStefano Zampini 
1285f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
1286bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1287bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1288bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1289bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1290bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1291bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
12924222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
12934222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
1294e6e9a74fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr);
1295fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
12964222ddf1SHong Zhang #endif
12973d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
12983d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL);CHKERRQ(ierr);
12993d0639e7SStefano Zampini #endif
13004222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr);
1301af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1302af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1303af8000cdSHong Zhang #endif
1304d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1305d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr);
1306d24d4204SJose E. Roman #endif
130763c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
130863c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
13094222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
131063c07aadSStefano Zampini #endif
1311b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1312c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1313c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1314bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1315bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1316846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1317bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1318bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
13194222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr);
13204222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
13214222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
1322ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJKron_C",NULL);CHKERRQ(ierr);
13233a40ed3dSBarry Smith   PetscFunctionReturn(0);
132417ab2063SBarry Smith }
132517ab2063SBarry Smith 
1326ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
132717ab2063SBarry Smith {
1328416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13294846f1f5SKris Buschelman   PetscErrorCode ierr;
13303a40ed3dSBarry Smith 
13313a40ed3dSBarry Smith   PetscFunctionBegin;
1332a65d3064SKris Buschelman   switch (op) {
1333a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13344e0d8c25SBarry Smith     a->roworiented = flg;
1335a65d3064SKris Buschelman     break;
1336a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1337a9817697SBarry Smith     a->keepnonzeropattern = flg;
1338a65d3064SKris Buschelman     break;
1339512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1340512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1341a65d3064SKris Buschelman     break;
1342a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13434e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1344a65d3064SKris Buschelman     break;
1345a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13464e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1347a65d3064SKris Buschelman     break;
134828b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
134928b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
135028b2fa4aSMatthew Knepley     break;
1351a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13524e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13530df259c2SBarry Smith     break;
13543d472b54SHong Zhang   case MAT_SPD:
1355b1646e73SJed Brown   case MAT_SYMMETRIC:
1356b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1357b1646e73SJed Brown   case MAT_HERMITIAN:
1358b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1359957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13605021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13615021d80fSJed Brown     break;
13628c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1363a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1364a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1365290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1366a65d3064SKris Buschelman     break;
1367b87ac2d8SJed Brown   case MAT_USE_INODES:
1368b215bc84SStefano Zampini     ierr = MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg);CHKERRQ(ierr);
1369b87ac2d8SJed Brown     break;
1370c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1371c10200c1SHong Zhang     A->submat_singleis = flg;
1372c10200c1SHong Zhang     break;
1373071fcb05SBarry Smith   case MAT_SORTED_FULL:
1374071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1375071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1376071fcb05SBarry Smith     break;
13771a2c6b5cSJunchao Zhang   case MAT_FORM_EXPLICIT_TRANSPOSE:
13781a2c6b5cSJunchao Zhang     A->form_explicit_transpose = flg;
13791a2c6b5cSJunchao Zhang     break;
1380a65d3064SKris Buschelman   default:
1381e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1382a65d3064SKris Buschelman   }
13833a40ed3dSBarry Smith   PetscFunctionReturn(0);
138417ab2063SBarry Smith }
138517ab2063SBarry Smith 
1386dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
138717ab2063SBarry Smith {
1388416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
13896849ba73SBarry Smith   PetscErrorCode    ierr;
1390fdc842d1SBarry Smith   PetscInt          i,j,n,*ai=a->i,*aj=a->j;
1391c898d852SStefano Zampini   PetscScalar       *x;
1392c898d852SStefano Zampini   const PetscScalar *aa;
139317ab2063SBarry Smith 
13943a40ed3dSBarry Smith   PetscFunctionBegin;
1395d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1396e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1397c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1398d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1399d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1400fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
14012c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1402fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1403c898d852SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
140435e7444dSHong Zhang     PetscFunctionReturn(0);
140535e7444dSHong Zhang   }
140635e7444dSHong Zhang 
1407fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
140835e7444dSHong Zhang   for (i=0; i<n; i++) {
1409fdc842d1SBarry Smith     x[i] = 0.0;
141035e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
141135e7444dSHong Zhang       if (aj[j] == i) {
141235e7444dSHong Zhang         x[i] = aa[j];
141317ab2063SBarry Smith         break;
141417ab2063SBarry Smith       }
141517ab2063SBarry Smith     }
141617ab2063SBarry Smith   }
1417fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1418c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14193a40ed3dSBarry Smith   PetscFunctionReturn(0);
142017ab2063SBarry Smith }
142117ab2063SBarry Smith 
1422c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1423dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
142417ab2063SBarry Smith {
1425416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1426d9ca1df4SBarry Smith   PetscScalar       *y;
1427d9ca1df4SBarry Smith   const PetscScalar *x;
1428dfbe8321SBarry Smith   PetscErrorCode    ierr;
1429d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14305c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1431*fff043a9SJunchao Zhang   const MatScalar   *v,*aa;
1432a77337e4SBarry Smith   PetscScalar       alpha;
1433d9ca1df4SBarry Smith   PetscInt          n,i,j;
1434d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14353447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1436ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14375c897100SBarry Smith #endif
143817ab2063SBarry Smith 
14393a40ed3dSBarry Smith   PetscFunctionBegin;
14402e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1441d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14421ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1443*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
14445c897100SBarry Smith 
14455c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1446*fff043a9SJunchao Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,aa,y);
14475c897100SBarry Smith #else
14483447b6efSHong Zhang   if (usecprow) {
14493447b6efSHong Zhang     m    = cprow.nrows;
14503447b6efSHong Zhang     ii   = cprow.i;
14517b2bb3b9SHong Zhang     ridx = cprow.rindex;
14523447b6efSHong Zhang   } else {
14533447b6efSHong Zhang     ii = a->i;
14543447b6efSHong Zhang   }
145517ab2063SBarry Smith   for (i=0; i<m; i++) {
14563447b6efSHong Zhang     idx = a->j + ii[i];
1457*fff043a9SJunchao Zhang     v   = aa + ii[i];
14583447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14593447b6efSHong Zhang     if (usecprow) {
14607b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14613447b6efSHong Zhang     } else {
146217ab2063SBarry Smith       alpha = x[i];
14633447b6efSHong Zhang     }
146404fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
146517ab2063SBarry Smith   }
14665c897100SBarry Smith #endif
1467dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1468d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14691ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1470*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14713a40ed3dSBarry Smith   PetscFunctionReturn(0);
147217ab2063SBarry Smith }
147317ab2063SBarry Smith 
1474dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14755c897100SBarry Smith {
1476dfbe8321SBarry Smith   PetscErrorCode ierr;
14775c897100SBarry Smith 
14785c897100SBarry Smith   PetscFunctionBegin;
1479170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
14805c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
14815c897100SBarry Smith   PetscFunctionReturn(0);
14825c897100SBarry Smith }
14835c897100SBarry Smith 
1484c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
148578b84d54SShri Abhyankar 
1486dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
148717ab2063SBarry Smith {
1488416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1489d9fead3dSBarry Smith   PetscScalar       *y;
149054f21887SBarry Smith   const PetscScalar *x;
1491*fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1492dfbe8321SBarry Smith   PetscErrorCode    ierr;
1493003131ecSBarry Smith   PetscInt          m=A->rmap->n;
14940298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
14957b083b7cSBarry Smith   PetscInt          n,i;
1496362ced78SSatish Balay   PetscScalar       sum;
1497ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
149817ab2063SBarry Smith 
1499b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
150097952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1501fee21e36SBarry Smith #endif
1502fee21e36SBarry Smith 
15033a40ed3dSBarry Smith   PetscFunctionBegin;
1504b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1505b215bc84SStefano Zampini     ierr = MatMult_SeqAIJ_Inode(A,xx,yy);CHKERRQ(ierr);
1506b215bc84SStefano Zampini     PetscFunctionReturn(0);
1507b215bc84SStefano Zampini   }
1508*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
15093649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
15101ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1511416022c9SBarry Smith   ii   = a->i;
15124eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1513580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
151497952fefSHong Zhang     m    = a->compressedrow.nrows;
151597952fefSHong Zhang     ii   = a->compressedrow.i;
151697952fefSHong Zhang     ridx = a->compressedrow.rindex;
151797952fefSHong Zhang     for (i=0; i<m; i++) {
151897952fefSHong Zhang       n           = ii[i+1] - ii[i];
151997952fefSHong Zhang       aj          = a->j + ii[i];
1520*fff043a9SJunchao Zhang       aa          = a_a + ii[i];
152197952fefSHong Zhang       sum         = 0.0;
1522003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1523003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
152497952fefSHong Zhang       y[*ridx++] = sum;
152597952fefSHong Zhang     }
152697952fefSHong Zhang   } else { /* do not use compressed row format */
1527b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15283d3eaba7SBarry Smith     aj   = a->j;
1529*fff043a9SJunchao Zhang     aa   = a_a;
1530b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1531b05257ddSBarry Smith #else
153217ab2063SBarry Smith     for (i=0; i<m; i++) {
1533003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1534003131ecSBarry Smith       aj          = a->j + ii[i];
1535*fff043a9SJunchao Zhang       aa          = a_a + ii[i];
153617ab2063SBarry Smith       sum         = 0.0;
1537003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
153817ab2063SBarry Smith       y[i] = sum;
153917ab2063SBarry Smith     }
15408d195f9aSBarry Smith #endif
1541b05257ddSBarry Smith   }
15427b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
15433649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
15441ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1545*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
15463a40ed3dSBarry Smith   PetscFunctionReturn(0);
154717ab2063SBarry Smith }
154817ab2063SBarry Smith 
1549b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1550b434eb95SMatthew G. Knepley {
1551b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1552b434eb95SMatthew G. Knepley   PetscScalar       *y;
1553b434eb95SMatthew G. Knepley   const PetscScalar *x;
1554*fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1555b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1556b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1557b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1558b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1559b434eb95SMatthew G. Knepley   PetscScalar       sum;
1560b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1561b434eb95SMatthew G. Knepley 
1562b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1563b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1564b434eb95SMatthew G. Knepley #endif
1565b434eb95SMatthew G. Knepley 
1566b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1567*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
1568b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1569b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1570b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1571b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1572b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1573b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1574b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1575b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1576b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1577*fff043a9SJunchao Zhang       aa          = a_a + ii[i];
1578b434eb95SMatthew G. Knepley       sum         = 0.0;
1579b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1580b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1581b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1582b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1583b434eb95SMatthew G. Knepley     }
1584b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15853d3eaba7SBarry Smith     ii = a->i;
1586b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1587b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1588b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1589*fff043a9SJunchao Zhang       aa          = a_a + ii[i];
1590b434eb95SMatthew G. Knepley       sum         = 0.0;
1591b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1592b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1593b434eb95SMatthew G. Knepley       y[i] = sum;
1594b434eb95SMatthew G. Knepley     }
1595b434eb95SMatthew G. Knepley   }
1596b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1597b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1598b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1599*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
1600b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1601b434eb95SMatthew G. Knepley }
1602b434eb95SMatthew G. Knepley 
1603b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1604b434eb95SMatthew G. Knepley {
1605b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1606b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1607b434eb95SMatthew G. Knepley   const PetscScalar *x;
1608*fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1609b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1610b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1611b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1612b434eb95SMatthew G. Knepley   PetscScalar       sum;
1613b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1614b434eb95SMatthew G. Knepley 
1615b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1616*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
1617b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1618d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1619b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1620b434eb95SMatthew G. Knepley     if (zz != yy) {
1621580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1622b434eb95SMatthew G. Knepley     }
1623b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1624b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1625b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1626b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1627b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1628b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1629*fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1630b434eb95SMatthew G. Knepley       sum = y[*ridx];
1631b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1632b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1633b434eb95SMatthew G. Knepley     }
1634b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16353d3eaba7SBarry Smith     ii = a->i;
1636b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1637b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1638b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1639*fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1640b434eb95SMatthew G. Knepley       sum = y[i];
1641b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1642b434eb95SMatthew G. Knepley       z[i] = sum;
1643b434eb95SMatthew G. Knepley     }
1644b434eb95SMatthew G. Knepley   }
1645b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1646b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1647d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1648*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
1649b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1650b434eb95SMatthew G. Knepley }
1651b434eb95SMatthew G. Knepley 
1652c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1653dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
165417ab2063SBarry Smith {
1655416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1656f15663dcSBarry Smith   PetscScalar       *y,*z;
1657f15663dcSBarry Smith   const PetscScalar *x;
1658*fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1659dfbe8321SBarry Smith   PetscErrorCode    ierr;
1660d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1661d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1662362ced78SSatish Balay   PetscScalar       sum;
1663ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16649ea0dfa2SSatish Balay 
16653a40ed3dSBarry Smith   PetscFunctionBegin;
1666b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1667b215bc84SStefano Zampini     ierr = MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz);CHKERRQ(ierr);
1668b215bc84SStefano Zampini     PetscFunctionReturn(0);
1669b215bc84SStefano Zampini   }
1670*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
1671f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1672d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16734eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16744eb6d288SHong Zhang     if (zz != yy) {
1675580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
16764eb6d288SHong Zhang     }
167797952fefSHong Zhang     m    = a->compressedrow.nrows;
167897952fefSHong Zhang     ii   = a->compressedrow.i;
167997952fefSHong Zhang     ridx = a->compressedrow.rindex;
168097952fefSHong Zhang     for (i=0; i<m; i++) {
168197952fefSHong Zhang       n   = ii[i+1] - ii[i];
168297952fefSHong Zhang       aj  = a->j + ii[i];
1683*fff043a9SJunchao Zhang       aa  = a_a + ii[i];
168497952fefSHong Zhang       sum = y[*ridx];
1685f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
168697952fefSHong Zhang       z[*ridx++] = sum;
168797952fefSHong Zhang     }
168897952fefSHong Zhang   } else { /* do not use compressed row format */
16893d3eaba7SBarry Smith     ii = a->i;
1690f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
16913d3eaba7SBarry Smith     aj = a->j;
1692*fff043a9SJunchao Zhang     aa = a_a;
1693f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1694f15663dcSBarry Smith #else
169517ab2063SBarry Smith     for (i=0; i<m; i++) {
1696f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1697f15663dcSBarry Smith       aj  = a->j + ii[i];
1698*fff043a9SJunchao Zhang       aa  = a_a + ii[i];
169917ab2063SBarry Smith       sum = y[i];
1700f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
170117ab2063SBarry Smith       z[i] = sum;
170217ab2063SBarry Smith     }
170302ab625aSSatish Balay #endif
1704f15663dcSBarry Smith   }
1705dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1706f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1707d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1708*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
17093a40ed3dSBarry Smith   PetscFunctionReturn(0);
171017ab2063SBarry Smith }
171117ab2063SBarry Smith 
171217ab2063SBarry Smith /*
171317ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
171417ab2063SBarry Smith */
1715dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
171617ab2063SBarry Smith {
1717416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17186849ba73SBarry Smith   PetscErrorCode ierr;
1719d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
172017ab2063SBarry Smith 
17213a40ed3dSBarry Smith   PetscFunctionBegin;
172209f38230SBarry Smith   if (!a->diag) {
1723785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
17243bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
172509f38230SBarry Smith   }
1726d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
172709f38230SBarry Smith     a->diag[i] = a->i[i+1];
1728bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1729bfeeae90SHong Zhang       if (a->j[j] == i) {
173009f38230SBarry Smith         a->diag[i] = j;
173117ab2063SBarry Smith         break;
173217ab2063SBarry Smith       }
173317ab2063SBarry Smith     }
173417ab2063SBarry Smith   }
17353a40ed3dSBarry Smith   PetscFunctionReturn(0);
173617ab2063SBarry Smith }
173717ab2063SBarry Smith 
173861ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
173961ecd0c6SBarry Smith {
174061ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
174161ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
174261ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
174361ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
174461ecd0c6SBarry Smith   PetscErrorCode    ierr;
174561ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
174661ecd0c6SBarry Smith 
174761ecd0c6SBarry Smith   PetscFunctionBegin;
174861ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
174961ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
175061ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
175161ecd0c6SBarry Smith     PetscFunctionReturn(0);
175261ecd0c6SBarry Smith   }
175361ecd0c6SBarry Smith 
175461ecd0c6SBarry Smith   if (a->diagonaldense) {
175561ecd0c6SBarry Smith     cnt = 0;
175661ecd0c6SBarry Smith   } else {
175761ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
175861ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
175961ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
176061ecd0c6SBarry Smith         cnt++;
176161ecd0c6SBarry Smith         mdiag[i] = 1;
176261ecd0c6SBarry Smith       }
176361ecd0c6SBarry Smith     }
176461ecd0c6SBarry Smith   }
176561ecd0c6SBarry Smith   if (!cnt) {
176661ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
176761ecd0c6SBarry Smith   } else {
1768b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1769b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
177061ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
177161ecd0c6SBarry Smith 
177261ecd0c6SBarry Smith     a->a = NULL;
177361ecd0c6SBarry Smith     a->j = NULL;
177461ecd0c6SBarry Smith     a->i = NULL;
177561ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
177661ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
177761ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1778447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
177961ecd0c6SBarry Smith     }
178061ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
178161ecd0c6SBarry Smith 
178261ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
178361ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
178461ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1785447d62f5SStefano Zampini       if (i < A->cmap->n) {
178661ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
178761ecd0c6SBarry Smith       }
1788447d62f5SStefano Zampini     }
178961ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179061ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179161ecd0c6SBarry Smith     if (singlemalloc) {
179261ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
179361ecd0c6SBarry Smith     } else {
179461ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
179561ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
179661ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
179761ecd0c6SBarry Smith     }
179861ecd0c6SBarry Smith   }
179961ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
180061ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
180161ecd0c6SBarry Smith   PetscFunctionReturn(0);
180261ecd0c6SBarry Smith }
180361ecd0c6SBarry Smith 
1804be5855fcSBarry Smith /*
1805be5855fcSBarry Smith      Checks for missing diagonals
1806be5855fcSBarry Smith */
1807ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1808be5855fcSBarry Smith {
1809be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
18107734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1811994fe344SLisandro Dalcin   PetscErrorCode ierr;
1812be5855fcSBarry Smith 
1813be5855fcSBarry Smith   PetscFunctionBegin;
181409f38230SBarry Smith   *missing = PETSC_FALSE;
18157734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
181609f38230SBarry Smith     *missing = PETSC_TRUE;
181709f38230SBarry Smith     if (d) *d = 0;
1818994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
181909f38230SBarry Smith   } else {
182001445905SHong Zhang     PetscInt n;
182101445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1822f1e2ffcdSBarry Smith     diag = a->diag;
182301445905SHong Zhang     for (i=0; i<n; i++) {
18247734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
182509f38230SBarry Smith         *missing = PETSC_TRUE;
182609f38230SBarry Smith         if (d) *d = i;
1827994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1828358d2f5dSShri Abhyankar         break;
182909f38230SBarry Smith       }
1830be5855fcSBarry Smith     }
1831be5855fcSBarry Smith   }
1832be5855fcSBarry Smith   PetscFunctionReturn(0);
1833be5855fcSBarry Smith }
1834be5855fcSBarry Smith 
18350da83c2eSBarry Smith #include <petscblaslapack.h>
18360da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18370da83c2eSBarry Smith 
18380da83c2eSBarry Smith /*
18390da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18400da83c2eSBarry Smith */
18410da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18420da83c2eSBarry Smith {
18430da83c2eSBarry Smith   PetscErrorCode  ierr;
18440da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18450da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18460da83c2eSBarry Smith   const PetscReal shift = 0.0;
18470da83c2eSBarry Smith   PetscInt        ipvt[5];
18480da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18490da83c2eSBarry Smith 
18500da83c2eSBarry Smith   PetscFunctionBegin;
18510da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18520da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18530da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
18540da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18550da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18560da83c2eSBarry Smith   }
18570da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
18580da83c2eSBarry Smith   if (bsizemax > 7) {
18590da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
18600da83c2eSBarry Smith   }
18610da83c2eSBarry Smith   ncnt = 0;
18620da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18630da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18640da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
18650da83c2eSBarry Smith     switch (bsizes[i]) {
18660da83c2eSBarry Smith     case 1:
18670da83c2eSBarry Smith       *diag = 1.0/(*diag);
18680da83c2eSBarry Smith       break;
18690da83c2eSBarry Smith     case 2:
18700da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18710da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18720da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
18730da83c2eSBarry Smith       break;
18740da83c2eSBarry Smith     case 3:
18750da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18760da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18770da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
18780da83c2eSBarry Smith       break;
18790da83c2eSBarry Smith     case 4:
18800da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18810da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18820da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
18830da83c2eSBarry Smith       break;
18840da83c2eSBarry Smith     case 5:
18850da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18860da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18870da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
18880da83c2eSBarry Smith       break;
18890da83c2eSBarry Smith     case 6:
18900da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18910da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18920da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
18930da83c2eSBarry Smith       break;
18940da83c2eSBarry Smith     case 7:
18950da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18960da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18970da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
18980da83c2eSBarry Smith       break;
18990da83c2eSBarry Smith     default:
19000da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19010da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19020da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
19030da83c2eSBarry Smith     }
19040da83c2eSBarry Smith     ncnt   += bsizes[i];
19050da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
19060da83c2eSBarry Smith   }
19070da83c2eSBarry Smith   if (bsizemax > 7) {
19080da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
19090da83c2eSBarry Smith   }
19100da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
19110da83c2eSBarry Smith   PetscFunctionReturn(0);
19120da83c2eSBarry Smith }
19130da83c2eSBarry Smith 
1914422a814eSBarry Smith /*
1915422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1916422a814eSBarry Smith */
19177087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
191871f1c65dSBarry Smith {
191971f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
192071f1c65dSBarry Smith   PetscErrorCode  ierr;
1921d0f46423SBarry Smith   PetscInt        i,*diag,m = A->rmap->n;
19222e5835c6SStefano Zampini   const MatScalar *v;
192354f21887SBarry Smith   PetscScalar     *idiag,*mdiag;
192471f1c65dSBarry Smith 
192571f1c65dSBarry Smith   PetscFunctionBegin;
192671f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
192771f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
192871f1c65dSBarry Smith   diag = a->diag;
192971f1c65dSBarry Smith   if (!a->idiag) {
1930dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
19313bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar));CHKERRQ(ierr);
193271f1c65dSBarry Smith   }
19332e5835c6SStefano Zampini 
193471f1c65dSBarry Smith   mdiag = a->mdiag;
193571f1c65dSBarry Smith   idiag = a->idiag;
19362e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
1937422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
193871f1c65dSBarry Smith     for (i=0; i<m; i++) {
193971f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1940899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1941899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1942899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
19437b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19447b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19457b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1946a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1947899639b0SHong Zhang       }
194871f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
194971f1c65dSBarry Smith     }
195071f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
195171f1c65dSBarry Smith   } else {
195271f1c65dSBarry Smith     for (i=0; i<m; i++) {
195371f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
195471f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
195571f1c65dSBarry Smith     }
1956dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
195771f1c65dSBarry Smith   }
195871f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
19592e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
196071f1c65dSBarry Smith   PetscFunctionReturn(0);
196171f1c65dSBarry Smith }
196271f1c65dSBarry Smith 
1963c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
196441f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
196517ab2063SBarry Smith {
1966416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1967e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
19682e5835c6SStefano Zampini   const MatScalar   *v,*idiag=NULL,*mdiag,*aa;
196954f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1970dfbe8321SBarry Smith   PetscErrorCode    ierr;
19713d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
197297f1f81fSBarry Smith   const PetscInt    *idx,*diag;
197317ab2063SBarry Smith 
19743a40ed3dSBarry Smith   PetscFunctionBegin;
1975b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
1976b215bc84SStefano Zampini     ierr = MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx);CHKERRQ(ierr);
1977b215bc84SStefano Zampini     PetscFunctionReturn(0);
1978b215bc84SStefano Zampini   }
1979b965ef7fSBarry Smith   its = its*lits;
198091723122SBarry Smith 
198171f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
198271f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
198371f1c65dSBarry Smith   a->fshift = fshift;
198471f1c65dSBarry Smith   a->omega  = omega;
1985ed480e8bSBarry Smith 
198671f1c65dSBarry Smith   diag  = a->diag;
198771f1c65dSBarry Smith   t     = a->ssor_work;
1988ed480e8bSBarry Smith   idiag = a->idiag;
198971f1c65dSBarry Smith   mdiag = a->mdiag;
1990ed480e8bSBarry Smith 
19912e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
19921ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
19933649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
1994ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
199517ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
199617ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1997ed480e8bSBarry Smith     bs = b;
199817ab2063SBarry Smith     for (i=0; i<m; i++) {
199971f1c65dSBarry Smith       d   = fshift + mdiag[i];
2000416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2001ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20022e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
200317ab2063SBarry Smith       sum = b[i]*d/omega;
2004003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
200517ab2063SBarry Smith       x[i] = sum;
200617ab2063SBarry Smith     }
20071ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20083649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20092e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2010efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20113a40ed3dSBarry Smith     PetscFunctionReturn(0);
201217ab2063SBarry Smith   }
2013c783ea89SBarry Smith 
20142205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
20152205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
20164c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
2017887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
201817ab2063SBarry Smith 
201917ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
202017ab2063SBarry Smith 
2021887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
202217ab2063SBarry Smith     */
202317ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
202417ab2063SBarry Smith 
202517ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
202617ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
2027416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2028ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20292e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
203017ab2063SBarry Smith       sum = b[i];
2031e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
2032ed480e8bSBarry Smith       x[i] = sum*idiag[i];
203317ab2063SBarry Smith     }
203417ab2063SBarry Smith 
203517ab2063SBarry Smith     /*  t = b - (2*E - D)x */
20362e5835c6SStefano Zampini     v = aa;
20372205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
203817ab2063SBarry Smith 
203917ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2040ed480e8bSBarry Smith     ts   = t;
2041416022c9SBarry Smith     diag = a->diag;
204217ab2063SBarry Smith     for (i=0; i<m; i++) {
2043416022c9SBarry Smith       n   = diag[i] - a->i[i];
2044ed480e8bSBarry Smith       idx = a->j + a->i[i];
20452e5835c6SStefano Zampini       v   = aa + a->i[i];
204617ab2063SBarry Smith       sum = t[i];
2047003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2048ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2049733d66baSBarry Smith       /*  x = x + t */
2050733d66baSBarry Smith       x[i] += t[i];
205117ab2063SBarry Smith     }
205217ab2063SBarry Smith 
2053dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
20541ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20553649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20563a40ed3dSBarry Smith     PetscFunctionReturn(0);
205717ab2063SBarry Smith   }
205817ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
205917ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
206017ab2063SBarry Smith       for (i=0; i<m; i++) {
2061416022c9SBarry Smith         n   = diag[i] - a->i[i];
2062ed480e8bSBarry Smith         idx = a->j + a->i[i];
20632e5835c6SStefano Zampini         v   = aa + a->i[i];
206417ab2063SBarry Smith         sum = b[i];
2065e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20665c99c7daSBarry Smith         t[i] = sum;
2067ed480e8bSBarry Smith         x[i] = sum*idiag[i];
206817ab2063SBarry Smith       }
20695c99c7daSBarry Smith       xb   = t;
2070efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20713a40ed3dSBarry Smith     } else xb = b;
207217ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
207317ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2074416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2075ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
20762e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
207717ab2063SBarry Smith         sum = xb[i];
2078e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20795c99c7daSBarry Smith         if (xb == b) {
2080ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20815c99c7daSBarry Smith         } else {
2082b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
208317ab2063SBarry Smith         }
20845c99c7daSBarry Smith       }
2085b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
208617ab2063SBarry Smith     }
208717ab2063SBarry Smith     its--;
208817ab2063SBarry Smith   }
208917ab2063SBarry Smith   while (its--) {
209017ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
209117ab2063SBarry Smith       for (i=0; i<m; i++) {
2092b19a5dc2SMark Adams         /* lower */
2093b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2094ed480e8bSBarry Smith         idx = a->j + a->i[i];
20952e5835c6SStefano Zampini         v   = aa + a->i[i];
209617ab2063SBarry Smith         sum = b[i];
2097e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2098b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2099b19a5dc2SMark Adams         /* upper */
2100b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2101b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
21022e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
2103b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2104b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
210517ab2063SBarry Smith       }
2106b19a5dc2SMark Adams       xb   = t;
21079f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2108b19a5dc2SMark Adams     } else xb = b;
210917ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
211017ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2111b19a5dc2SMark Adams         sum = xb[i];
2112b19a5dc2SMark Adams         if (xb == b) {
2113b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2114416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2115ed480e8bSBarry Smith           idx = a->j + a->i[i];
21162e5835c6SStefano Zampini           v   = aa + a->i[i];
2117e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2118ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2119b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2120b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2121b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
21222e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2123b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2124b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
212517ab2063SBarry Smith         }
2126b19a5dc2SMark Adams       }
2127b19a5dc2SMark Adams       if (xb == b) {
21289f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2129b19a5dc2SMark Adams       } else {
2130b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
2131b19a5dc2SMark Adams       }
213217ab2063SBarry Smith     }
213317ab2063SBarry Smith   }
21342e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
21351ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
21363649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
2137365a8a9eSBarry Smith   PetscFunctionReturn(0);
213817ab2063SBarry Smith }
213917ab2063SBarry Smith 
2140dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
214117ab2063SBarry Smith {
2142416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21434e220ebcSLois Curfman McInnes 
21443a40ed3dSBarry Smith   PetscFunctionBegin;
21454e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21463966268fSBarry Smith   info->nz_allocated = a->maxnz;
21473966268fSBarry Smith   info->nz_used      = a->nz;
21483966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21493966268fSBarry Smith   info->assemblies   = A->num_ass;
21503966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21517adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2152d5f3da31SBarry Smith   if (A->factortype) {
21534e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21544e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21554e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21564e220ebcSLois Curfman McInnes   } else {
21574e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21584e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21594e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21604e220ebcSLois Curfman McInnes   }
21613a40ed3dSBarry Smith   PetscFunctionReturn(0);
216217ab2063SBarry Smith }
216317ab2063SBarry Smith 
21642b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
216517ab2063SBarry Smith {
2166416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2167c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
21686849ba73SBarry Smith   PetscErrorCode    ierr;
216997b48c8fSBarry Smith   const PetscScalar *xx;
21702e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
2171c7da8527SEric Chamberland   PetscInt          d = 0;
217217ab2063SBarry Smith 
21733a40ed3dSBarry Smith   PetscFunctionBegin;
217497b48c8fSBarry Smith   if (x && b) {
217597b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
217697b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
217797b48c8fSBarry Smith     for (i=0; i<N; i++) {
217897b48c8fSBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2179447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
218097b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
218197b48c8fSBarry Smith     }
218297b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
218397b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
218497b48c8fSBarry Smith   }
218597b48c8fSBarry Smith 
21862e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
2187a9817697SBarry Smith   if (a->keepnonzeropattern) {
2188f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
2189e32f2f54SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
21902e5835c6SStefano Zampini       ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2191f1e2ffcdSBarry Smith     }
2192f4df32b1SMatthew Knepley     if (diag != 0.0) {
2193c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2194c7da8527SEric Chamberland         d = rows[i];
2195447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2196c7da8527SEric 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);
2197c7da8527SEric Chamberland       }
2198f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2199447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
22002e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
2201f1e2ffcdSBarry Smith       }
2202f1e2ffcdSBarry Smith     }
2203f1e2ffcdSBarry Smith   } else {
2204f4df32b1SMatthew Knepley     if (diag != 0.0) {
220517ab2063SBarry Smith       for (i=0; i<N; i++) {
2206e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22077ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2208447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2209447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2210447d62f5SStefano Zampini           } else {
2211416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
22122e5835c6SStefano Zampini             aa[a->i[rows[i]]]   = diag;
2213bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2214447d62f5SStefano Zampini           }
2215447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2216f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
221717ab2063SBarry Smith         }
221817ab2063SBarry Smith       }
22193a40ed3dSBarry Smith     } else {
222017ab2063SBarry Smith       for (i=0; i<N; i++) {
2221e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2222416022c9SBarry Smith         a->ilen[rows[i]] = 0;
222317ab2063SBarry Smith       }
222417ab2063SBarry Smith     }
2225e56f5c9eSBarry Smith     A->nonzerostate++;
2226f1e2ffcdSBarry Smith   }
22272e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
22284099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22293a40ed3dSBarry Smith   PetscFunctionReturn(0);
223017ab2063SBarry Smith }
223117ab2063SBarry Smith 
22326e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
22336e169961SBarry Smith {
22346e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
22356e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
22366e169961SBarry Smith   PetscErrorCode    ierr;
22372b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
22386e169961SBarry Smith   const PetscScalar *xx;
22392e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
22406e169961SBarry Smith 
22416e169961SBarry Smith   PetscFunctionBegin;
22422e5835c6SStefano Zampini   if (!N) PetscFunctionReturn(0);
22432e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
22446e169961SBarry Smith   if (x && b) {
22456e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
22466e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
22472b40b63fSBarry Smith     vecs = PETSC_TRUE;
22486e169961SBarry Smith   }
22491795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
22506e169961SBarry Smith   for (i=0; i<N; i++) {
22516e169961SBarry Smith     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22522e5835c6SStefano Zampini     ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
22532205254eSKarl Rupp 
22546e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22556e169961SBarry Smith   }
22566e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22576e169961SBarry Smith     if (!zeroed[i]) {
22586e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22594cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22602e5835c6SStefano Zampini           if (vecs) bb[i] -= aa[j]*xx[a->j[j]];
22612e5835c6SStefano Zampini           aa[j] = 0.0;
22626e169961SBarry Smith         }
22636e169961SBarry Smith       }
22644cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22656e169961SBarry Smith   }
22666e169961SBarry Smith   if (x && b) {
22676e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
22686e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
22696e169961SBarry Smith   }
22706e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
22716e169961SBarry Smith   if (diag != 0.0) {
22726e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
22731d5a398dSstefano_zampini     if (missing) {
22741d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22754cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
22764cf107fdSStefano 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]);
22771d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
22781d5a398dSstefano_zampini       }
22791d5a398dSstefano_zampini     } else {
22806e169961SBarry Smith       for (i=0; i<N; i++) {
22812e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
22826e169961SBarry Smith       }
22836e169961SBarry Smith     }
22841d5a398dSstefano_zampini   }
22852e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
22864099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22876e169961SBarry Smith   PetscFunctionReturn(0);
22886e169961SBarry Smith }
22896e169961SBarry Smith 
2290a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
229117ab2063SBarry Smith {
22922e5835c6SStefano Zampini   PetscErrorCode  ierr;
2293*fff043a9SJunchao Zhang   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2294*fff043a9SJunchao Zhang   const PetscScalar *aa;
2295*fff043a9SJunchao Zhang   PetscInt          *itmp;
229617ab2063SBarry Smith 
22973a40ed3dSBarry Smith   PetscFunctionBegin;
22982e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
2299416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
23002e5835c6SStefano Zampini   if (v) *v = (PetscScalar*)(aa + a->i[row]);
230117ab2063SBarry Smith   if (idx) {
2302bfeeae90SHong Zhang     itmp = a->j + a->i[row];
230326fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2304f4259b30SLisandro Dalcin     else *idx = NULL;
230517ab2063SBarry Smith   }
23062e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
23073a40ed3dSBarry Smith   PetscFunctionReturn(0);
230817ab2063SBarry Smith }
230917ab2063SBarry Smith 
2310a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
231117ab2063SBarry Smith {
23123a40ed3dSBarry Smith   PetscFunctionBegin;
2313cb4a9cd9SHong Zhang   if (nz)  *nz = 0;
23142e5835c6SStefano Zampini   if (idx) *idx = NULL;
23152e5835c6SStefano Zampini   if (v)   *v = NULL;
23163a40ed3dSBarry Smith   PetscFunctionReturn(0);
231717ab2063SBarry Smith }
231817ab2063SBarry Smith 
2319dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
232017ab2063SBarry Smith {
2321416022c9SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
23222e5835c6SStefano Zampini   const MatScalar *v;
232336db0b34SBarry Smith   PetscReal       sum = 0.0;
23246849ba73SBarry Smith   PetscErrorCode  ierr;
232597f1f81fSBarry Smith   PetscInt        i,j;
232617ab2063SBarry Smith 
23273a40ed3dSBarry Smith   PetscFunctionBegin;
23282e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
232917ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2330570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2331570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
233273cf7048SBarry Smith     PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one));
2333570b7f6dSBarry Smith #else
2334416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
233536db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
233617ab2063SBarry Smith     }
23378f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2338570b7f6dSBarry Smith #endif
2339ca0c957dSBarry Smith     ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
23403a40ed3dSBarry Smith   } else if (type == NORM_1) {
234136db0b34SBarry Smith     PetscReal *tmp;
234297f1f81fSBarry Smith     PetscInt  *jj = a->j;
23431795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2344064f8208SBarry Smith     *nrm = 0.0;
2345416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2346bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
234717ab2063SBarry Smith     }
2348d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2349064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
235017ab2063SBarry Smith     }
2351606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
235251f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
23533a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2354064f8208SBarry Smith     *nrm = 0.0;
2355d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
23562e5835c6SStefano Zampini       const PetscScalar *v2 = v + a->i[j];
235717ab2063SBarry Smith       sum = 0.0;
2358416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
23592e5835c6SStefano Zampini         sum += PetscAbsScalar(*v2); v2++;
236017ab2063SBarry Smith       }
2361064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
236217ab2063SBarry Smith     }
236351f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2364f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
23652e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
23663a40ed3dSBarry Smith   PetscFunctionReturn(0);
236717ab2063SBarry Smith }
236817ab2063SBarry Smith 
23694e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
23704e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
23714e938277SHong Zhang {
23724e938277SHong Zhang   PetscErrorCode ierr;
23734e938277SHong Zhang   PetscInt       i,j,anzj;
23744e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
23754e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
23764e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
23774e938277SHong Zhang 
23784e938277SHong Zhang   PetscFunctionBegin;
23794e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2380854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2381785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2382785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
23834e938277SHong Zhang 
23844e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
23854e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
238626fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
23874e938277SHong Zhang   /* Form ati for csr format of A^T. */
238826fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
23894e938277SHong Zhang 
23904e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2391580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
23924e938277SHong Zhang 
23934e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
23944e938277SHong Zhang   for (i=0;i<am;i++) {
23954e938277SHong Zhang     anzj = ai[i+1] - ai[i];
23964e938277SHong Zhang     for (j=0;j<anzj;j++) {
23974e938277SHong Zhang       atj[atfill[*aj]] = i;
23984e938277SHong Zhang       atfill[*aj++]   += 1;
23994e938277SHong Zhang     }
24004e938277SHong Zhang   }
24014e938277SHong Zhang 
24024e938277SHong Zhang   /* Clean up temporary space and complete requests. */
24034e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2404ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
240533d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2406b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2407a2f3521dSMark F. Adams 
24084e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
24094e938277SHong Zhang   b->free_a  = PETSC_FALSE;
24104e938277SHong Zhang   b->free_ij = PETSC_TRUE;
24114e938277SHong Zhang   b->nonew   = 0;
24124e938277SHong Zhang   PetscFunctionReturn(0);
24134e938277SHong Zhang }
24144e938277SHong Zhang 
24157087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2416cd0d46ebSvictorle {
24173d3eaba7SBarry Smith   Mat_SeqAIJ      *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
241854f21887SBarry Smith   PetscInt        *adx,*bdx,*aii,*bii,*aptr,*bptr;
24192e5835c6SStefano Zampini   const MatScalar *va,*vb;
24206849ba73SBarry Smith   PetscErrorCode  ierr;
242197f1f81fSBarry Smith   PetscInt        ma,na,mb,nb, i;
2422cd0d46ebSvictorle 
2423cd0d46ebSvictorle   PetscFunctionBegin;
2424cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2425cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24265485867bSBarry Smith   if (ma!=nb || na!=mb) {
24275485867bSBarry Smith     *f = PETSC_FALSE;
24285485867bSBarry Smith     PetscFunctionReturn(0);
24295485867bSBarry Smith   }
24302e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&va);CHKERRQ(ierr);
24312e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(B,&vb);CHKERRQ(ierr);
2432cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2433cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2434785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2435785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2436cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2437cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2438cd0d46ebSvictorle 
2439cd0d46ebSvictorle   *f = PETSC_TRUE;
2440cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2441cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
244297f1f81fSBarry Smith       PetscInt    idc,idr;
24435485867bSBarry Smith       PetscScalar vc,vr;
2444cd0d46ebSvictorle       /* column/row index/value */
24455485867bSBarry Smith       idc = adx[aptr[i]];
24465485867bSBarry Smith       idr = bdx[bptr[idc]];
24475485867bSBarry Smith       vc  = va[aptr[i]];
24485485867bSBarry Smith       vr  = vb[bptr[idc]];
24495485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24505485867bSBarry Smith         *f = PETSC_FALSE;
24515485867bSBarry Smith         goto done;
2452cd0d46ebSvictorle       } else {
24535485867bSBarry Smith         aptr[i]++;
24545485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2455cd0d46ebSvictorle       }
2456cd0d46ebSvictorle     }
2457cd0d46ebSvictorle   }
2458cd0d46ebSvictorle done:
2459cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
24603aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
24612e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&va);CHKERRQ(ierr);
24622e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(B,&vb);CHKERRQ(ierr);
2463cd0d46ebSvictorle   PetscFunctionReturn(0);
2464cd0d46ebSvictorle }
2465cd0d46ebSvictorle 
24667087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
24671cbb95d3SBarry Smith {
24683d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
246954f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
247054f21887SBarry Smith   MatScalar      *va,*vb;
24711cbb95d3SBarry Smith   PetscErrorCode ierr;
24721cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
24731cbb95d3SBarry Smith 
24741cbb95d3SBarry Smith   PetscFunctionBegin;
24751cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
24761cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24771cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
24781cbb95d3SBarry Smith     *f = PETSC_FALSE;
24791cbb95d3SBarry Smith     PetscFunctionReturn(0);
24801cbb95d3SBarry Smith   }
24811cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
24821cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
24831cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2484785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2485785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
24861cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
24871cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
24881cbb95d3SBarry Smith 
24891cbb95d3SBarry Smith   *f = PETSC_TRUE;
24901cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
24911cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
24921cbb95d3SBarry Smith       PetscInt    idc,idr;
24931cbb95d3SBarry Smith       PetscScalar vc,vr;
24941cbb95d3SBarry Smith       /* column/row index/value */
24951cbb95d3SBarry Smith       idc = adx[aptr[i]];
24961cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
24971cbb95d3SBarry Smith       vc  = va[aptr[i]];
24981cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
24991cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
25001cbb95d3SBarry Smith         *f = PETSC_FALSE;
25011cbb95d3SBarry Smith         goto done;
25021cbb95d3SBarry Smith       } else {
25031cbb95d3SBarry Smith         aptr[i]++;
25041cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
25051cbb95d3SBarry Smith       }
25061cbb95d3SBarry Smith     }
25071cbb95d3SBarry Smith   }
25081cbb95d3SBarry Smith done:
25091cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
25101cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
25111cbb95d3SBarry Smith   PetscFunctionReturn(0);
25121cbb95d3SBarry Smith }
25131cbb95d3SBarry Smith 
2514ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25159e29f15eSvictorle {
2516dfbe8321SBarry Smith   PetscErrorCode ierr;
25176e111a19SKarl Rupp 
25189e29f15eSvictorle   PetscFunctionBegin;
25195485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25209e29f15eSvictorle   PetscFunctionReturn(0);
25219e29f15eSvictorle }
25229e29f15eSvictorle 
2523ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25241cbb95d3SBarry Smith {
25251cbb95d3SBarry Smith   PetscErrorCode ierr;
25266e111a19SKarl Rupp 
25271cbb95d3SBarry Smith   PetscFunctionBegin;
25281cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25291cbb95d3SBarry Smith   PetscFunctionReturn(0);
25301cbb95d3SBarry Smith }
25311cbb95d3SBarry Smith 
2532dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
253317ab2063SBarry Smith {
2534416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2535fff8e43fSBarry Smith   const PetscScalar *l,*r;
2536fff8e43fSBarry Smith   PetscScalar       x;
253754f21887SBarry Smith   MatScalar         *v;
2538dfbe8321SBarry Smith   PetscErrorCode    ierr;
2539fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2540fff8e43fSBarry Smith   const PetscInt    *jj;
254117ab2063SBarry Smith 
25423a40ed3dSBarry Smith   PetscFunctionBegin;
254317ab2063SBarry Smith   if (ll) {
25443ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
25453ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2546e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
2547e32f2f54SBarry Smith     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2548fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
25492e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
255017ab2063SBarry Smith     for (i=0; i<m; i++) {
255117ab2063SBarry Smith       x = l[i];
2552416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25532205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
255417ab2063SBarry Smith     }
2555fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2556efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
25572e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
255817ab2063SBarry Smith   }
255917ab2063SBarry Smith   if (rr) {
2560e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
2561e32f2f54SBarry Smith     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2562fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
25632e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
25642e5835c6SStefano Zampini     jj = a->j;
25652205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
25662e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
2567fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2568efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
256917ab2063SBarry Smith   }
2570acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
25713a40ed3dSBarry Smith   PetscFunctionReturn(0);
257217ab2063SBarry Smith }
257317ab2063SBarry Smith 
25747dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
257517ab2063SBarry Smith {
2576db02288aSLois Curfman McInnes   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*c;
25776849ba73SBarry Smith   PetscErrorCode    ierr;
2578d0f46423SBarry Smith   PetscInt          *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
257997f1f81fSBarry Smith   PetscInt          row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
25805d0c19d7SBarry Smith   const PetscInt    *irow,*icol;
25812e5835c6SStefano Zampini   const PetscScalar *aa;
25825d0c19d7SBarry Smith   PetscInt          nrows,ncols;
258397f1f81fSBarry Smith   PetscInt          *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
258454f21887SBarry Smith   MatScalar         *a_new,*mat_a;
2585416022c9SBarry Smith   Mat               C;
2586cdc6f3adSToby Isaac   PetscBool         stride;
258717ab2063SBarry Smith 
25883a40ed3dSBarry Smith   PetscFunctionBegin;
258917ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2590b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2591b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
259217ab2063SBarry Smith 
2593251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2594ff718158SBarry Smith   if (stride) {
2595ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2596ff718158SBarry Smith   } else {
2597ff718158SBarry Smith     first = 0;
2598ff718158SBarry Smith     step  = 0;
2599ff718158SBarry Smith   }
2600fee21e36SBarry Smith   if (stride && step == 1) {
260102834360SBarry Smith     /* special case of contiguous rows */
2602dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
260302834360SBarry Smith     /* loop over new rows determining lens and starting points */
260402834360SBarry Smith     for (i=0; i<nrows; i++) {
2605bfeeae90SHong Zhang       kstart = ai[irow[i]];
2606a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2607a91a9bebSLisandro Dalcin       starts[i] = kstart;
260802834360SBarry Smith       for (k=kstart; k<kend; k++) {
2609bfeeae90SHong Zhang         if (aj[k] >= first) {
261002834360SBarry Smith           starts[i] = k;
261102834360SBarry Smith           break;
261202834360SBarry Smith         }
261302834360SBarry Smith       }
2614a2744918SBarry Smith       sum = 0;
261502834360SBarry Smith       while (k < kend) {
2616bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2617a2744918SBarry Smith         sum++;
261802834360SBarry Smith       }
2619a2744918SBarry Smith       lens[i] = sum;
262002834360SBarry Smith     }
262102834360SBarry Smith     /* create submatrix */
2622cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
262397f1f81fSBarry Smith       PetscInt n_cols,n_rows;
262408480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2625e32f2f54SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2626d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
262708480c60SBarry Smith       C    = *B;
26283a40ed3dSBarry Smith     } else {
26293bef6203SJed Brown       PetscInt rbs,cbs;
2630ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2631f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26323bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26333bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26343bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26357adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2636ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
263708480c60SBarry Smith     }
2638db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2639db02288aSLois Curfman McInnes 
264002834360SBarry Smith     /* loop over rows inserting into submatrix */
2641db02288aSLois Curfman McInnes     a_new = c->a;
2642db02288aSLois Curfman McInnes     j_new = c->j;
2643db02288aSLois Curfman McInnes     i_new = c->i;
26442e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
264502834360SBarry Smith     for (i=0; i<nrows; i++) {
2646a2744918SBarry Smith       ii    = starts[i];
2647a2744918SBarry Smith       lensi = lens[i];
2648a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2649a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
265002834360SBarry Smith       }
26512e5835c6SStefano Zampini       ierr       = PetscArraycpy(a_new,aa + starts[i],lensi);CHKERRQ(ierr);
2652a2744918SBarry Smith       a_new     += lensi;
2653a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2654a2744918SBarry Smith       c->ilen[i] = lensi;
265502834360SBarry Smith     }
26562e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
26570e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
26583a40ed3dSBarry Smith   } else {
265902834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
26601795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2661854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
26624dcab191SBarry Smith     for (i=0; i<ncols; i++) {
2663d9ef940eSSatish 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);
26644dcab191SBarry Smith       smap[icol[i]] = i+1;
26654dcab191SBarry Smith     }
26664dcab191SBarry Smith 
266702834360SBarry Smith     /* determine lens of each row */
266802834360SBarry Smith     for (i=0; i<nrows; i++) {
2669bfeeae90SHong Zhang       kstart  = ai[irow[i]];
267002834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
267102834360SBarry Smith       lens[i] = 0;
267202834360SBarry Smith       for (k=kstart; k<kend; k++) {
2673bfeeae90SHong Zhang         if (smap[aj[k]]) {
267402834360SBarry Smith           lens[i]++;
267502834360SBarry Smith         }
267602834360SBarry Smith       }
267702834360SBarry Smith     }
267817ab2063SBarry Smith     /* Create and fill new matrix */
2679a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2680ace3abfcSBarry Smith       PetscBool equal;
26810f5bd95cSBarry Smith 
268299141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2683e32f2f54SBarry Smith       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2684580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
2685f23aa3ddSBarry Smith       if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2686580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
268708480c60SBarry Smith       C    = *B;
26883a40ed3dSBarry Smith     } else {
26893bef6203SJed Brown       PetscInt rbs,cbs;
2690ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2691f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26923bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26933bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26943bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26957adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2696ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
269708480c60SBarry Smith     }
26982e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
269999141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
270017ab2063SBarry Smith     for (i=0; i<nrows; i++) {
270199141d43SSatish Balay       row      = irow[i];
2702bfeeae90SHong Zhang       kstart   = ai[row];
270399141d43SSatish Balay       kend     = kstart + a->ilen[row];
2704bfeeae90SHong Zhang       mat_i    = c->i[i];
270599141d43SSatish Balay       mat_j    = c->j + mat_i;
270699141d43SSatish Balay       mat_a    = c->a + mat_i;
270799141d43SSatish Balay       mat_ilen = c->ilen + i;
270817ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2709bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2710ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
27112e5835c6SStefano Zampini           *mat_a++ = aa[k];
271299141d43SSatish Balay           (*mat_ilen)++;
271399141d43SSatish Balay 
271417ab2063SBarry Smith         }
271517ab2063SBarry Smith       }
271617ab2063SBarry Smith     }
27172e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
271802834360SBarry Smith     /* Free work space */
271902834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2720606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2721606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2722cdc6f3adSToby Isaac     /* sort */
2723cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2724cdc6f3adSToby Isaac       PetscInt ilen;
2725cdc6f3adSToby Isaac 
2726cdc6f3adSToby Isaac       mat_i = c->i[i];
2727cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2728cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2729cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2730390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2731cdc6f3adSToby Isaac     }
273202834360SBarry Smith   }
27338c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2734b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr);
2735305c6ccfSStefano Zampini #endif
27366d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27376d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
273817ab2063SBarry Smith 
273917ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2740416022c9SBarry Smith   *B   = C;
27413a40ed3dSBarry Smith   PetscFunctionReturn(0);
274217ab2063SBarry Smith }
274317ab2063SBarry Smith 
2744fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
274582d44351SHong Zhang {
274682d44351SHong Zhang   PetscErrorCode ierr;
274782d44351SHong Zhang   Mat            B;
274882d44351SHong Zhang 
274982d44351SHong Zhang   PetscFunctionBegin;
2750c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
275182d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
275282d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
275333d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
275482d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
275582d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
275682d44351SHong Zhang     *subMat = B;
2757c2d650bdSHong Zhang   } else {
2758c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2759c2d650bdSHong Zhang   }
276082d44351SHong Zhang   PetscFunctionReturn(0);
276182d44351SHong Zhang }
276282d44351SHong Zhang 
27639a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2764a871dcd8SBarry Smith {
276563b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2766dfbe8321SBarry Smith   PetscErrorCode ierr;
276763b91edcSBarry Smith   Mat            outA;
2768ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
276963b91edcSBarry Smith 
27703a40ed3dSBarry Smith   PetscFunctionBegin;
2771e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
27721df811f5SHong Zhang 
2773b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2774b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2775a871dcd8SBarry Smith 
277663b91edcSBarry Smith   outA             = inA;
2777d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2778f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2779f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
27802205254eSKarl Rupp 
2781c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
27826bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
27832205254eSKarl Rupp 
2784c3122656SLisandro Dalcin   a->row = row;
27852205254eSKarl Rupp 
2786c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
27876bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
27882205254eSKarl Rupp 
2789c3122656SLisandro Dalcin   a->col = col;
279063b91edcSBarry Smith 
279136db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
27926bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
27934c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
27943bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2795f0ec6fceSSatish Balay 
279694a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2797854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
27983bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
279994a9d846SBarry Smith   }
280063b91edcSBarry Smith 
2801f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2802137fb511SHong Zhang   if (row_identity && col_identity) {
2803ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2804137fb511SHong Zhang   } else {
2805719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2806137fb511SHong Zhang   }
28073a40ed3dSBarry Smith   PetscFunctionReturn(0);
2808a871dcd8SBarry Smith }
2809a871dcd8SBarry Smith 
2810f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2811f0b747eeSBarry Smith {
2812f0b747eeSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2813dfa0f9e5SStefano Zampini   PetscScalar    *v;
2814efee365bSSatish Balay   PetscErrorCode ierr;
2815c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
28163a40ed3dSBarry Smith 
28173a40ed3dSBarry Smith   PetscFunctionBegin;
2818dfa0f9e5SStefano Zampini   ierr = MatSeqAIJGetArray(inA,&v);CHKERRQ(ierr);
2819c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
2820dfa0f9e5SStefano Zampini   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&alpha,v,&one));
2821efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2822dfa0f9e5SStefano Zampini   ierr = MatSeqAIJRestoreArray(inA,&v);CHKERRQ(ierr);
2823acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
28243a40ed3dSBarry Smith   PetscFunctionReturn(0);
2825f0b747eeSBarry Smith }
2826f0b747eeSBarry Smith 
2827f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
282816b64355SHong Zhang {
282916b64355SHong Zhang   PetscErrorCode ierr;
283016b64355SHong Zhang   PetscInt       i;
283116b64355SHong Zhang 
283216b64355SHong Zhang   PetscFunctionBegin;
283316b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
283416b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
283516b64355SHong Zhang 
283616b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
283716b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
283816b64355SHong Zhang     }
283916b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
284016b64355SHong Zhang 
284116b64355SHong Zhang     if (submatj->rbuf1) {
284216b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
284316b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
284416b64355SHong Zhang     }
284516b64355SHong Zhang 
284616b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
284716b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
284816b64355SHong Zhang     }
284916b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
285016b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
285116b64355SHong Zhang   }
285216b64355SHong Zhang 
285316b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
285416b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
285516b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
285616b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
285716b64355SHong Zhang #else
285816b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
285916b64355SHong Zhang #endif
286016b64355SHong Zhang 
286116b64355SHong Zhang   if (!submatj->allcolumns) {
286216b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
286316b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
286416b64355SHong Zhang #else
286516b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
286616b64355SHong Zhang #endif
286716b64355SHong Zhang   }
286816b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
286916b64355SHong Zhang 
287016b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
287116b64355SHong Zhang   PetscFunctionReturn(0);
287216b64355SHong Zhang }
287316b64355SHong Zhang 
28740fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
287516b64355SHong Zhang {
287616b64355SHong Zhang   PetscErrorCode ierr;
287716b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
28785c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
287916b64355SHong Zhang 
288016b64355SHong Zhang   PetscFunctionBegin;
288134136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2882f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
288316b64355SHong Zhang   PetscFunctionReturn(0);
288416b64355SHong Zhang }
288516b64355SHong Zhang 
28862d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
28872d033e1fSHong Zhang {
28882d033e1fSHong Zhang   PetscErrorCode ierr;
28892d033e1fSHong Zhang   PetscInt       i;
28900fb991dcSHong Zhang   Mat            C;
28910fb991dcSHong Zhang   Mat_SeqAIJ     *c;
28920fb991dcSHong Zhang   Mat_SubSppt    *submatj;
28932d033e1fSHong Zhang 
28942d033e1fSHong Zhang   PetscFunctionBegin;
28952d033e1fSHong Zhang   for (i=0; i<n; i++) {
28960fb991dcSHong Zhang     C       = (*mat)[i];
28970fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
28980fb991dcSHong Zhang     submatj = c->submatis1;
28992d033e1fSHong Zhang     if (submatj) {
2900682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
290134136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2902f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
290334136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
29042d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
29052d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
29062d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2907682e4c99SStefano Zampini       }
29082d033e1fSHong Zhang     } else {
29092d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
29102d033e1fSHong Zhang     }
29112d033e1fSHong Zhang   }
291286e85357SHong Zhang 
291363a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
291463a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
291563a75b2aSHong Zhang 
29162d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
29172d033e1fSHong Zhang   PetscFunctionReturn(0);
29182d033e1fSHong Zhang }
29192d033e1fSHong Zhang 
29207dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2921cddf8d76SBarry Smith {
2922dfbe8321SBarry Smith   PetscErrorCode ierr;
292397f1f81fSBarry Smith   PetscInt       i;
2924cddf8d76SBarry Smith 
29253a40ed3dSBarry Smith   PetscFunctionBegin;
2926cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2927df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2928cddf8d76SBarry Smith   }
2929cddf8d76SBarry Smith 
2930cddf8d76SBarry Smith   for (i=0; i<n; i++) {
29317dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2932cddf8d76SBarry Smith   }
29333a40ed3dSBarry Smith   PetscFunctionReturn(0);
2934cddf8d76SBarry Smith }
2935cddf8d76SBarry Smith 
293697f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
29374dcbc457SBarry Smith {
2938e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29396849ba73SBarry Smith   PetscErrorCode ierr;
29405d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
29415d0c19d7SBarry Smith   const PetscInt *idx;
294297f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2943f1af5d2fSBarry Smith   PetscBT        table;
2944bbd702dbSSatish Balay 
29453a40ed3dSBarry Smith   PetscFunctionBegin;
2946d0f46423SBarry Smith   m  = A->rmap->n;
2947e4d965acSSatish Balay   ai = a->i;
2948bfeeae90SHong Zhang   aj = a->j;
29498a047759SSatish Balay 
2950e32f2f54SBarry Smith   if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
295106763907SSatish Balay 
2952854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
295353b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
295406763907SSatish Balay 
2955e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2956b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2957e4d965acSSatish Balay     isz  = 0;
29586831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2959e4d965acSSatish Balay 
2960e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
29614dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2962b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
2963e4d965acSSatish Balay 
2964dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2965e4d965acSSatish Balay     for (j=0; j<n; ++j) {
29662205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
29674dcbc457SBarry Smith     }
296806763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
29696bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
2970e4d965acSSatish Balay 
297104a348a9SBarry Smith     k = 0;
297204a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
297304a348a9SBarry Smith       n = isz;
297406763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2975e4d965acSSatish Balay         row   = nidx[k];
2976e4d965acSSatish Balay         start = ai[row];
2977e4d965acSSatish Balay         end   = ai[row+1];
297804a348a9SBarry Smith         for (l = start; l<end; l++) {
2979efb16452SHong Zhang           val = aj[l];
29802205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
2981e4d965acSSatish Balay         }
2982e4d965acSSatish Balay       }
2983e4d965acSSatish Balay     }
298470b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
2985e4d965acSSatish Balay   }
298694bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
2987606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
29883a40ed3dSBarry Smith   PetscFunctionReturn(0);
29894dcbc457SBarry Smith }
299017ab2063SBarry Smith 
29910513a670SBarry Smith /* -------------------------------------------------------------- */
2992dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
29930513a670SBarry Smith {
29940513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29956849ba73SBarry Smith   PetscErrorCode ierr;
29963b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
29975d0c19d7SBarry Smith   const PetscInt *row,*col;
29985d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
299956cd22aeSBarry Smith   IS             icolp,irowp;
30000298fd71SBarry Smith   PetscInt       *cwork = NULL;
30010298fd71SBarry Smith   PetscScalar    *vwork = NULL;
30020513a670SBarry Smith 
30033a40ed3dSBarry Smith   PetscFunctionBegin;
30044c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
300556cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
30064c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
300756cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
30080513a670SBarry Smith 
30090513a670SBarry Smith   /* determine lengths of permuted rows */
3010854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
30112205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
3012ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
3013f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
301433d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
30157adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
3016ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
3017606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
30180513a670SBarry Smith 
3019785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
30200513a670SBarry Smith   for (i=0; i<m; i++) {
302132ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30222205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
3023cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
302432ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30250513a670SBarry Smith   }
3026606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
30272205254eSKarl Rupp 
30283c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
30292205254eSKarl Rupp 
30308c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3031b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr);
30329fe5e383SStefano Zampini #endif
30330513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
30340513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
303556cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
303656cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
30376bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
30386bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
30396768869dSprj-   if (rowp == colp) {
3040dc29a518SPierre Jolivet     ierr = MatPropagateSymmetryOptions(A,*B);CHKERRQ(ierr);
30416768869dSprj-   }
30423a40ed3dSBarry Smith   PetscFunctionReturn(0);
30430513a670SBarry Smith }
30440513a670SBarry Smith 
3045dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
3046cb5b572fSBarry Smith {
3047dfbe8321SBarry Smith   PetscErrorCode ierr;
3048cb5b572fSBarry Smith 
3049cb5b572fSBarry Smith   PetscFunctionBegin;
305033f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
305133f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
3052be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
3053be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ*)B->data;
30542e5835c6SStefano Zampini     const PetscScalar *aa;
3055be6bf707SBarry Smith 
30562e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
30574d805d7cSStefano 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]);
30582e5835c6SStefano Zampini     ierr = PetscArraycpy(b->a,aa,a->i[A->rmap->n]);CHKERRQ(ierr);
3059cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
30602e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
3061cb5b572fSBarry Smith   } else {
3062cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
3063cb5b572fSBarry Smith   }
3064cb5b572fSBarry Smith   PetscFunctionReturn(0);
3065cb5b572fSBarry Smith }
3066cb5b572fSBarry Smith 
30674994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3068273d9f13SBarry Smith {
3069dfbe8321SBarry Smith   PetscErrorCode ierr;
3070273d9f13SBarry Smith 
3071273d9f13SBarry Smith   PetscFunctionBegin;
3072f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
3073273d9f13SBarry Smith   PetscFunctionReturn(0);
3074273d9f13SBarry Smith }
3075273d9f13SBarry Smith 
3076f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
30776c0721eeSBarry Smith {
30786c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
30796e111a19SKarl Rupp 
30806c0721eeSBarry Smith   PetscFunctionBegin;
30816c0721eeSBarry Smith   *array = a->a;
30826c0721eeSBarry Smith   PetscFunctionReturn(0);
30836c0721eeSBarry Smith }
30846c0721eeSBarry Smith 
3085f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
30866c0721eeSBarry Smith {
30876c0721eeSBarry Smith   PetscFunctionBegin;
3088f38c1e66SStefano Zampini   *array = NULL;
30896c0721eeSBarry Smith   PetscFunctionReturn(0);
30906c0721eeSBarry Smith }
3091273d9f13SBarry Smith 
30928229c054SShri Abhyankar /*
30938229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
30948229c054SShri Abhyankar    have different nonzero structure.
30958229c054SShri Abhyankar */
3096b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3097ec7775f6SShri Abhyankar {
3098b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3099ec7775f6SShri Abhyankar 
3100ec7775f6SShri Abhyankar   PetscFunctionBegin;
3101ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3102ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3103b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3104b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3105b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
31068af7cee1SJed Brown     nnz[i] = 0;
31078af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3108b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3109b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
31108af7cee1SJed Brown       nnz[i]++;
31118af7cee1SJed Brown     }
31128af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3113ec7775f6SShri Abhyankar   }
3114ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3115ec7775f6SShri Abhyankar }
3116ec7775f6SShri Abhyankar 
3117b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3118b264fe52SHong Zhang {
3119b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3120b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3121b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3122b264fe52SHong Zhang   PetscErrorCode ierr;
3123b264fe52SHong Zhang 
3124b264fe52SHong Zhang   PetscFunctionBegin;
3125b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
3126b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
3127b264fe52SHong Zhang   PetscFunctionReturn(0);
3128b264fe52SHong Zhang }
3129b264fe52SHong Zhang 
3130f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3131ac90fabeSBarry Smith {
3132dfbe8321SBarry Smith   PetscErrorCode ierr;
3133ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3134ac90fabeSBarry Smith 
3135ac90fabeSBarry Smith   PetscFunctionBegin;
313641f5e1b1SStefano Zampini   if (str == UNKNOWN_NONZERO_PATTERN && x->nz == y->nz) {
313781fa06acSBarry Smith     PetscBool e;
313881fa06acSBarry Smith     ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
313981fa06acSBarry Smith     if (e) {
314081fa06acSBarry Smith       ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
314181fa06acSBarry Smith       if (e) {
314281fa06acSBarry Smith         str = SAME_NONZERO_PATTERN;
314381fa06acSBarry Smith       }
314481fa06acSBarry Smith     }
314581fa06acSBarry Smith   }
3146ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
31472e5835c6SStefano Zampini     const PetscScalar *xa;
31482e5835c6SStefano Zampini     PetscScalar       *ya,alpha = a;
314981fa06acSBarry Smith     PetscBLASInt      one = 1,bnz;
315081fa06acSBarry Smith 
315181fa06acSBarry Smith     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
31522e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(Y,&ya);CHKERRQ(ierr);
31532e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(X,&xa);CHKERRQ(ierr);
31542e5835c6SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one));
31552e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(X,&xa);CHKERRQ(ierr);
31562e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(Y,&ya);CHKERRQ(ierr);
315741f5e1b1SStefano Zampini     ierr = PetscLogFlops(2.0*bnz);CHKERRQ(ierr);
3158acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3159a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
3160ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3161ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3162ac90fabeSBarry Smith   } else {
31638229c054SShri Abhyankar     Mat      B;
31648229c054SShri Abhyankar     PetscInt *nnz;
3165785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3166ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3167bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
316881fa06acSBarry Smith     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
31692e5835c6SStefano Zampini     ierr = MatSetType(B,((PetscObject)Y)->type_name);CHKERRQ(ierr);
31708229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3171ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3172ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
317328be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
31748229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3175ac90fabeSBarry Smith   }
3176ac90fabeSBarry Smith   PetscFunctionReturn(0);
3177ac90fabeSBarry Smith }
3178ac90fabeSBarry Smith 
31792726fb6dSPierre Jolivet PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
3180354c94deSBarry Smith {
3181354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3182354c94deSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3183354c94deSBarry Smith   PetscInt       i,nz;
3184354c94deSBarry Smith   PetscScalar    *a;
3185ce496241SStefano Zampini   PetscErrorCode ierr;
3186354c94deSBarry Smith 
3187354c94deSBarry Smith   PetscFunctionBegin;
3188354c94deSBarry Smith   nz = aij->nz;
3189ce496241SStefano Zampini   ierr = MatSeqAIJGetArray(mat,&a);CHKERRQ(ierr);
31902205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
3191ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArray(mat,&a);CHKERRQ(ierr);
3192354c94deSBarry Smith #else
3193354c94deSBarry Smith   PetscFunctionBegin;
3194354c94deSBarry Smith #endif
3195354c94deSBarry Smith   PetscFunctionReturn(0);
3196354c94deSBarry Smith }
3197354c94deSBarry Smith 
3198985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3199e34fafa9SBarry Smith {
3200e34fafa9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3201e34fafa9SBarry Smith   PetscErrorCode  ierr;
3202d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3203e34fafa9SBarry Smith   PetscReal       atmp;
3204985db425SBarry Smith   PetscScalar     *x;
3205ce496241SStefano Zampini   const MatScalar *aa,*av;
3206e34fafa9SBarry Smith 
3207e34fafa9SBarry Smith   PetscFunctionBegin;
3208e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3209ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3210ce496241SStefano Zampini   aa = av;
3211e34fafa9SBarry Smith   ai = a->i;
3212e34fafa9SBarry Smith   aj = a->j;
3213e34fafa9SBarry Smith 
3214985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3215475b8b61SHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3216e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3217e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3218e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3219e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3220e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3221985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3222985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3223985db425SBarry Smith       aa++; aj++;
3224985db425SBarry Smith     }
3225985db425SBarry Smith   }
3226475b8b61SHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3227ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3228985db425SBarry Smith   PetscFunctionReturn(0);
3229985db425SBarry Smith }
3230985db425SBarry Smith 
3231985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3232985db425SBarry Smith {
3233985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3234985db425SBarry Smith   PetscErrorCode  ierr;
3235d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3236985db425SBarry Smith   PetscScalar     *x;
3237ce496241SStefano Zampini   const MatScalar *aa,*av;
3238985db425SBarry Smith 
3239985db425SBarry Smith   PetscFunctionBegin;
3240e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3241ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3242ce496241SStefano Zampini   aa = av;
3243985db425SBarry Smith   ai = a->i;
3244985db425SBarry Smith   aj = a->j;
3245985db425SBarry Smith 
3246985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3247fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3248985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3249e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3250985db425SBarry Smith   for (i=0; i<m; i++) {
3251985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3252d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3253985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3254985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3255985db425SBarry Smith       x[i] = 0.0;
3256985db425SBarry Smith       if (idx) {
3257985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3258985db425SBarry Smith           if (aj[j] > j) {
3259985db425SBarry Smith             idx[i] = j;
3260985db425SBarry Smith             break;
3261985db425SBarry Smith           }
3262985db425SBarry Smith         }
32631a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
32641a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3265985db425SBarry Smith       }
3266985db425SBarry Smith     }
3267985db425SBarry Smith     for (j=0; j<ncols; j++) {
3268985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3269985db425SBarry Smith       aa++; aj++;
3270985db425SBarry Smith     }
3271985db425SBarry Smith   }
3272fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3273ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3274985db425SBarry Smith   PetscFunctionReturn(0);
3275985db425SBarry Smith }
3276985db425SBarry Smith 
3277c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3278c87e5d42SMatthew Knepley {
3279c87e5d42SMatthew Knepley   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3280c87e5d42SMatthew Knepley   PetscErrorCode  ierr;
3281c87e5d42SMatthew Knepley   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3282ce496241SStefano Zampini   PetscScalar     *x;
3283ce496241SStefano Zampini   const MatScalar *aa,*av;
3284c87e5d42SMatthew Knepley 
3285c87e5d42SMatthew Knepley   PetscFunctionBegin;
3286ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3287ce496241SStefano Zampini   aa = av;
3288c87e5d42SMatthew Knepley   ai = a->i;
3289c87e5d42SMatthew Knepley   aj = a->j;
3290c87e5d42SMatthew Knepley 
3291c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3292f07e67edSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3293c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3294f07e67edSHong Zhang   if (n != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", m, n);
3295c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3296c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3297f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3298f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3299f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3300f07e67edSHong Zhang       x[i] = 0.0;
3301f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3302289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3303f07e67edSHong Zhang           if (aj[j] > j) {
3304f07e67edSHong Zhang             idx[i] = j;
33052205254eSKarl Rupp             break;
33062205254eSKarl Rupp           }
3307289a08f5SMatthew Knepley         }
3308f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3309f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3310f07e67edSHong Zhang       }
3311289a08f5SMatthew Knepley     }
3312c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3313f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3314c87e5d42SMatthew Knepley       aa++; aj++;
3315c87e5d42SMatthew Knepley     }
3316c87e5d42SMatthew Knepley   }
3317f07e67edSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3318ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3319c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3320c87e5d42SMatthew Knepley }
3321c87e5d42SMatthew Knepley 
3322985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3323985db425SBarry Smith {
3324985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3325985db425SBarry Smith   PetscErrorCode  ierr;
3326d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3327d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3328985db425SBarry Smith   PetscScalar     *x;
3329ce496241SStefano Zampini   const MatScalar *aa,*av;
3330985db425SBarry Smith 
3331985db425SBarry Smith   PetscFunctionBegin;
3332e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3333ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3334ce496241SStefano Zampini   aa = av;
3335985db425SBarry Smith   ai = a->i;
3336985db425SBarry Smith   aj = a->j;
3337985db425SBarry Smith 
3338985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3339fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3340985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3341f07e67edSHong Zhang   if (n != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3342985db425SBarry Smith   for (i=0; i<m; i++) {
3343985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3344d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3345985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3346985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3347985db425SBarry Smith       x[i] = 0.0;
3348985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3349985db425SBarry Smith         for (j=0; j<ncols; j++) {
3350985db425SBarry Smith           if (aj[j] > j) {
3351985db425SBarry Smith             idx[i] = j;
3352985db425SBarry Smith             break;
3353985db425SBarry Smith           }
3354985db425SBarry Smith         }
3355fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3356fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3357985db425SBarry Smith       }
3358985db425SBarry Smith     }
3359985db425SBarry Smith     for (j=0; j<ncols; j++) {
3360985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3361985db425SBarry Smith       aa++; aj++;
3362e34fafa9SBarry Smith     }
3363e34fafa9SBarry Smith   }
3364fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3365ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3366e34fafa9SBarry Smith   PetscFunctionReturn(0);
3367e34fafa9SBarry Smith }
3368bbead8a2SBarry Smith 
3369713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3370bbead8a2SBarry Smith {
3371bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3372bbead8a2SBarry Smith   PetscErrorCode  ierr;
337333d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3374bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
33750da83c2eSBarry Smith   const PetscReal shift = 0.0;
33761a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3377bbead8a2SBarry Smith 
3378bbead8a2SBarry Smith   PetscFunctionBegin;
3379a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
33804a0d0026SBarry Smith   if (a->ibdiagvalid) {
33814a0d0026SBarry Smith     if (values) *values = a->ibdiag;
33824a0d0026SBarry Smith     PetscFunctionReturn(0);
33834a0d0026SBarry Smith   }
3384bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3385bbead8a2SBarry Smith   if (!a->ibdiag) {
3386785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
33873bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3388bbead8a2SBarry Smith   }
3389bbead8a2SBarry Smith   diag = a->ibdiag;
3390bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3391bbead8a2SBarry Smith   /* factor and invert each block */
3392bbead8a2SBarry Smith   switch (bs) {
3393bbead8a2SBarry Smith   case 1:
3394bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3395bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3396ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3397ec1892c8SHong Zhang         if (allowzeropivot) {
33987b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33997b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
34007b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
34017b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
34027b6c816cSBarry 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);
3403ec1892c8SHong Zhang       }
3404bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3405bbead8a2SBarry Smith     }
3406bbead8a2SBarry Smith     break;
3407bbead8a2SBarry Smith   case 2:
3408bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3409bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3410bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3411a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34127b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
341396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3414bbead8a2SBarry Smith       diag += 4;
3415bbead8a2SBarry Smith     }
3416bbead8a2SBarry Smith     break;
3417bbead8a2SBarry Smith   case 3:
3418bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3419bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3420bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3421a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34227b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
342396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3424bbead8a2SBarry Smith       diag += 9;
3425bbead8a2SBarry Smith     }
3426bbead8a2SBarry Smith     break;
3427bbead8a2SBarry Smith   case 4:
3428bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3429bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3430bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3431a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34327b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
343396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3434bbead8a2SBarry Smith       diag += 16;
3435bbead8a2SBarry Smith     }
3436bbead8a2SBarry Smith     break;
3437bbead8a2SBarry Smith   case 5:
3438bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3439bbead8a2SBarry 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;
3440bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3441a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34427b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
344396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3444bbead8a2SBarry Smith       diag += 25;
3445bbead8a2SBarry Smith     }
3446bbead8a2SBarry Smith     break;
3447bbead8a2SBarry Smith   case 6:
3448bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3449bbead8a2SBarry 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;
3450bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3451a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34527b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
345396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3454bbead8a2SBarry Smith       diag += 36;
3455bbead8a2SBarry Smith     }
3456bbead8a2SBarry Smith     break;
3457bbead8a2SBarry Smith   case 7:
3458bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3459bbead8a2SBarry 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;
3460bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3461a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34627b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
346396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3464bbead8a2SBarry Smith       diag += 49;
3465bbead8a2SBarry Smith     }
3466bbead8a2SBarry Smith     break;
3467bbead8a2SBarry Smith   default:
3468dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3469bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3470bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3471bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3472bbead8a2SBarry Smith       }
3473bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
34745f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34757b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
347696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3477bbead8a2SBarry Smith       diag += bs2;
3478bbead8a2SBarry Smith     }
3479bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3480bbead8a2SBarry Smith   }
3481bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3482bbead8a2SBarry Smith   PetscFunctionReturn(0);
3483bbead8a2SBarry Smith }
3484bbead8a2SBarry Smith 
348573a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
348673a71a0fSBarry Smith {
348773a71a0fSBarry Smith   PetscErrorCode ierr;
348873a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3489*fff043a9SJunchao Zhang   PetscScalar    a,*aa;
349073a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
349173a71a0fSBarry Smith 
349273a71a0fSBarry Smith   PetscFunctionBegin;
349373a71a0fSBarry Smith   if (!x->assembled) {
349473a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
349573a71a0fSBarry Smith     for (i=0; i<m; i++) {
349673a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
349773a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
349873a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
349973a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
350073a71a0fSBarry Smith       }
350173a71a0fSBarry Smith     }
3502e2ce353bSJunchao Zhang   } else {
3503*fff043a9SJunchao Zhang     ierr = MatSeqAIJGetArrayWrite(x,&aa);CHKERRQ(ierr);
3504*fff043a9SJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aa+i);CHKERRQ(ierr);}
3505*fff043a9SJunchao Zhang     ierr = MatSeqAIJRestoreArrayWrite(x,&aa);CHKERRQ(ierr);
3506e2ce353bSJunchao Zhang   }
350773a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
350873a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
350973a71a0fSBarry Smith   PetscFunctionReturn(0);
351073a71a0fSBarry Smith }
351173a71a0fSBarry Smith 
3512679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3513679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3514679944adSJunchao Zhang {
3515679944adSJunchao Zhang   PetscErrorCode ierr;
3516679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3517679944adSJunchao Zhang   PetscScalar    a;
3518679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3519679944adSJunchao Zhang 
3520679944adSJunchao Zhang   PetscFunctionBegin;
3521679944adSJunchao Zhang   nskip = high - low;
3522679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3523679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3524679944adSJunchao Zhang   for (i=0; i<m; i++) {
3525679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3526679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3527679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3528679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3529679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3530679944adSJunchao Zhang     }
3531e2ce353bSJunchao Zhang   }
3532679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3533679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3534679944adSJunchao Zhang   PetscFunctionReturn(0);
3535679944adSJunchao Zhang }
3536679944adSJunchao Zhang 
3537682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
35380a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3539cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3540cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3541cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
354297304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
35437c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
35447c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3545f4259b30SLisandro Dalcin                                         NULL,
3546f4259b30SLisandro Dalcin                                         NULL,
3547f4259b30SLisandro Dalcin                                         NULL,
3548f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3549cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3550f4259b30SLisandro Dalcin                                         NULL,
355141f059aeSBarry Smith                                         MatSOR_SeqAIJ,
355291e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
355397304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3554cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3555cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3556cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3557cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3558f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3559cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3560cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3561cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3562d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3563f4259b30SLisandro Dalcin                                         NULL,
3564f4259b30SLisandro Dalcin                                         NULL,
3565f4259b30SLisandro Dalcin                                         NULL,
3566f4259b30SLisandro Dalcin                                         NULL,
35674994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3568f4259b30SLisandro Dalcin                                         NULL,
3569f4259b30SLisandro Dalcin                                         NULL,
3570f4259b30SLisandro Dalcin                                         NULL,
3571f4259b30SLisandro Dalcin                                         NULL,
3572d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3573f4259b30SLisandro Dalcin                                         NULL,
3574f4259b30SLisandro Dalcin                                         NULL,
3575cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3576f4259b30SLisandro Dalcin                                         NULL,
3577d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
35787dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3579cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3580cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3581cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3582d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3583cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
35847d68702bSBarry Smith                                         MatShift_SeqAIJ,
358579299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
35866e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
358773a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
35883b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
35893b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
35903b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3591a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
359293dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3593f4259b30SLisandro Dalcin                                         NULL,
3594f4259b30SLisandro Dalcin                                         NULL,
3595cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3596f4259b30SLisandro Dalcin                                         NULL,
3597f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3598b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3599b9b97703SBarry Smith                                         MatView_SeqAIJ,
3600f4259b30SLisandro Dalcin                                         NULL,
3601f4259b30SLisandro Dalcin                                         NULL,
3602f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3603321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3604f4259b30SLisandro Dalcin                                         NULL,
3605f4259b30SLisandro Dalcin                                         NULL,
3606f4259b30SLisandro Dalcin                                         NULL,
3607d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3608c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3609f4259b30SLisandro Dalcin                                         NULL,
3610f4259b30SLisandro Dalcin                                         NULL,
3611f4259b30SLisandro Dalcin                                         NULL,
3612f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
36133acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3614f4259b30SLisandro Dalcin                                         NULL,
3615f4259b30SLisandro Dalcin                                         NULL,
3616f4259b30SLisandro Dalcin                                         NULL,
36176ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3618f4259b30SLisandro Dalcin                                         NULL,
3619f4259b30SLisandro Dalcin                                         NULL,
3620f4259b30SLisandro Dalcin                                         NULL,
3621bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3622d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
36231cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3624f4259b30SLisandro Dalcin                                         NULL,
3625f4259b30SLisandro Dalcin                                         NULL,
3626f4259b30SLisandro Dalcin                                         NULL,
3627f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3628f4259b30SLisandro Dalcin                                         NULL,
362926be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3630f4259b30SLisandro Dalcin                                         NULL,
3631f4259b30SLisandro Dalcin                                         NULL,
36328fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3633f4259b30SLisandro Dalcin                                         NULL,
3634f4259b30SLisandro Dalcin                                         NULL,
36356fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3636f4259b30SLisandro Dalcin                                         NULL,
36374222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3638f4259b30SLisandro Dalcin                                         NULL,
3639f4259b30SLisandro Dalcin                                         NULL,
364087d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3641f4259b30SLisandro Dalcin                                         NULL,
3642d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
364399cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3644f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3645f4259b30SLisandro Dalcin                                         NULL,
3646f4259b30SLisandro Dalcin                                         NULL,
3647cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3648f4259b30SLisandro Dalcin                                         NULL,
36492af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3650f4259b30SLisandro Dalcin                                         NULL,
3651599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3652f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3653f4259b30SLisandro Dalcin                                         NULL,
3654f4259b30SLisandro Dalcin                                         NULL,
3655f4259b30SLisandro Dalcin                                         NULL,
3656f4259b30SLisandro Dalcin                                         NULL,
3657f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3658f4259b30SLisandro Dalcin                                         NULL,
3659f4259b30SLisandro Dalcin                                         NULL,
3660f4259b30SLisandro Dalcin                                         NULL,
3661b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
36620716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3663a873a8cdSSam Reynolds                                         MatGetColumnReductions_SeqAIJ,
366437868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
36650da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3666f4259b30SLisandro Dalcin                                         NULL,
3667f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3668f4259b30SLisandro Dalcin                                         NULL,
3669f4259b30SLisandro Dalcin                                         NULL,
367075648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3671b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3672b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
36732b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3674f4259b30SLisandro Dalcin                                         NULL,
3675f4259b30SLisandro Dalcin                                         NULL,
36763964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3677f4259b30SLisandro Dalcin                                  /*139*/NULL,
3678f4259b30SLisandro Dalcin                                         NULL,
3679f4259b30SLisandro Dalcin                                         NULL,
36803a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
36819c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
36824222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
36834222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3684f4259b30SLisandro Dalcin                                         NULL,
3685f4259b30SLisandro Dalcin                                         NULL
36869e29f15eSvictorle };
368717ab2063SBarry Smith 
36887087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3689bef8e0ddSBarry Smith {
3690bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
369197f1f81fSBarry Smith   PetscInt   i,nz,n;
3692bef8e0ddSBarry Smith 
3693bef8e0ddSBarry Smith   PetscFunctionBegin;
3694bef8e0ddSBarry Smith   nz = aij->maxnz;
3695d0f46423SBarry Smith   n  = mat->rmap->n;
3696bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3697bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3698bef8e0ddSBarry Smith   }
3699bef8e0ddSBarry Smith   aij->nz = nz;
3700bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3701bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3702bef8e0ddSBarry Smith   }
3703bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3704bef8e0ddSBarry Smith }
3705bef8e0ddSBarry Smith 
3706a3bb6f32SFande Kong /*
3707ddea5d60SJunchao Zhang  * Given a sparse matrix with global column indices, compact it by using a local column space.
3708ddea5d60SJunchao Zhang  * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3709ddea5d60SJunchao Zhang  */
3710a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3711a3bb6f32SFande Kong {
3712a3bb6f32SFande Kong   Mat_SeqAIJ         *aij = (Mat_SeqAIJ*)mat->data;
3713a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3714a3bb6f32SFande Kong   PetscTablePosition tpos;
371525b670f0SStefano Zampini   PetscInt           gid,lid,i,ec,nz = aij->nz;
371625b670f0SStefano Zampini   PetscInt           *garray,*jj = aij->j;
3717a3bb6f32SFande Kong   PetscErrorCode     ierr;
3718a3bb6f32SFande Kong 
3719a3bb6f32SFande Kong   PetscFunctionBegin;
3720a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3721a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3722a3bb6f32SFande Kong   /* use a table */
3723a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3724a3bb6f32SFande Kong   ec = 0;
372525b670f0SStefano Zampini   for (i=0; i<nz; i++) {
372625b670f0SStefano Zampini     PetscInt data,gid1 = jj[i] + 1;
3727a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3728a3bb6f32SFande Kong     if (!data) {
3729a3bb6f32SFande Kong       /* one based table */
3730a3bb6f32SFande Kong       ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3731a3bb6f32SFande Kong     }
3732a3bb6f32SFande Kong   }
3733a3bb6f32SFande Kong   /* form array of columns we need */
3734b3c64f9dSJunchao Zhang   ierr = PetscMalloc1(ec,&garray);CHKERRQ(ierr);
3735a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3736a3bb6f32SFande Kong   while (tpos) {
3737a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3738a3bb6f32SFande Kong     gid--;
3739a3bb6f32SFande Kong     lid--;
3740a3bb6f32SFande Kong     garray[lid] = gid;
3741a3bb6f32SFande Kong   }
3742a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3743a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3744a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3745a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3746a3bb6f32SFande Kong   }
3747a3bb6f32SFande Kong   /* compact out the extra columns in B */
374825b670f0SStefano Zampini   for (i=0; i<nz; i++) {
374925b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
3750a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3751a3bb6f32SFande Kong     lid--;
375225b670f0SStefano Zampini     jj[i] = lid;
3753a3bb6f32SFande Kong   }
3754ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3755a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
375625b670f0SStefano Zampini   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3757a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3758a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3759a3bb6f32SFande Kong   PetscFunctionReturn(0);
3760a3bb6f32SFande Kong }
3761a3bb6f32SFande Kong 
3762bef8e0ddSBarry Smith /*@
3763bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3764bef8e0ddSBarry Smith        in the matrix.
3765bef8e0ddSBarry Smith 
3766bef8e0ddSBarry Smith   Input Parameters:
3767bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3768bef8e0ddSBarry Smith -  indices - the column indices
3769bef8e0ddSBarry Smith 
377015091d37SBarry Smith   Level: advanced
377115091d37SBarry Smith 
3772bef8e0ddSBarry Smith   Notes:
3773bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3774bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3775bef8e0ddSBarry Smith   of the MatSetValues() operation.
3776bef8e0ddSBarry Smith 
3777bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3778d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3779bef8e0ddSBarry Smith 
3780bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3781bef8e0ddSBarry Smith 
3782b9617806SBarry Smith     The indices should start with zero, not one.
3783b9617806SBarry Smith 
3784bef8e0ddSBarry Smith @*/
37857087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3786bef8e0ddSBarry Smith {
37874ac538c5SBarry Smith   PetscErrorCode ierr;
3788bef8e0ddSBarry Smith 
3789bef8e0ddSBarry Smith   PetscFunctionBegin;
37900700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
37914482741eSBarry Smith   PetscValidPointer(indices,2);
37924ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3793bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3794bef8e0ddSBarry Smith }
3795bef8e0ddSBarry Smith 
3796be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3797be6bf707SBarry Smith 
37987087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3799be6bf707SBarry Smith {
3800be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38016849ba73SBarry Smith   PetscErrorCode ierr;
3802d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3803be6bf707SBarry Smith 
3804be6bf707SBarry Smith   PetscFunctionBegin;
3805169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3806be6bf707SBarry Smith 
3807be6bf707SBarry Smith   /* allocate space for values if not already there */
3808be6bf707SBarry Smith   if (!aij->saved_values) {
3809854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
38103bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3811be6bf707SBarry Smith   }
3812be6bf707SBarry Smith 
3813be6bf707SBarry Smith   /* copy values over */
3814580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3815be6bf707SBarry Smith   PetscFunctionReturn(0);
3816be6bf707SBarry Smith }
3817be6bf707SBarry Smith 
3818be6bf707SBarry Smith /*@
3819be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3820be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3821be6bf707SBarry Smith        nonlinear portion.
3822be6bf707SBarry Smith 
3823be6bf707SBarry Smith    Collect on Mat
3824be6bf707SBarry Smith 
3825be6bf707SBarry Smith   Input Parameters:
38260e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3827be6bf707SBarry Smith 
382815091d37SBarry Smith   Level: advanced
382915091d37SBarry Smith 
3830be6bf707SBarry Smith   Common Usage, with SNESSolve():
3831be6bf707SBarry Smith $    Create Jacobian matrix
3832be6bf707SBarry Smith $    Set linear terms into matrix
3833be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3834be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3835be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3836512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3837be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3838be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3839be6bf707SBarry Smith $    In your Jacobian routine
3840be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3841be6bf707SBarry Smith $      Set nonlinear terms in matrix
3842be6bf707SBarry Smith 
3843be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3844be6bf707SBarry Smith $    // build linear portion of Jacobian
3845512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3846be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3847be6bf707SBarry Smith $    loop over nonlinear iterations
3848be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3849be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3850be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3851be6bf707SBarry Smith $       Solve linear system with Jacobian
3852be6bf707SBarry Smith $    endloop
3853be6bf707SBarry Smith 
3854be6bf707SBarry Smith   Notes:
3855be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3856512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3857be6bf707SBarry Smith     calling this routine.
3858be6bf707SBarry Smith 
38590c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
38600c468ba9SBarry Smith     and does not allocated additional space.
38610c468ba9SBarry Smith 
3862be6bf707SBarry Smith .seealso: MatRetrieveValues()
3863be6bf707SBarry Smith 
3864be6bf707SBarry Smith @*/
38657087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3866be6bf707SBarry Smith {
38674ac538c5SBarry Smith   PetscErrorCode ierr;
3868be6bf707SBarry Smith 
3869be6bf707SBarry Smith   PetscFunctionBegin;
38700700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3871e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3872e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
38734ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3874be6bf707SBarry Smith   PetscFunctionReturn(0);
3875be6bf707SBarry Smith }
3876be6bf707SBarry Smith 
38777087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3878be6bf707SBarry Smith {
3879be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38806849ba73SBarry Smith   PetscErrorCode ierr;
3881d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3882be6bf707SBarry Smith 
3883be6bf707SBarry Smith   PetscFunctionBegin;
3884169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3885f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3886be6bf707SBarry Smith   /* copy values over */
3887580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3888be6bf707SBarry Smith   PetscFunctionReturn(0);
3889be6bf707SBarry Smith }
3890be6bf707SBarry Smith 
3891be6bf707SBarry Smith /*@
3892be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3893be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3894be6bf707SBarry Smith        nonlinear portion.
3895be6bf707SBarry Smith 
3896be6bf707SBarry Smith    Collect on Mat
3897be6bf707SBarry Smith 
3898be6bf707SBarry Smith   Input Parameters:
3899386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3900be6bf707SBarry Smith 
390115091d37SBarry Smith   Level: advanced
390215091d37SBarry Smith 
3903be6bf707SBarry Smith .seealso: MatStoreValues()
3904be6bf707SBarry Smith 
3905be6bf707SBarry Smith @*/
39067087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3907be6bf707SBarry Smith {
39084ac538c5SBarry Smith   PetscErrorCode ierr;
3909be6bf707SBarry Smith 
3910be6bf707SBarry Smith   PetscFunctionBegin;
39110700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3912e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3913e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39144ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3915be6bf707SBarry Smith   PetscFunctionReturn(0);
3916be6bf707SBarry Smith }
3917be6bf707SBarry Smith 
3918be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
391917ab2063SBarry Smith /*@C
3920682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
39210d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
39226e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
392351c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
39242bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
392517ab2063SBarry Smith 
3926d083f849SBarry Smith    Collective
3927db81eaa0SLois Curfman McInnes 
392817ab2063SBarry Smith    Input Parameters:
3929db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
393017ab2063SBarry Smith .  m - number of rows
393117ab2063SBarry Smith .  n - number of columns
393217ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
393351c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39340298fd71SBarry Smith          (possibly different for each row) or NULL
393517ab2063SBarry Smith 
393617ab2063SBarry Smith    Output Parameter:
3937416022c9SBarry Smith .  A - the matrix
393817ab2063SBarry Smith 
3939175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3940f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3941175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3942175b88e8SBarry Smith 
3943b259b22eSLois Curfman McInnes    Notes:
394449a6f317SBarry Smith    If nnz is given then nz is ignored
394549a6f317SBarry Smith 
394617ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
394717ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
39480002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
394944cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
395017ab2063SBarry Smith 
395117ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39520298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
39533d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
39546da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
395517ab2063SBarry Smith 
3956682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
39574fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3958682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
39596c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
39606c7ebb05SLois Curfman McInnes 
39616c7ebb05SLois Curfman McInnes    Options Database Keys:
3962698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
39639db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
396417ab2063SBarry Smith 
3965027ccd11SLois Curfman McInnes    Level: intermediate
3966027ccd11SLois Curfman McInnes 
396769b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
396836db0b34SBarry Smith 
396917ab2063SBarry Smith @*/
39707087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
397117ab2063SBarry Smith {
3972dfbe8321SBarry Smith   PetscErrorCode ierr;
39736945ee14SBarry Smith 
39743a40ed3dSBarry Smith   PetscFunctionBegin;
3975f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3976117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3977c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
3978d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
3979273d9f13SBarry Smith   PetscFunctionReturn(0);
3980273d9f13SBarry Smith }
3981273d9f13SBarry Smith 
3982273d9f13SBarry Smith /*@C
3983273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3984273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
3985273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
3986273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
3987273d9f13SBarry Smith 
3988d083f849SBarry Smith    Collective
3989273d9f13SBarry Smith 
3990273d9f13SBarry Smith    Input Parameters:
39911c4f3114SJed Brown +  B - The matrix
3992273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
3993273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39940298fd71SBarry Smith          (possibly different for each row) or NULL
3995273d9f13SBarry Smith 
3996273d9f13SBarry Smith    Notes:
399749a6f317SBarry Smith      If nnz is given then nz is ignored
399849a6f317SBarry Smith 
3999273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
4000273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
4001273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
4002273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
4003273d9f13SBarry Smith 
4004273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
40050298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
4006273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
4007273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
4008273d9f13SBarry Smith 
4009aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
4010aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
4011aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
4012aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
4013aa95bbe8SBarry Smith 
4014a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
4015a96a251dSBarry Smith    entries or columns indices
4016a96a251dSBarry Smith 
4017273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
4018273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
4019273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
4020273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
4021273d9f13SBarry Smith 
4022273d9f13SBarry Smith    Options Database Keys:
4023698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
402447b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
4025273d9f13SBarry Smith 
4026273d9f13SBarry Smith    Level: intermediate
4027273d9f13SBarry Smith 
402819b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
402919b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
4030273d9f13SBarry Smith 
4031273d9f13SBarry Smith @*/
40327087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
4033273d9f13SBarry Smith {
40344ac538c5SBarry Smith   PetscErrorCode ierr;
4035a23d5eceSKris Buschelman 
4036a23d5eceSKris Buschelman   PetscFunctionBegin;
40376ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40386ba663aaSJed Brown   PetscValidType(B,1);
40394ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
4040a23d5eceSKris Buschelman   PetscFunctionReturn(0);
4041a23d5eceSKris Buschelman }
4042a23d5eceSKris Buschelman 
40437087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4044a23d5eceSKris Buschelman {
4045273d9f13SBarry Smith   Mat_SeqAIJ     *b;
40462576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
40476849ba73SBarry Smith   PetscErrorCode ierr;
404897f1f81fSBarry Smith   PetscInt       i;
4049273d9f13SBarry Smith 
4050273d9f13SBarry Smith   PetscFunctionBegin;
40512576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4052a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
4053c461c341SBarry Smith     skipallocation = PETSC_TRUE;
4054c461c341SBarry Smith     nz             = 0;
4055c461c341SBarry Smith   }
405626283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
405726283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4058899cda47SBarry Smith 
4059435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
406060e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
4061cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
4062d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
406360e0710aSBarry 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]);
406460e0710aSBarry 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);
4065b73539f3SBarry Smith     }
4066b73539f3SBarry Smith   }
4067b73539f3SBarry Smith 
4068273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
40692205254eSKarl Rupp 
4070273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
4071273d9f13SBarry Smith 
4072ab93d7beSBarry Smith   if (!skipallocation) {
40732ee49352SLisandro Dalcin     if (!b->imax) {
4074071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4075071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4076071fcb05SBarry Smith     }
4077071fcb05SBarry Smith     if (!b->ilen) {
4078071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
4079071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4080071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4081071fcb05SBarry Smith     } else {
4082071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
40832ee49352SLisandro Dalcin     }
4084846b4da1SFande Kong     if (!b->ipre) {
4085846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4086846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4087846b4da1SFande Kong     }
4088273d9f13SBarry Smith     if (!nnz) {
4089435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4090c62bd62aSJed Brown       else if (nz < 0) nz = 1;
40915d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4092d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4093d0f46423SBarry Smith       nz = nz*B->rmap->n;
4094273d9f13SBarry Smith     } else {
4095c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4096c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4097c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4098273d9f13SBarry Smith     }
4099ab93d7beSBarry Smith 
4100273d9f13SBarry Smith     /* allocate the matrix space */
410153dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
41022ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4103396832f4SHong Zhang     if (B->structure_only) {
41045848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
41055848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4106396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4107396832f4SHong Zhang     } else {
4108dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
41093bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4110396832f4SHong Zhang     }
4111bfeeae90SHong Zhang     b->i[0] = 0;
4112d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
41135da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
41145da197adSKris Buschelman     }
4115396832f4SHong Zhang     if (B->structure_only) {
4116396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4117396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4118396832f4SHong Zhang     } else {
4119273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4120e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4121396832f4SHong Zhang     }
4122e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4123c461c341SBarry Smith   } else {
4124e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4125e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4126c461c341SBarry Smith   }
4127273d9f13SBarry Smith 
4128846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
4129846b4da1SFande Kong     /* reserve user-requested sparsity */
4130580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4131846b4da1SFande Kong   }
4132846b4da1SFande Kong 
4133273d9f13SBarry Smith   b->nz               = 0;
4134273d9f13SBarry Smith   b->maxnz            = nz;
4135273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
41362205254eSKarl Rupp   if (realalloc) {
41372205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
41382205254eSKarl Rupp   }
4139cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4140cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4141273d9f13SBarry Smith   PetscFunctionReturn(0);
4142273d9f13SBarry Smith }
4143273d9f13SBarry Smith 
4144846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4145846b4da1SFande Kong {
4146846b4da1SFande Kong   Mat_SeqAIJ     *a;
4147a5bbaf83SFande Kong   PetscInt       i;
4148846b4da1SFande Kong   PetscErrorCode ierr;
4149846b4da1SFande Kong 
4150846b4da1SFande Kong   PetscFunctionBegin;
4151846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
415214d0e64fSAlex Lindsay 
415314d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
415414d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
415514d0e64fSAlex Lindsay 
4156846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
41572c814fdeSFande Kong   /* if no saved info, we error out */
4158fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
41592c814fdeSFande Kong 
4160fb4dc15dSAlex 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");
41612c814fdeSFande Kong 
4162580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4163580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4164846b4da1SFande Kong   a->i[0] = 0;
4165846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4166846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4167846b4da1SFande Kong   }
4168846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4169846b4da1SFande Kong   a->nz               = 0;
4170846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4171846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4172846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4173846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4174846b4da1SFande Kong   PetscFunctionReturn(0);
4175846b4da1SFande Kong }
4176846b4da1SFande Kong 
417758d36128SBarry Smith /*@
4178a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4179a1661176SMatthew Knepley 
4180a1661176SMatthew Knepley    Input Parameters:
4181a1661176SMatthew Knepley +  B - the matrix
4182a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4183a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4184a1661176SMatthew Knepley -  v - optional values in the matrix
4185a1661176SMatthew Knepley 
4186a1661176SMatthew Knepley    Level: developer
4187a1661176SMatthew Knepley 
41886a9b8d82SBarry Smith    Notes:
418958d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
419058d36128SBarry Smith 
41916a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
41926a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
41936a9b8d82SBarry Smith 
41946a9b8d82SBarry Smith     Developer Notes:
41956a9b8d82SBarry 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
41966a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
41976a9b8d82SBarry Smith 
41986a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
41996a9b8d82SBarry Smith 
42006a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4201a1661176SMatthew Knepley @*/
4202a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4203a1661176SMatthew Knepley {
4204a1661176SMatthew Knepley   PetscErrorCode ierr;
4205a1661176SMatthew Knepley 
4206a1661176SMatthew Knepley   PetscFunctionBegin;
42070700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
42086ba663aaSJed Brown   PetscValidType(B,1);
42094ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4210a1661176SMatthew Knepley   PetscFunctionReturn(0);
4211a1661176SMatthew Knepley }
4212a1661176SMatthew Knepley 
42137087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4214a1661176SMatthew Knepley {
4215a1661176SMatthew Knepley   PetscInt       i;
4216a1661176SMatthew Knepley   PetscInt       m,n;
4217a1661176SMatthew Knepley   PetscInt       nz;
42186a9b8d82SBarry Smith   PetscInt       *nnz;
4219a1661176SMatthew Knepley   PetscErrorCode ierr;
4220a1661176SMatthew Knepley 
4221a1661176SMatthew Knepley   PetscFunctionBegin;
422265e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
4223779a8d59SSatish Balay 
4224779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4225779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4226779a8d59SSatish Balay 
4227779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4228854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4229a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4230b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
423165e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
4232a1661176SMatthew Knepley     nnz[i] = nz;
4233a1661176SMatthew Knepley   }
4234a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4235a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4236a1661176SMatthew Knepley 
4237a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4238071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4239a1661176SMatthew Knepley   }
4240a1661176SMatthew Knepley 
4241a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4242a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4243a1661176SMatthew Knepley 
42447827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4245a1661176SMatthew Knepley   PetscFunctionReturn(0);
4246a1661176SMatthew Knepley }
4247a1661176SMatthew Knepley 
4248ad7e164aSPierre Jolivet /*@
4249ad7e164aSPierre Jolivet    MatSeqAIJKron - Computes C, the Kronecker product of A and B.
4250ad7e164aSPierre Jolivet 
4251ad7e164aSPierre Jolivet    Input Parameters:
4252ad7e164aSPierre Jolivet +  A - left-hand side matrix
4253ad7e164aSPierre Jolivet .  B - right-hand side matrix
4254ad7e164aSPierre Jolivet -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
4255ad7e164aSPierre Jolivet 
4256ad7e164aSPierre Jolivet    Output Parameter:
4257ad7e164aSPierre Jolivet .  C - Kronecker product of A and B
4258ad7e164aSPierre Jolivet 
4259ad7e164aSPierre Jolivet    Level: intermediate
4260ad7e164aSPierre Jolivet 
4261ad7e164aSPierre Jolivet    Notes:
4262ad7e164aSPierre 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().
4263ad7e164aSPierre Jolivet 
4264ad7e164aSPierre Jolivet .seealso: MatCreateSeqAIJ(), MATSEQAIJ, MATKAIJ, MatReuse
4265ad7e164aSPierre Jolivet @*/
4266ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C)
4267ad7e164aSPierre Jolivet {
4268ad7e164aSPierre Jolivet   PetscErrorCode ierr;
4269ad7e164aSPierre Jolivet 
4270ad7e164aSPierre Jolivet   PetscFunctionBegin;
4271ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4272ad7e164aSPierre Jolivet   PetscValidType(A,1);
4273ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4274ad7e164aSPierre Jolivet   PetscValidType(B,2);
4275ad7e164aSPierre Jolivet   PetscValidPointer(C,4);
4276ad7e164aSPierre Jolivet   if (reuse == MAT_REUSE_MATRIX) {
4277ad7e164aSPierre Jolivet     PetscValidHeaderSpecific(*C,MAT_CLASSID,4);
4278ad7e164aSPierre Jolivet     PetscValidType(*C,4);
4279ad7e164aSPierre Jolivet   }
4280ad7e164aSPierre Jolivet   ierr = PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C));CHKERRQ(ierr);
4281ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4282ad7e164aSPierre Jolivet }
4283ad7e164aSPierre Jolivet 
4284ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C)
4285ad7e164aSPierre Jolivet {
4286*fff043a9SJunchao Zhang   PetscErrorCode     ierr;
4287ad7e164aSPierre Jolivet   Mat                newmat;
4288ad7e164aSPierre Jolivet   Mat_SeqAIJ         *a = (Mat_SeqAIJ*)A->data;
4289ad7e164aSPierre Jolivet   Mat_SeqAIJ         *b = (Mat_SeqAIJ*)B->data;
4290ad7e164aSPierre Jolivet   PetscScalar        *v;
4291*fff043a9SJunchao Zhang   const PetscScalar  *aa,*ba;
4292ad7e164aSPierre 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;
4293ad7e164aSPierre Jolivet   PetscBool          flg;
4294ad7e164aSPierre Jolivet 
4295ad7e164aSPierre Jolivet   PetscFunctionBegin;
4296ad7e164aSPierre Jolivet   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4297ad7e164aSPierre Jolivet   if (!A->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4298ad7e164aSPierre Jolivet   if (B->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4299ad7e164aSPierre Jolivet   if (!B->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4300ad7e164aSPierre Jolivet   ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg);CHKERRQ(ierr);
4301ad7e164aSPierre Jolivet   if (!flg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name);
4302ad7e164aSPierre Jolivet   if (reuse != MAT_INITIAL_MATRIX && reuse != MAT_REUSE_MATRIX) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse);
4303ad7e164aSPierre Jolivet   if (reuse == MAT_INITIAL_MATRIX) {
4304ad7e164aSPierre Jolivet     ierr = PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j);CHKERRQ(ierr);
4305ad7e164aSPierre Jolivet     ierr = MatCreate(PETSC_COMM_SELF,&newmat);CHKERRQ(ierr);
4306ad7e164aSPierre Jolivet     ierr = MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn);CHKERRQ(ierr);
4307ad7e164aSPierre Jolivet     ierr = MatSetType(newmat,MATAIJ);CHKERRQ(ierr);
4308ad7e164aSPierre Jolivet     i[0] = 0;
4309ad7e164aSPierre Jolivet     for (m = 0; m < am; ++m) {
4310ad7e164aSPierre Jolivet       for (p = 0; p < bm; ++p) {
4311ad7e164aSPierre Jolivet         i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]);
4312ad7e164aSPierre Jolivet         for (n = a->i[m]; n < a->i[m+1]; ++n) {
4313ad7e164aSPierre Jolivet           for (q = b->i[p]; q < b->i[p+1]; ++q) {
4314ad7e164aSPierre Jolivet             j[nnz++] = a->j[n]*bn + b->j[q];
4315ad7e164aSPierre Jolivet           }
4316ad7e164aSPierre Jolivet         }
4317ad7e164aSPierre Jolivet       }
4318ad7e164aSPierre Jolivet     }
4319ad7e164aSPierre Jolivet     ierr = MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL);CHKERRQ(ierr);
4320ad7e164aSPierre Jolivet     *C = newmat;
4321ad7e164aSPierre Jolivet     ierr = PetscFree2(i,j);CHKERRQ(ierr);
4322ad7e164aSPierre Jolivet     nnz = 0;
4323ad7e164aSPierre Jolivet   }
4324ad7e164aSPierre Jolivet   ierr = MatSeqAIJGetArray(*C,&v);CHKERRQ(ierr);
4325*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4326*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(B,&ba);CHKERRQ(ierr);
4327ad7e164aSPierre Jolivet   for (m = 0; m < am; ++m) {
4328ad7e164aSPierre Jolivet     for (p = 0; p < bm; ++p) {
4329ad7e164aSPierre Jolivet       for (n = a->i[m]; n < a->i[m+1]; ++n) {
4330ad7e164aSPierre Jolivet         for (q = b->i[p]; q < b->i[p+1]; ++q) {
4331*fff043a9SJunchao Zhang           v[nnz++] = aa[n] * ba[q];
4332ad7e164aSPierre Jolivet         }
4333ad7e164aSPierre Jolivet       }
4334ad7e164aSPierre Jolivet     }
4335ad7e164aSPierre Jolivet   }
4336ad7e164aSPierre Jolivet   ierr = MatSeqAIJRestoreArray(*C,&v);CHKERRQ(ierr);
4337*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
4338*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(B,&ba);CHKERRQ(ierr);
4339ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4340ad7e164aSPierre Jolivet }
4341ad7e164aSPierre Jolivet 
4342c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4343af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4344170fe5c8SBarry Smith 
4345170fe5c8SBarry Smith /*
4346170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4347170fe5c8SBarry Smith 
4348170fe5c8SBarry Smith                n                       p                          p
43492da392ccSBarry Smith         [             ]       [             ]         [                 ]
43502da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
43512da392ccSBarry Smith         [             ]       [             ]         [                 ]
4352170fe5c8SBarry Smith 
4353170fe5c8SBarry Smith */
4354170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4355170fe5c8SBarry Smith {
4356170fe5c8SBarry Smith   PetscErrorCode    ierr;
4357170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4358170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4359170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
436086214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4361170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4362170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4363170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
436486214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
436586214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4366170fe5c8SBarry Smith 
4367170fe5c8SBarry Smith   PetscFunctionBegin;
4368d0f46423SBarry Smith   m    = A->rmap->n;
4369d0f46423SBarry Smith   n    = A->cmap->n;
4370d0f46423SBarry Smith   p    = B->cmap->n;
4371170fe5c8SBarry Smith   a    = sub_a->v;
4372170fe5c8SBarry Smith   b    = sub_b->a;
4373170fe5c8SBarry Smith   c    = sub_c->v;
437486214ceeSStefano Zampini   if (clda == m) {
4375580bdb30SBarry Smith     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
437686214ceeSStefano Zampini   } else {
437786214ceeSStefano Zampini     for (j=0;j<p;j++)
437886214ceeSStefano Zampini       for (i=0;i<m;i++)
437986214ceeSStefano Zampini         c[j*clda + i] = 0.0;
438086214ceeSStefano Zampini   }
4381170fe5c8SBarry Smith   ii  = sub_b->i;
4382170fe5c8SBarry Smith   idx = sub_b->j;
4383170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4384170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4385170fe5c8SBarry Smith     while (q-->0) {
438686214ceeSStefano Zampini       c_q = c + clda*(*idx);
438786214ceeSStefano Zampini       a_q = a + alda*i;
4388854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4389170fe5c8SBarry Smith       idx++;
4390170fe5c8SBarry Smith       b++;
4391170fe5c8SBarry Smith     }
4392170fe5c8SBarry Smith   }
4393170fe5c8SBarry Smith   PetscFunctionReturn(0);
4394170fe5c8SBarry Smith }
4395170fe5c8SBarry Smith 
43964222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4397170fe5c8SBarry Smith {
4398170fe5c8SBarry Smith   PetscErrorCode ierr;
4399d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
440086214ceeSStefano Zampini   PetscBool      cisdense;
4401170fe5c8SBarry Smith 
4402170fe5c8SBarry Smith   PetscFunctionBegin;
440360e0710aSBarry 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);
44044222ddf1SHong Zhang   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
44054222ddf1SHong Zhang   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
440686214ceeSStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
440786214ceeSStefano Zampini   if (!cisdense) {
440886214ceeSStefano Zampini     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
440986214ceeSStefano Zampini   }
441086214ceeSStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
4411d73949e8SHong Zhang 
44124222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4413170fe5c8SBarry Smith   PetscFunctionReturn(0);
4414170fe5c8SBarry Smith }
4415170fe5c8SBarry Smith 
4416170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
44170bad9183SKris Buschelman /*MC
4418fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
44190bad9183SKris Buschelman    based on compressed sparse row format.
44200bad9183SKris Buschelman 
44210bad9183SKris Buschelman    Options Database Keys:
44220bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
44230bad9183SKris Buschelman 
44240bad9183SKris Buschelman    Level: beginner
44250bad9183SKris Buschelman 
44260cd7f59aSBarry Smith    Notes:
44270cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
44280cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
44290cd7f59aSBarry Smith     in the matrix
44300cd7f59aSBarry Smith 
44310cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
44320cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
44330cd7f59aSBarry Smith 
44340cd7f59aSBarry Smith   Developer Notes:
44350cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
44360cd7f59aSBarry Smith 
4437f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
44380bad9183SKris Buschelman M*/
44390bad9183SKris Buschelman 
4440ccd284c7SBarry Smith /*MC
4441ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4442ccd284c7SBarry Smith 
4443ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4444ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
44450cd7f59aSBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4446ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4447ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4448ccd284c7SBarry Smith 
4449ccd284c7SBarry Smith    Options Database Keys:
4450ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4451ccd284c7SBarry Smith 
445295452b02SPatrick Sanan   Developer Notes:
4453ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4454ccd284c7SBarry Smith    enough exist.
4455ccd284c7SBarry Smith 
4456ccd284c7SBarry Smith   Level: beginner
4457ccd284c7SBarry Smith 
4458ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4459ccd284c7SBarry Smith M*/
4460ccd284c7SBarry Smith 
4461ccd284c7SBarry Smith /*MC
4462ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4463ccd284c7SBarry Smith 
4464ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4465ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4466ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4467ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4468ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4469ccd284c7SBarry Smith 
4470ccd284c7SBarry Smith    Options Database Keys:
4471ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4472ccd284c7SBarry Smith 
4473ccd284c7SBarry Smith   Level: beginner
4474ccd284c7SBarry Smith 
4475ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4476ccd284c7SBarry Smith M*/
4477ccd284c7SBarry Smith 
44787906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
44797906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
44807906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
44817906f579SHong Zhang #endif
4482d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4483d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4484d24d4204SJose E. Roman #endif
44857906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
44867906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
44877906f579SHong Zhang #endif
44887906f579SHong Zhang 
4489d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4490c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
44914222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
44927906f579SHong Zhang 
44938c778c55SBarry Smith /*@C
44948f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
44958c778c55SBarry Smith 
44968c778c55SBarry Smith    Not Collective
44978c778c55SBarry Smith 
44988c778c55SBarry Smith    Input Parameter:
4499579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
45008c778c55SBarry Smith 
45018c778c55SBarry Smith    Output Parameter:
45028c778c55SBarry Smith .   array - pointer to the data
45038c778c55SBarry Smith 
45048c778c55SBarry Smith    Level: intermediate
45058c778c55SBarry Smith 
4506774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
45078c778c55SBarry Smith @*/
45088c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
45098c778c55SBarry Smith {
45108c778c55SBarry Smith   PetscErrorCode ierr;
4511d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
45128c778c55SBarry Smith 
45138c778c55SBarry Smith   PetscFunctionBegin;
4514d67d9f35SJunchao Zhang   if (aij->ops->getarray) {
4515d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarray)(A,array);CHKERRQ(ierr);
4516d67d9f35SJunchao Zhang   } else {
4517d67d9f35SJunchao Zhang     *array = aij->a;
4518d67d9f35SJunchao Zhang   }
4519d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4520d67d9f35SJunchao Zhang }
4521d67d9f35SJunchao Zhang 
4522d67d9f35SJunchao Zhang /*@C
4523d67d9f35SJunchao Zhang    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
4524d67d9f35SJunchao Zhang 
4525d67d9f35SJunchao Zhang    Not Collective
4526d67d9f35SJunchao Zhang 
4527d67d9f35SJunchao Zhang    Input Parameters:
4528d67d9f35SJunchao Zhang +  mat - a MATSEQAIJ matrix
4529d67d9f35SJunchao Zhang -  array - pointer to the data
4530d67d9f35SJunchao Zhang 
4531d67d9f35SJunchao Zhang    Level: intermediate
4532d67d9f35SJunchao Zhang 
4533d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
4534d67d9f35SJunchao Zhang @*/
4535d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
4536d67d9f35SJunchao Zhang {
4537d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4538d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4539d67d9f35SJunchao Zhang 
4540d67d9f35SJunchao Zhang   PetscFunctionBegin;
4541d67d9f35SJunchao Zhang   if (aij->ops->restorearray) {
4542d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearray)(A,array);CHKERRQ(ierr);
4543d67d9f35SJunchao Zhang   } else {
4544d67d9f35SJunchao Zhang     *array = NULL;
4545d67d9f35SJunchao Zhang   }
45468c778c55SBarry Smith   PetscFunctionReturn(0);
45478c778c55SBarry Smith }
45488c778c55SBarry Smith 
454921e72a00SBarry Smith /*@C
45508f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
45518f1ea47aSStefano Zampini 
45528f1ea47aSStefano Zampini    Not Collective
45538f1ea47aSStefano Zampini 
45548f1ea47aSStefano Zampini    Input Parameter:
45558f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
45568f1ea47aSStefano Zampini 
45578f1ea47aSStefano Zampini    Output Parameter:
45588f1ea47aSStefano Zampini .   array - pointer to the data
45598f1ea47aSStefano Zampini 
45608f1ea47aSStefano Zampini    Level: intermediate
45618f1ea47aSStefano Zampini 
45628f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
45638f1ea47aSStefano Zampini @*/
45648f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
45658f1ea47aSStefano Zampini {
45668f1ea47aSStefano Zampini   PetscErrorCode ierr;
4567d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
45688f1ea47aSStefano Zampini 
45698f1ea47aSStefano Zampini   PetscFunctionBegin;
4570d67d9f35SJunchao Zhang   if (aij->ops->getarrayread) {
4571d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarrayread)(A,array);CHKERRQ(ierr);
4572d67d9f35SJunchao Zhang   } else {
4573d67d9f35SJunchao Zhang     *array = aij->a;
4574d67d9f35SJunchao Zhang   }
45758f1ea47aSStefano Zampini   PetscFunctionReturn(0);
45768f1ea47aSStefano Zampini }
45778f1ea47aSStefano Zampini 
45788f1ea47aSStefano Zampini /*@C
45798f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
45808f1ea47aSStefano Zampini 
45818f1ea47aSStefano Zampini    Not Collective
45828f1ea47aSStefano Zampini 
45838f1ea47aSStefano Zampini    Input Parameter:
45848f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
45858f1ea47aSStefano Zampini 
45868f1ea47aSStefano Zampini    Output Parameter:
45878f1ea47aSStefano Zampini .   array - pointer to the data
45888f1ea47aSStefano Zampini 
45898f1ea47aSStefano Zampini    Level: intermediate
45908f1ea47aSStefano Zampini 
45918f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
45928f1ea47aSStefano Zampini @*/
45938f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
45948f1ea47aSStefano Zampini {
45958f1ea47aSStefano Zampini   PetscErrorCode ierr;
4596d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
45978f1ea47aSStefano Zampini 
45988f1ea47aSStefano Zampini   PetscFunctionBegin;
4599d67d9f35SJunchao Zhang   if (aij->ops->restorearrayread) {
4600d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearrayread)(A,array);CHKERRQ(ierr);
4601d67d9f35SJunchao Zhang   } else {
4602d67d9f35SJunchao Zhang     *array = NULL;
4603d67d9f35SJunchao Zhang   }
4604d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4605d67d9f35SJunchao Zhang }
4606d67d9f35SJunchao Zhang 
4607d67d9f35SJunchao Zhang /*@C
4608d67d9f35SJunchao Zhang    MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a MATSEQAIJ matrix is stored
4609d67d9f35SJunchao Zhang 
4610d67d9f35SJunchao Zhang    Not Collective
4611d67d9f35SJunchao Zhang 
4612d67d9f35SJunchao Zhang    Input Parameter:
4613d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4614d67d9f35SJunchao Zhang 
4615d67d9f35SJunchao Zhang    Output Parameter:
4616d67d9f35SJunchao Zhang .   array - pointer to the data
4617d67d9f35SJunchao Zhang 
4618d67d9f35SJunchao Zhang    Level: intermediate
4619d67d9f35SJunchao Zhang 
4620d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
4621d67d9f35SJunchao Zhang @*/
4622d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJGetArrayWrite(Mat A,PetscScalar **array)
4623d67d9f35SJunchao Zhang {
4624d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4625d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4626d67d9f35SJunchao Zhang 
4627d67d9f35SJunchao Zhang   PetscFunctionBegin;
4628d67d9f35SJunchao Zhang   if (aij->ops->getarraywrite) {
4629d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarraywrite)(A,array);CHKERRQ(ierr);
4630d67d9f35SJunchao Zhang   } else {
4631d67d9f35SJunchao Zhang     *array = aij->a;
4632d67d9f35SJunchao Zhang   }
4633d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4634d67d9f35SJunchao Zhang }
4635d67d9f35SJunchao Zhang 
4636d67d9f35SJunchao Zhang /*@C
4637d67d9f35SJunchao Zhang    MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead
4638d67d9f35SJunchao Zhang 
4639d67d9f35SJunchao Zhang    Not Collective
4640d67d9f35SJunchao Zhang 
4641d67d9f35SJunchao Zhang    Input Parameter:
4642d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4643d67d9f35SJunchao Zhang 
4644d67d9f35SJunchao Zhang    Output Parameter:
4645d67d9f35SJunchao Zhang .   array - pointer to the data
4646d67d9f35SJunchao Zhang 
4647d67d9f35SJunchao Zhang    Level: intermediate
4648d67d9f35SJunchao Zhang 
4649d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
4650d67d9f35SJunchao Zhang @*/
4651d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArrayWrite(Mat A,PetscScalar **array)
4652d67d9f35SJunchao Zhang {
4653d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4654d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4655d67d9f35SJunchao Zhang 
4656d67d9f35SJunchao Zhang   PetscFunctionBegin;
4657d67d9f35SJunchao Zhang   if (aij->ops->restorearraywrite) {
4658d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearraywrite)(A,array);CHKERRQ(ierr);
4659d67d9f35SJunchao Zhang   } else {
4660d67d9f35SJunchao Zhang     *array = NULL;
4661d67d9f35SJunchao Zhang   }
46628f1ea47aSStefano Zampini   PetscFunctionReturn(0);
46638f1ea47aSStefano Zampini }
46648f1ea47aSStefano Zampini 
46658f1ea47aSStefano Zampini /*@C
466621e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
466721e72a00SBarry Smith 
466821e72a00SBarry Smith    Not Collective
466921e72a00SBarry Smith 
467021e72a00SBarry Smith    Input Parameter:
4671579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
467221e72a00SBarry Smith 
467321e72a00SBarry Smith    Output Parameter:
467421e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
467521e72a00SBarry Smith 
467621e72a00SBarry Smith    Level: intermediate
467721e72a00SBarry Smith 
467821e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
467921e72a00SBarry Smith @*/
468021e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
468121e72a00SBarry Smith {
468221e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
468321e72a00SBarry Smith 
468421e72a00SBarry Smith   PetscFunctionBegin;
468521e72a00SBarry Smith   *nz = aij->rmax;
468621e72a00SBarry Smith   PetscFunctionReturn(0);
468721e72a00SBarry Smith }
468821e72a00SBarry Smith 
468934b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
46905063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat,MatType,MatReuse,Mat*);
469102fe1965SBarry Smith #endif
46923d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
46935063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat,MatType,MatReuse,Mat*);
46943d0639e7SStefano Zampini #endif
469502fe1965SBarry Smith 
46968cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4697273d9f13SBarry Smith {
4698273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4699dfbe8321SBarry Smith   PetscErrorCode ierr;
470038baddfdSBarry Smith   PetscMPIInt    size;
4701273d9f13SBarry Smith 
4702273d9f13SBarry Smith   PetscFunctionBegin;
4703ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRMPI(ierr);
4704e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4705273d9f13SBarry Smith 
4706b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
47072205254eSKarl Rupp 
4708b0a32e0cSBarry Smith   B->data = (void*)b;
47092205254eSKarl Rupp 
4710549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4711071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
47122205254eSKarl Rupp 
4713f4259b30SLisandro Dalcin   b->row                = NULL;
4714f4259b30SLisandro Dalcin   b->col                = NULL;
4715f4259b30SLisandro Dalcin   b->icol               = NULL;
4716b810aeb4SBarry Smith   b->reallocs           = 0;
471736db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4718f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4719416022c9SBarry Smith   b->nonew              = 0;
4720f4259b30SLisandro Dalcin   b->diag               = NULL;
4721f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4722f4259b30SLisandro Dalcin   B->spptr              = NULL;
4723f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4724f4259b30SLisandro Dalcin   b->idiag              = NULL;
4725f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4726f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
472771f1c65dSBarry Smith   b->omega              = 1.0;
472871f1c65dSBarry Smith   b->fshift             = 0.0;
472971f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4730bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4731a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
473217ab2063SBarry Smith 
473335d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
47348c778c55SBarry Smith 
4735b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4736bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4737bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4738b3866ffcSBarry Smith #endif
473917f1a0eaSHong Zhang 
4740bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4741bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4742bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4743bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4744bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4745bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
47464dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
47479779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
47484a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4749191b95cbSRichard Tran Mills #endif
475034b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
475102fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
47524222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4753fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
475402fe1965SBarry Smith #endif
47553d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
47563d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
47573d0639e7SStefano Zampini #endif
4758bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4759af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4760af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4761af8000cdSHong Zhang #endif
4762d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4763d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4764d24d4204SJose E. Roman #endif
476563c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
476663c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
47674222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
476863c07aadSStefano Zampini #endif
4769b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4770d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4771c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4772bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4773bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4774bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4775846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4776bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4777bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
47784222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
47794222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
47804222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4781ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ);CHKERRQ(ierr);
47824108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
478317667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
47844099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
47853a40ed3dSBarry Smith   PetscFunctionReturn(0);
478617ab2063SBarry Smith }
478717ab2063SBarry Smith 
4788b24902e0SBarry Smith /*
4789b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4790b24902e0SBarry Smith */
4791ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
479217ab2063SBarry Smith {
47932a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
47946849ba73SBarry Smith   PetscErrorCode ierr;
4795071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
479617ab2063SBarry Smith 
47973a40ed3dSBarry Smith   PetscFunctionBegin;
4798ca133879SJose E. Roman   if (!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4799273d9f13SBarry Smith 
4800d5f3da31SBarry Smith   C->factortype = A->factortype;
4801f4259b30SLisandro Dalcin   c->row        = NULL;
4802f4259b30SLisandro Dalcin   c->col        = NULL;
4803f4259b30SLisandro Dalcin   c->icol       = NULL;
48046ad4291fSHong Zhang   c->reallocs   = 0;
480517ab2063SBarry Smith 
48066ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
480717ab2063SBarry Smith 
4808aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4809aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4810eec197d1SBarry Smith 
4811071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4812071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4813071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4814071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
48153bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
481617ab2063SBarry Smith 
481717ab2063SBarry Smith   /* allocate the matrix space */
4818f77e22a1SHong Zhang   if (mallocmatspace) {
4819dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
48203bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
48212205254eSKarl Rupp 
4822f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
48232205254eSKarl Rupp 
4824580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
482517ab2063SBarry Smith     if (m > 0) {
4826580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4827be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
48282e5835c6SStefano Zampini         const PetscScalar *aa;
48292e5835c6SStefano Zampini 
48302e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
48312e5835c6SStefano Zampini         ierr = PetscArraycpy(c->a,aa,a->i[m]);CHKERRQ(ierr);
48322e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4833be6bf707SBarry Smith       } else {
4834580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
483517ab2063SBarry Smith       }
483608480c60SBarry Smith     }
4837f77e22a1SHong Zhang   }
483817ab2063SBarry Smith 
48396ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4840416022c9SBarry Smith   c->roworiented       = a->roworiented;
4841416022c9SBarry Smith   c->nonew             = a->nonew;
4842416022c9SBarry Smith   if (a->diag) {
4843854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4844071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
48453bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4846071fcb05SBarry Smith   } else c->diag = NULL;
48472205254eSKarl Rupp 
4848f4259b30SLisandro Dalcin   c->solve_work         = NULL;
4849f4259b30SLisandro Dalcin   c->saved_values       = NULL;
4850f4259b30SLisandro Dalcin   c->idiag              = NULL;
4851f4259b30SLisandro Dalcin   c->ssor_work          = NULL;
4852a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4853e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4854e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
48556ad4291fSHong Zhang 
4856893ad86cSHong Zhang   c->rmax         = a->rmax;
4857416022c9SBarry Smith   c->nz           = a->nz;
48588ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4859273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4860754ec7b1SSatish Balay 
48616ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
48626ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4863cd6b891eSBarry Smith   if (a->compressedrow.use) {
48646ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4865dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4866580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4867580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
486827ea64f8SHong Zhang   } else {
486927ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
48700298fd71SBarry Smith     c->compressedrow.i      = NULL;
48710298fd71SBarry Smith     c->compressedrow.rindex = NULL;
48726ad4291fSHong Zhang   }
4873ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4874e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
48754846f1f5SKris Buschelman 
48762205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4877140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
48783a40ed3dSBarry Smith   PetscFunctionReturn(0);
487917ab2063SBarry Smith }
488017ab2063SBarry Smith 
4881b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4882b24902e0SBarry Smith {
4883b24902e0SBarry Smith   PetscErrorCode ierr;
4884b24902e0SBarry Smith 
4885b24902e0SBarry Smith   PetscFunctionBegin;
4886ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
48874b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4888cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
488933d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4890cfd3f464SBarry Smith   }
4891a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4892f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4893b24902e0SBarry Smith   PetscFunctionReturn(0);
4894b24902e0SBarry Smith }
4895b24902e0SBarry Smith 
4896112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4897fbdbba38SShri Abhyankar {
489852f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
489952f91c60SVaclav Hapla   PetscErrorCode ierr;
490052f91c60SVaclav Hapla 
490152f91c60SVaclav Hapla   PetscFunctionBegin;
490252f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
490352f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4904c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4905c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
490652f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
490752f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
490852f91c60SVaclav Hapla   if (isbinary) {
490952f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
491052f91c60SVaclav Hapla   } else if (ishdf5) {
491152f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
491252f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
491352f91c60SVaclav Hapla #else
491452f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
491552f91c60SVaclav Hapla #endif
491652f91c60SVaclav Hapla   } else {
491752f91c60SVaclav 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);
491852f91c60SVaclav Hapla   }
491952f91c60SVaclav Hapla   PetscFunctionReturn(0);
492052f91c60SVaclav Hapla }
492152f91c60SVaclav Hapla 
49223ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
492352f91c60SVaclav Hapla {
49243ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
4925fbdbba38SShri Abhyankar   PetscErrorCode ierr;
49263ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4927fbdbba38SShri Abhyankar 
4928fbdbba38SShri Abhyankar   PetscFunctionBegin;
49293ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4930bbead8a2SBarry Smith 
49313ea6fe3dSLisandro Dalcin   /* read in matrix header */
49323ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
49333ea6fe3dSLisandro Dalcin   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4934fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
49353ea6fe3dSLisandro Dalcin   if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%D) in file is negative",M);
49363ea6fe3dSLisandro Dalcin   if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%D) in file is negative",N);
4937bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4938fbdbba38SShri Abhyankar 
49393ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
49403ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
49413ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
49423ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
49433ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
49443ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
49453ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
49463ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
49473ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
49483ea6fe3dSLisandro Dalcin 
49493ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
49503ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
49513ea6fe3dSLisandro 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);
49523ea6fe3dSLisandro Dalcin 
4953fbdbba38SShri Abhyankar   /* read in row lengths */
49543ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
49553ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
49563ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
49573ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
49583ea6fe3dSLisandro 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);
49593ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
49603ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
49613ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
496260e0710aSBarry 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);
49633ea6fe3dSLisandro Dalcin   /* store row lengths */
49643ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
49653ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
4966fbdbba38SShri Abhyankar 
49673ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
49683ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
49693ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
49703ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
49713ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
49723ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4973fbdbba38SShri Abhyankar 
49743ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
49753ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4976fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4977fbdbba38SShri Abhyankar }
4978fbdbba38SShri Abhyankar 
4979ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
49807264ac53SSatish Balay {
49817264ac53SSatish Balay   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4982dfbe8321SBarry Smith   PetscErrorCode    ierr;
4983*fff043a9SJunchao Zhang   const PetscScalar *aa,*ba;
4984eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4985eeffb40dSHong Zhang   PetscInt k;
4986eeffb40dSHong Zhang #endif
49877264ac53SSatish Balay 
49883a40ed3dSBarry Smith   PetscFunctionBegin;
4989bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4990d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4991ca44d042SBarry Smith     *flg = PETSC_FALSE;
4992ca44d042SBarry Smith     PetscFunctionReturn(0);
4993bcd2baecSBarry Smith   }
49947264ac53SSatish Balay 
49957264ac53SSatish Balay   /* if the a->i are the same */
4996580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4997abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
49987264ac53SSatish Balay 
49997264ac53SSatish Balay   /* if a->j are the same */
5000580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
5001abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
5002bcd2baecSBarry Smith 
5003*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
5004*fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(B,&ba);CHKERRQ(ierr);
5005bcd2baecSBarry Smith   /* if a->a are the same */
5006eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5007eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
5008*fff043a9SJunchao Zhang     if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) {
5009eeffb40dSHong Zhang       *flg = PETSC_FALSE;
50103a40ed3dSBarry Smith       PetscFunctionReturn(0);
5011eeffb40dSHong Zhang     }
5012eeffb40dSHong Zhang   }
5013eeffb40dSHong Zhang #else
5014*fff043a9SJunchao Zhang   ierr = PetscArraycmp(aa,ba,a->nz,flg);CHKERRQ(ierr);
5015eeffb40dSHong Zhang #endif
5016*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
5017*fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(B,&ba);CHKERRQ(ierr);
5018eeffb40dSHong Zhang   PetscFunctionReturn(0);
50197264ac53SSatish Balay }
502036db0b34SBarry Smith 
502105869f15SSatish Balay /*@
502236db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
502336db0b34SBarry Smith               provided by the user.
502436db0b34SBarry Smith 
5025d083f849SBarry Smith       Collective
502636db0b34SBarry Smith 
502736db0b34SBarry Smith    Input Parameters:
502836db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
502936db0b34SBarry Smith .   m - number of rows
503036db0b34SBarry Smith .   n - number of columns
5031483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
503236db0b34SBarry Smith .   j - column indices
503336db0b34SBarry Smith -   a - matrix values
503436db0b34SBarry Smith 
503536db0b34SBarry Smith    Output Parameter:
503636db0b34SBarry Smith .   mat - the matrix
503736db0b34SBarry Smith 
503836db0b34SBarry Smith    Level: intermediate
503936db0b34SBarry Smith 
504036db0b34SBarry Smith    Notes:
50410551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
5042292fb18eSBarry Smith     once the matrix is destroyed and not before
504336db0b34SBarry Smith 
504436db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
504536db0b34SBarry Smith 
5046bfeeae90SHong Zhang        The i and j indices are 0 based
504736db0b34SBarry Smith 
5048a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
5049a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
50508eef79e4SBarry Smith     as shown
5051a4552177SSatish Balay 
50528eef79e4SBarry Smith $        1 0 0
50538eef79e4SBarry Smith $        2 0 3
50548eef79e4SBarry Smith $        4 5 6
50558eef79e4SBarry Smith $
50568eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
50578eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
50588eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
5059a4552177SSatish Balay 
506069b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
506136db0b34SBarry Smith 
506236db0b34SBarry Smith @*/
5063c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
506436db0b34SBarry Smith {
5065dfbe8321SBarry Smith   PetscErrorCode ierr;
5066cbcfb4deSHong Zhang   PetscInt       ii;
506736db0b34SBarry Smith   Mat_SeqAIJ     *aij;
5068cbcfb4deSHong Zhang   PetscInt jj;
506936db0b34SBarry Smith 
507036db0b34SBarry Smith   PetscFunctionBegin;
507141096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
5072f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
5073f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
5074a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
5075ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
5076f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
5077ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
5078071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
5079071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
5080ab93d7beSBarry Smith 
508136db0b34SBarry Smith   aij->i            = i;
508236db0b34SBarry Smith   aij->j            = j;
508336db0b34SBarry Smith   aij->a            = a;
508436db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
508536db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
5086e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
5087e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
508836db0b34SBarry Smith 
508936db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
509036db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
509176bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
509260e0710aSBarry 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]);
50939985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
5094a061629eSStefano 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);
5095a061629eSStefano 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);
50969985e31cSBarry Smith       }
509736db0b34SBarry Smith     }
509876bd3646SJed Brown   }
509976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
510036db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
510160e0710aSBarry Smith       if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
510260e0710aSBarry 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]);
510336db0b34SBarry Smith     }
510476bd3646SJed Brown   }
510536db0b34SBarry Smith 
5106b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5107b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
510836db0b34SBarry Smith   PetscFunctionReturn(0);
510936db0b34SBarry Smith }
511080ef6e79SMatthew G Knepley /*@C
5111d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
51128a0b0e6bSVictor Minden               provided by the user.
51138a0b0e6bSVictor Minden 
5114d083f849SBarry Smith       Collective
51158a0b0e6bSVictor Minden 
51168a0b0e6bSVictor Minden    Input Parameters:
51178a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
51188a0b0e6bSVictor Minden .   m   - number of rows
51198a0b0e6bSVictor Minden .   n   - number of columns
51208a0b0e6bSVictor Minden .   i   - row indices
51218a0b0e6bSVictor Minden .   j   - column indices
51221230e6d1SVictor Minden .   a   - matrix values
51231230e6d1SVictor Minden .   nz  - number of nonzeros
51241230e6d1SVictor Minden -   idx - 0 or 1 based
51258a0b0e6bSVictor Minden 
51268a0b0e6bSVictor Minden    Output Parameter:
51278a0b0e6bSVictor Minden .   mat - the matrix
51288a0b0e6bSVictor Minden 
51298a0b0e6bSVictor Minden    Level: intermediate
51308a0b0e6bSVictor Minden 
51318a0b0e6bSVictor Minden    Notes:
51329e99939fSJunchao 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,
51339e99939fSJunchao Zhang        the input data expected is as shown
51349e99939fSJunchao Zhang .vb
51358a0b0e6bSVictor Minden         1 0 0
51368a0b0e6bSVictor Minden         2 0 3
51378a0b0e6bSVictor Minden         4 5 6
51388a0b0e6bSVictor Minden 
51398a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
51408a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
51418a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
51429e99939fSJunchao Zhang .ve
51438a0b0e6bSVictor Minden 
514469b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
51458a0b0e6bSVictor Minden 
51468a0b0e6bSVictor Minden @*/
5147c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
51488a0b0e6bSVictor Minden {
51498a0b0e6bSVictor Minden   PetscErrorCode ierr;
5150d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
51518a0b0e6bSVictor Minden 
51528a0b0e6bSVictor Minden   PetscFunctionBegin;
51531795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
51541230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
5155c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
51561230e6d1SVictor Minden   }
51578a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
51588a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
51598a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
51601230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
51611230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
51621230e6d1SVictor Minden     if (idx) {
51631230e6d1SVictor Minden       row = i[ii] - 1;
51641230e6d1SVictor Minden       col = j[ii] - 1;
51651230e6d1SVictor Minden     } else {
51661230e6d1SVictor Minden       row = i[ii];
51671230e6d1SVictor Minden       col = j[ii];
51688a0b0e6bSVictor Minden     }
51691230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
51708a0b0e6bSVictor Minden   }
51718a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
51728a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5173d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
51748a0b0e6bSVictor Minden   PetscFunctionReturn(0);
51758a0b0e6bSVictor Minden }
517636db0b34SBarry Smith 
5177acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5178acf2f550SJed Brown {
5179acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5180acf2f550SJed Brown   PetscErrorCode ierr;
5181acf2f550SJed Brown 
5182acf2f550SJed Brown   PetscFunctionBegin;
5183acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5184acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
51852205254eSKarl Rupp 
5186acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
5187acf2f550SJed Brown   PetscFunctionReturn(0);
5188acf2f550SJed Brown }
5189acf2f550SJed Brown 
51909c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
51919c8f2541SHong Zhang {
51929c8f2541SHong Zhang   PetscErrorCode ierr;
51938761c3d6SHong Zhang   PetscMPIInt    size;
51949c8f2541SHong Zhang 
51959c8f2541SHong Zhang   PetscFunctionBegin;
5196ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
51977bbdc51dSHong Zhang   if (size == 1) {
51987bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
51997bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
52007bbdc51dSHong Zhang     } else {
52018761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
52027bbdc51dSHong Zhang     }
52038761c3d6SHong Zhang   } else {
52049c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
52058761c3d6SHong Zhang   }
52069c8f2541SHong Zhang   PetscFunctionReturn(0);
52079c8f2541SHong Zhang }
52089c8f2541SHong Zhang 
520981824310SBarry Smith /*
521053dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
521153dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
521253dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
521353dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
521453dd7562SDmitry Karpeev  */
521553dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
521653dd7562SDmitry Karpeev {
521753dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
521853dd7562SDmitry Karpeev   PetscErrorCode ierr;
521953dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
522053dd7562SDmitry Karpeev   PetscBool      seqaij;
522153dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
522253dd7562SDmitry Karpeev   PetscScalar    v;
522353dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
522453dd7562SDmitry Karpeev 
522553dd7562SDmitry Karpeev   PetscFunctionBegin;
522653dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
522753dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
52284099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
522953dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
523053dd7562SDmitry Karpeev   if (rowemb) {
523153dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
523253dd7562SDmitry 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);
523353dd7562SDmitry Karpeev   } else {
52346c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
523553dd7562SDmitry Karpeev   }
523653dd7562SDmitry Karpeev   if (colemb) {
523753dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
523853dd7562SDmitry 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);
523953dd7562SDmitry Karpeev   } else {
524053dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
524153dd7562SDmitry Karpeev   }
524253dd7562SDmitry Karpeev 
524353dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
524453dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
524553dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
524653dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
524753dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
524853dd7562SDmitry Karpeev     }
524953dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
525053dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
525153dd7562SDmitry Karpeev   }
525253dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
525353dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
525453dd7562SDmitry Karpeev   }
525553dd7562SDmitry Karpeev   count = 0;
525653dd7562SDmitry Karpeev   rowindices = NULL;
525753dd7562SDmitry Karpeev   colindices = NULL;
525853dd7562SDmitry Karpeev   if (rowemb) {
525953dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
526053dd7562SDmitry Karpeev   }
526153dd7562SDmitry Karpeev   if (colemb) {
526253dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
526353dd7562SDmitry Karpeev   }
526453dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
526553dd7562SDmitry Karpeev     PetscInt row;
526653dd7562SDmitry Karpeev     row = i;
526753dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
526853dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
526953dd7562SDmitry Karpeev       PetscInt col;
527053dd7562SDmitry Karpeev       col  = Baij->j[count];
527153dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
527253dd7562SDmitry Karpeev       v    = Baij->a[count];
527353dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
527453dd7562SDmitry Karpeev       ++count;
527553dd7562SDmitry Karpeev     }
527653dd7562SDmitry Karpeev   }
527753dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
527853dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
527953dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
528053dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
528153dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
528253dd7562SDmitry Karpeev   PetscFunctionReturn(0);
528353dd7562SDmitry Karpeev }
528453dd7562SDmitry Karpeev 
52854099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
52864099cc6bSBarry Smith 
52874099cc6bSBarry Smith /*@C
52884099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
52894099cc6bSBarry Smith 
52904099cc6bSBarry Smith    Collective on Mat
52914099cc6bSBarry Smith 
52924099cc6bSBarry Smith    Input Parameters:
52934099cc6bSBarry Smith +  mat      - the matrix object
52944099cc6bSBarry Smith -  matype   - matrix type
52954099cc6bSBarry Smith 
52964099cc6bSBarry Smith    Options Database Key:
52974099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
52984099cc6bSBarry Smith 
52994099cc6bSBarry Smith   Level: intermediate
53004099cc6bSBarry Smith 
53014099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
53024099cc6bSBarry Smith @*/
53034099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
53044099cc6bSBarry Smith {
5305fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
53064099cc6bSBarry Smith   PetscBool      sametype;
53074099cc6bSBarry Smith 
53084099cc6bSBarry Smith   PetscFunctionBegin;
53094099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
53104099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
53114099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
53124099cc6bSBarry Smith 
53134099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
53144099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
53154099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
53164099cc6bSBarry Smith   PetscFunctionReturn(0);
53174099cc6bSBarry Smith }
53184099cc6bSBarry Smith 
53194099cc6bSBarry Smith /*@C
53204099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
53214099cc6bSBarry Smith 
53224099cc6bSBarry Smith    Not Collective
53234099cc6bSBarry Smith 
53244099cc6bSBarry Smith    Input Parameters:
53254099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
53264099cc6bSBarry Smith -  function - routine to convert to subtype
53274099cc6bSBarry Smith 
53284099cc6bSBarry Smith    Notes:
53294099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
53304099cc6bSBarry Smith 
53314099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
53324099cc6bSBarry Smith $     -mat_seqaij_type my_mat
53334099cc6bSBarry Smith 
53344099cc6bSBarry Smith    Level: advanced
53354099cc6bSBarry Smith 
53364099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
53374099cc6bSBarry Smith 
53384099cc6bSBarry Smith   Level: advanced
53394099cc6bSBarry Smith @*/
5340388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
53414099cc6bSBarry Smith {
53424099cc6bSBarry Smith   PetscErrorCode ierr;
53434099cc6bSBarry Smith 
53444099cc6bSBarry Smith   PetscFunctionBegin;
53459cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
53464099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
53474099cc6bSBarry Smith   PetscFunctionReturn(0);
53484099cc6bSBarry Smith }
53494099cc6bSBarry Smith 
53504099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
53514099cc6bSBarry Smith 
53524099cc6bSBarry Smith /*@C
53534099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
53544099cc6bSBarry Smith 
53554099cc6bSBarry Smith   Not Collective
53564099cc6bSBarry Smith 
53574099cc6bSBarry Smith   Level: advanced
53584099cc6bSBarry Smith 
53594099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
53604099cc6bSBarry Smith @*/
53614099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
53624099cc6bSBarry Smith {
53634099cc6bSBarry Smith   PetscErrorCode ierr;
53644099cc6bSBarry Smith 
53654099cc6bSBarry Smith   PetscFunctionBegin;
53664099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
53674099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
53684099cc6bSBarry Smith 
53694099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
53704099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
53714dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
53729779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
53736b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5374485f9817SRichard Tran Mills #endif
53755063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA)
53765063d097SStefano Zampini   ierr = MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
53775063d097SStefano Zampini #endif
53785063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
53795063d097SStefano Zampini   ierr = MatSeqAIJRegister(MATSEQAIJKOKKOS,   MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
53805063d097SStefano Zampini #endif
53814099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
53824099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
53834099cc6bSBarry Smith #endif
53844099cc6bSBarry Smith   PetscFunctionReturn(0);
53854099cc6bSBarry Smith }
538653dd7562SDmitry Karpeev 
538753dd7562SDmitry Karpeev /*
538881824310SBarry Smith     Special version for direct calls from Fortran
538981824310SBarry Smith */
5390af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
539181824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
539281824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
539381824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
539481824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
539581824310SBarry Smith #endif
539681824310SBarry Smith 
539781824310SBarry Smith /* Change these macros so can be used in void function */
539881824310SBarry Smith #undef CHKERRQ
53992e58f0efSBarry Smith #define CHKERRQ(err) CHKERRABORT(PetscObjectComm((PetscObject)A),err)
540081824310SBarry Smith #undef SETERRQ2
54012e58f0efSBarry Smith #define SETERRQ2(comm,err,b,c,d) CHKERRABORT(comm,err)
54024994cf47SJed Brown #undef SETERRQ3
54032e58f0efSBarry Smith #define SETERRQ3(comm,err,b,c,d,e) CHKERRABORT(comm,err)
540481824310SBarry Smith 
540519caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
540681824310SBarry Smith {
540781824310SBarry Smith   Mat            A  = *AA;
540881824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
540981824310SBarry Smith   InsertMode     is = *isis;
541081824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
541181824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
541281824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
541381824310SBarry Smith   PetscErrorCode ierr;
541481824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
541554f21887SBarry Smith   MatScalar      *ap,value,*aa;
5416ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5417ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
541881824310SBarry Smith 
541981824310SBarry Smith   PetscFunctionBegin;
54204994cf47SJed Brown   MatCheckPreallocated(A,1);
542181824310SBarry Smith   imax  = a->imax;
542281824310SBarry Smith   ai    = a->i;
542381824310SBarry Smith   ailen = a->ilen;
542481824310SBarry Smith   aj    = a->j;
542581824310SBarry Smith   aa    = a->a;
542681824310SBarry Smith 
542781824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
542881824310SBarry Smith     row = im[k];
542981824310SBarry Smith     if (row < 0) continue;
5430cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
543181824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
543281824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
543381824310SBarry Smith     low  = 0;
543481824310SBarry Smith     high = nrow;
543581824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
543681824310SBarry Smith       if (in[l] < 0) continue;
5437cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
543881824310SBarry Smith       col = in[l];
54392205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
54402205254eSKarl Rupp       else value = v[k + l*m];
54412205254eSKarl Rupp 
544281824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
544381824310SBarry Smith 
54442205254eSKarl Rupp       if (col <= lastcol) low = 0;
54452205254eSKarl Rupp       else high = nrow;
544681824310SBarry Smith       lastcol = col;
544781824310SBarry Smith       while (high-low > 5) {
544881824310SBarry Smith         t = (low+high)/2;
544981824310SBarry Smith         if (rp[t] > col) high = t;
545081824310SBarry Smith         else             low  = t;
545181824310SBarry Smith       }
545281824310SBarry Smith       for (i=low; i<high; i++) {
545381824310SBarry Smith         if (rp[i] > col) break;
545481824310SBarry Smith         if (rp[i] == col) {
545581824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
545681824310SBarry Smith           else                  ap[i] = value;
545781824310SBarry Smith           goto noinsert;
545881824310SBarry Smith         }
545981824310SBarry Smith       }
546081824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
546181824310SBarry Smith       if (nonew == 1) goto noinsert;
5462ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5463fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
546481824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
546581824310SBarry Smith       /* shift up all the later entries in this row */
546681824310SBarry Smith       for (ii=N; ii>=i; ii--) {
546781824310SBarry Smith         rp[ii+1] = rp[ii];
546881824310SBarry Smith         ap[ii+1] = ap[ii];
546981824310SBarry Smith       }
547081824310SBarry Smith       rp[i] = col;
547181824310SBarry Smith       ap[i] = value;
5472e56f5c9eSBarry Smith       A->nonzerostate++;
547381824310SBarry Smith noinsert:;
547481824310SBarry Smith       low = i + 1;
547581824310SBarry Smith     }
547681824310SBarry Smith     ailen[row] = nrow;
547781824310SBarry Smith   }
547881824310SBarry Smith   PetscFunctionReturnVoid();
547981824310SBarry Smith }
5480