xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 3ea6fe3deafcf7110bb325a46d9e95bff484222a)
1b377110cSBarry Smith 
2d5d45c9bSBarry Smith /*
33369ce9aSBarry Smith     Defines the basic matrix operations for the AIJ (compressed row)
4d5d45c9bSBarry Smith   matrix storage format.
5d5d45c9bSBarry Smith */
63369ce9aSBarry Smith 
77c4f633dSBarry Smith 
8c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>          /*I "petscmat.h" I*/
9c6db04a5SJed Brown #include <petscblaslapack.h>
10c6db04a5SJed Brown #include <petscbt.h>
11af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h>
120716a85fSBarry Smith 
134099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A)
144099cc6bSBarry Smith {
154099cc6bSBarry Smith   PetscErrorCode       ierr;
164099cc6bSBarry Smith   PetscBool            flg;
174099cc6bSBarry Smith   char                 type[256];
184099cc6bSBarry Smith 
194099cc6bSBarry Smith   PetscFunctionBegin;
204099cc6bSBarry Smith   ierr = PetscObjectOptionsBegin((PetscObject)A);
214099cc6bSBarry Smith   ierr = PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg);CHKERRQ(ierr);
224099cc6bSBarry Smith   if (flg) {
234099cc6bSBarry Smith     ierr = MatSeqAIJSetType(A,type);CHKERRQ(ierr);
244099cc6bSBarry Smith   }
254099cc6bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
264099cc6bSBarry Smith   PetscFunctionReturn(0);
274099cc6bSBarry Smith }
284099cc6bSBarry Smith 
290716a85fSBarry Smith PetscErrorCode MatGetColumnNorms_SeqAIJ(Mat A,NormType type,PetscReal *norms)
300716a85fSBarry Smith {
310716a85fSBarry Smith   PetscErrorCode ierr;
320716a85fSBarry Smith   PetscInt       i,m,n;
330716a85fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
340716a85fSBarry Smith 
350716a85fSBarry Smith   PetscFunctionBegin;
360716a85fSBarry Smith   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);
37580bdb30SBarry Smith   ierr = PetscArrayzero(norms,n);CHKERRQ(ierr);
380716a85fSBarry Smith   if (type == NORM_2) {
390716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
400716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
410716a85fSBarry Smith     }
420716a85fSBarry Smith   } else if (type == NORM_1) {
430716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
440716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]);
450716a85fSBarry Smith     }
460716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
470716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
480716a85fSBarry Smith       norms[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),norms[aij->j[i]]);
490716a85fSBarry Smith     }
500716a85fSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown NormType");
510716a85fSBarry Smith 
520716a85fSBarry Smith   if (type == NORM_2) {
538f1a2a5eSBarry Smith     for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
540716a85fSBarry Smith   }
550716a85fSBarry Smith   PetscFunctionReturn(0);
560716a85fSBarry Smith }
570716a85fSBarry Smith 
583a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is)
593a062f41SBarry Smith {
603a062f41SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
613a062f41SBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs;
623a062f41SBarry Smith   const PetscInt  *jj = a->j,*ii = a->i;
633a062f41SBarry Smith   PetscInt        *rows;
643a062f41SBarry Smith   PetscErrorCode  ierr;
653a062f41SBarry Smith 
663a062f41SBarry Smith   PetscFunctionBegin;
673a062f41SBarry Smith   for (i=0; i<m; i++) {
683a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
693a062f41SBarry Smith       cnt++;
703a062f41SBarry Smith     }
713a062f41SBarry Smith   }
723a062f41SBarry Smith   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
733a062f41SBarry Smith   cnt  = 0;
743a062f41SBarry Smith   for (i=0; i<m; i++) {
753a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
763a062f41SBarry Smith       rows[cnt] = i;
773a062f41SBarry Smith       cnt++;
783a062f41SBarry Smith     }
793a062f41SBarry Smith   }
803a062f41SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is);CHKERRQ(ierr);
813a062f41SBarry Smith   PetscFunctionReturn(0);
823a062f41SBarry Smith }
833a062f41SBarry Smith 
84f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows)
856ce1633cSBarry Smith {
866ce1633cSBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
876ce1633cSBarry Smith   const MatScalar *aa = a->a;
886ce1633cSBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0;
89b2db7409Sstefano_zampini   const PetscInt  *ii = a->i,*jj = a->j,*diag;
906ce1633cSBarry Smith   PetscInt        *rows;
916ce1633cSBarry Smith   PetscErrorCode  ierr;
926ce1633cSBarry Smith 
936ce1633cSBarry Smith   PetscFunctionBegin;
946ce1633cSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
956ce1633cSBarry Smith   diag = a->diag;
966ce1633cSBarry Smith   for (i=0; i<m; i++) {
97b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
986ce1633cSBarry Smith       cnt++;
996ce1633cSBarry Smith     }
1006ce1633cSBarry Smith   }
101785e854fSJed Brown   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
1026ce1633cSBarry Smith   cnt  = 0;
1036ce1633cSBarry Smith   for (i=0; i<m; i++) {
104b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1056ce1633cSBarry Smith       rows[cnt++] = i;
1066ce1633cSBarry Smith     }
1076ce1633cSBarry Smith   }
108f1f41ecbSJed Brown   *nrows = cnt;
109f1f41ecbSJed Brown   *zrows = rows;
110f1f41ecbSJed Brown   PetscFunctionReturn(0);
111f1f41ecbSJed Brown }
112f1f41ecbSJed Brown 
113f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
114f1f41ecbSJed Brown {
115f1f41ecbSJed Brown   PetscInt       nrows,*rows;
116f1f41ecbSJed Brown   PetscErrorCode ierr;
117f1f41ecbSJed Brown 
118f1f41ecbSJed Brown   PetscFunctionBegin;
1190298fd71SBarry Smith   *zrows = NULL;
120f1f41ecbSJed Brown   ierr   = MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);CHKERRQ(ierr);
121ce94432eSBarry Smith   ierr   = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr);
1226ce1633cSBarry Smith   PetscFunctionReturn(0);
1236ce1633cSBarry Smith }
1246ce1633cSBarry Smith 
125b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
126b3a44c85SBarry Smith {
127b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
128b3a44c85SBarry Smith   const MatScalar *aa;
129b3a44c85SBarry Smith   PetscInt        m=A->rmap->n,cnt = 0;
130b3a44c85SBarry Smith   const PetscInt  *ii;
131b3a44c85SBarry Smith   PetscInt        n,i,j,*rows;
132b3a44c85SBarry Smith   PetscErrorCode  ierr;
133b3a44c85SBarry Smith 
134b3a44c85SBarry Smith   PetscFunctionBegin;
135b3a44c85SBarry Smith   *keptrows = 0;
136b3a44c85SBarry Smith   ii        = a->i;
137b3a44c85SBarry Smith   for (i=0; i<m; i++) {
138b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
139b3a44c85SBarry Smith     if (!n) {
140b3a44c85SBarry Smith       cnt++;
141b3a44c85SBarry Smith       goto ok1;
142b3a44c85SBarry Smith     }
143b3a44c85SBarry Smith     aa = a->a + ii[i];
144b3a44c85SBarry Smith     for (j=0; j<n; j++) {
145b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
146b3a44c85SBarry Smith     }
147b3a44c85SBarry Smith     cnt++;
148b3a44c85SBarry Smith ok1:;
149b3a44c85SBarry Smith   }
150b3a44c85SBarry Smith   if (!cnt) PetscFunctionReturn(0);
151854ce69bSBarry Smith   ierr = PetscMalloc1(A->rmap->n-cnt,&rows);CHKERRQ(ierr);
152b3a44c85SBarry Smith   cnt  = 0;
153b3a44c85SBarry Smith   for (i=0; i<m; i++) {
154b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
155b3a44c85SBarry Smith     if (!n) continue;
156b3a44c85SBarry Smith     aa = a->a + ii[i];
157b3a44c85SBarry Smith     for (j=0; j<n; j++) {
158b3a44c85SBarry Smith       if (aa[j] != 0.0) {
159b3a44c85SBarry Smith         rows[cnt++] = i;
160b3a44c85SBarry Smith         break;
161b3a44c85SBarry Smith       }
162b3a44c85SBarry Smith     }
163b3a44c85SBarry Smith   }
164b3a44c85SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr);
165b3a44c85SBarry Smith   PetscFunctionReturn(0);
166b3a44c85SBarry Smith }
167b3a44c85SBarry Smith 
1687087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
16979299369SBarry Smith {
17079299369SBarry Smith   PetscErrorCode    ierr;
17179299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
17299e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
17399e65526SBarry Smith   const PetscInt    *diag;
17454f21887SBarry Smith   MatScalar         *aa = aij->a;
17599e65526SBarry Smith   const PetscScalar *v;
176ace3abfcSBarry Smith   PetscBool         missing;
177837a59e1SRichard Tran Mills #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
178837a59e1SRichard Tran Mills   PetscBool         inserted = PETSC_FALSE;
179837a59e1SRichard Tran Mills #endif
18079299369SBarry Smith 
18179299369SBarry Smith   PetscFunctionBegin;
18209f38230SBarry Smith   if (Y->assembled) {
1830298fd71SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr);
18409f38230SBarry Smith     if (!missing) {
18579299369SBarry Smith       diag = aij->diag;
18699e65526SBarry Smith       ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr);
18779299369SBarry Smith       if (is == INSERT_VALUES) {
188837a59e1SRichard Tran Mills #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
189837a59e1SRichard Tran Mills         inserted = PETSC_TRUE;
190837a59e1SRichard Tran Mills #endif
19179299369SBarry Smith         for (i=0; i<m; i++) {
19279299369SBarry Smith           aa[diag[i]] = v[i];
19379299369SBarry Smith         }
19479299369SBarry Smith       } else {
19579299369SBarry Smith         for (i=0; i<m; i++) {
196837a59e1SRichard Tran Mills #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
197837a59e1SRichard Tran Mills           if (v[i] != 0.0) inserted = PETSC_TRUE;
198837a59e1SRichard Tran Mills #endif
19979299369SBarry Smith           aa[diag[i]] += v[i];
20079299369SBarry Smith         }
20179299369SBarry Smith       }
202837a59e1SRichard Tran Mills #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
203837a59e1SRichard Tran Mills       if (inserted) Y->offloadmask = PETSC_OFFLOAD_CPU;
204837a59e1SRichard Tran Mills #endif
20599e65526SBarry Smith       ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr);
20679299369SBarry Smith       PetscFunctionReturn(0);
20779299369SBarry Smith     }
208acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
20909f38230SBarry Smith   }
21009f38230SBarry Smith   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
21109f38230SBarry Smith   PetscFunctionReturn(0);
21209f38230SBarry Smith }
21379299369SBarry Smith 
2141a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
21517ab2063SBarry Smith {
216416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
217dfbe8321SBarry Smith   PetscErrorCode ierr;
21897f1f81fSBarry Smith   PetscInt       i,ishift;
21917ab2063SBarry Smith 
2203a40ed3dSBarry Smith   PetscFunctionBegin;
221d0f46423SBarry Smith   *m = A->rmap->n;
2223a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
223bfeeae90SHong Zhang   ishift = 0;
22453e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2252462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
226bfeeae90SHong Zhang   } else if (oshift == 1) {
2271a83f524SJed Brown     PetscInt *tia;
228d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2293b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
230854ce69bSBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr);
2311a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2321a83f524SJed Brown     *ia = tia;
233ecc77c7aSBarry Smith     if (ja) {
2341a83f524SJed Brown       PetscInt *tja;
235854ce69bSBarry Smith       ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr);
2361a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2371a83f524SJed Brown       *ja = tja;
238ecc77c7aSBarry Smith     }
2396945ee14SBarry Smith   } else {
240ecc77c7aSBarry Smith     *ia = a->i;
241ecc77c7aSBarry Smith     if (ja) *ja = a->j;
242a2ce50c7SBarry Smith   }
2433a40ed3dSBarry Smith   PetscFunctionReturn(0);
244a2744918SBarry Smith }
245a2744918SBarry Smith 
2461a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2476945ee14SBarry Smith {
248dfbe8321SBarry Smith   PetscErrorCode ierr;
2496945ee14SBarry Smith 
2503a40ed3dSBarry Smith   PetscFunctionBegin;
2513a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
252bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
253606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
254ecc77c7aSBarry Smith     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
255bcd2baecSBarry Smith   }
2563a40ed3dSBarry Smith   PetscFunctionReturn(0);
25717ab2063SBarry Smith }
25817ab2063SBarry Smith 
2591a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2603b2fbd54SBarry Smith {
2613b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
262dfbe8321SBarry Smith   PetscErrorCode ierr;
263d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
26497f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2653b2fbd54SBarry Smith 
2663a40ed3dSBarry Smith   PetscFunctionBegin;
267899cda47SBarry Smith   *nn = n;
2683a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2693b2fbd54SBarry Smith   if (symmetric) {
2702462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
2713b2fbd54SBarry Smith   } else {
272b9e7e5c1SBarry Smith     ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
273854ce69bSBarry Smith     ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
274b9e7e5c1SBarry Smith     ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
2753b2fbd54SBarry Smith     jj   = a->j;
2763b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
277bfeeae90SHong Zhang       collengths[jj[i]]++;
2783b2fbd54SBarry Smith     }
2793b2fbd54SBarry Smith     cia[0] = oshift;
2803b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2813b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2823b2fbd54SBarry Smith     }
283580bdb30SBarry Smith     ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
2843b2fbd54SBarry Smith     jj   = a->j;
285a93ec695SBarry Smith     for (row=0; row<m; row++) {
286a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
287a93ec695SBarry Smith       for (i=0; i<mr; i++) {
288bfeeae90SHong Zhang         col = *jj++;
2892205254eSKarl Rupp 
2903b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2913b2fbd54SBarry Smith       }
2923b2fbd54SBarry Smith     }
293606d414cSSatish Balay     ierr = PetscFree(collengths);CHKERRQ(ierr);
2943b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
2953b2fbd54SBarry Smith   }
2963a40ed3dSBarry Smith   PetscFunctionReturn(0);
2973b2fbd54SBarry Smith }
2983b2fbd54SBarry Smith 
2991a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
3003b2fbd54SBarry Smith {
301dfbe8321SBarry Smith   PetscErrorCode ierr;
302606d414cSSatish Balay 
3033a40ed3dSBarry Smith   PetscFunctionBegin;
3043a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
3053b2fbd54SBarry Smith 
306606d414cSSatish Balay   ierr = PetscFree(*ia);CHKERRQ(ierr);
307606d414cSSatish Balay   ierr = PetscFree(*ja);CHKERRQ(ierr);
3083a40ed3dSBarry Smith   PetscFunctionReturn(0);
3093b2fbd54SBarry Smith }
3103b2fbd54SBarry Smith 
3117cee066cSHong Zhang /*
3127cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3137cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
314040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3157cee066cSHong Zhang */
3167cee066cSHong 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)
3177cee066cSHong Zhang {
3187cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3197cee066cSHong Zhang   PetscErrorCode ierr;
3207cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
321071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3227cee066cSHong Zhang   PetscInt       *cspidx;
323071fcb05SBarry Smith   const PetscInt *jj;
3247cee066cSHong Zhang 
3257cee066cSHong Zhang   PetscFunctionBegin;
3267cee066cSHong Zhang   *nn = n;
3277cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
328625f6d37SHong Zhang 
329b9e7e5c1SBarry Smith   ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
330854ce69bSBarry Smith   ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
331b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
332b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr);
3337cee066cSHong Zhang   jj   = a->j;
3347cee066cSHong Zhang   for (i=0; i<nz; i++) {
3357cee066cSHong Zhang     collengths[jj[i]]++;
3367cee066cSHong Zhang   }
3377cee066cSHong Zhang   cia[0] = oshift;
3387cee066cSHong Zhang   for (i=0; i<n; i++) {
3397cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3407cee066cSHong Zhang   }
341580bdb30SBarry Smith   ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
3427cee066cSHong Zhang   jj   = a->j;
3437cee066cSHong Zhang   for (row=0; row<m; row++) {
3447cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3457cee066cSHong Zhang     for (i=0; i<mr; i++) {
3467cee066cSHong Zhang       col         = *jj++;
347071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
348071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
349071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3507cee066cSHong Zhang     }
3517cee066cSHong Zhang   }
3527cee066cSHong Zhang   ierr   = PetscFree(collengths);CHKERRQ(ierr);
353071fcb05SBarry Smith   *ia    = cia;
354071fcb05SBarry Smith   *ja    = cja;
3557cee066cSHong Zhang   *spidx = cspidx;
3567cee066cSHong Zhang   PetscFunctionReturn(0);
3577cee066cSHong Zhang }
3587cee066cSHong Zhang 
3597cee066cSHong 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)
3607cee066cSHong Zhang {
3617cee066cSHong Zhang   PetscErrorCode ierr;
3627cee066cSHong Zhang 
3637cee066cSHong Zhang   PetscFunctionBegin;
3645243ef75SHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
3657cee066cSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
3667cee066cSHong Zhang   PetscFunctionReturn(0);
3677cee066cSHong Zhang }
3687cee066cSHong Zhang 
36987d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
37087d4246cSBarry Smith {
37187d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
37287d4246cSBarry Smith   PetscInt       *ai = a->i;
37387d4246cSBarry Smith   PetscErrorCode ierr;
37487d4246cSBarry Smith 
37587d4246cSBarry Smith   PetscFunctionBegin;
376580bdb30SBarry Smith   ierr = PetscArraycpy(a->a+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr);
377e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
378c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && ai[row+1]-ai[row]) A->offloadmask = PETSC_OFFLOAD_CPU;
379e2cf4d64SStefano Zampini #endif
38087d4246cSBarry Smith   PetscFunctionReturn(0);
38187d4246cSBarry Smith }
38287d4246cSBarry Smith 
383bd04181cSBarry Smith /*
384bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
385bd04181cSBarry Smith 
386bd04181cSBarry Smith       -   a single row of values is set with each call
387bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
388bd04181cSBarry Smith       -   the values are always added to the matrix, not set
389bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
390bd04181cSBarry Smith 
3911f763a69SBarry Smith      This does NOT assume the global column indices are sorted
392bd04181cSBarry Smith 
3931f763a69SBarry Smith */
394bd04181cSBarry Smith 
395af0996ceSBarry Smith #include <petsc/private/isimpl.h>
396189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
397189e4007SBarry Smith {
398189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3991f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
4001f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
4011f763a69SBarry Smith   PetscInt       lastcol = -1;
402189e4007SBarry Smith   MatScalar      *ap,value,*aa = a->a;
403189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
404189e4007SBarry Smith 
405f38dd0b8SBarry Smith   row  = ridx[im[0]];
4061f763a69SBarry Smith   rp   = aj + ai[row];
4071f763a69SBarry Smith   ap   = aa + ai[row];
4081f763a69SBarry Smith   nrow = ailen[row];
409189e4007SBarry Smith   low  = 0;
410189e4007SBarry Smith   high = nrow;
411189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
412189e4007SBarry Smith     col = cidx[in[l]];
413f38dd0b8SBarry Smith     value = v[l];
414189e4007SBarry Smith 
415189e4007SBarry Smith     if (col <= lastcol) low = 0;
416189e4007SBarry Smith     else high = nrow;
417189e4007SBarry Smith     lastcol = col;
418189e4007SBarry Smith     while (high-low > 5) {
419189e4007SBarry Smith       t = (low+high)/2;
420189e4007SBarry Smith       if (rp[t] > col) high = t;
421189e4007SBarry Smith       else low = t;
422189e4007SBarry Smith     }
423189e4007SBarry Smith     for (i=low; i<high; i++) {
424189e4007SBarry Smith       if (rp[i] == col) {
4251f763a69SBarry Smith         ap[i] += value;
426189e4007SBarry Smith         low = i + 1;
4271f763a69SBarry Smith         break;
428189e4007SBarry Smith       }
429189e4007SBarry Smith     }
430189e4007SBarry Smith   }
431e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
432c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
433e2cf4d64SStefano Zampini #endif
434f38dd0b8SBarry Smith   return 0;
435189e4007SBarry Smith }
436189e4007SBarry Smith 
43797f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
43817ab2063SBarry Smith {
439416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
440e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
44197f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
4426849ba73SBarry Smith   PetscErrorCode ierr;
443e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
444d8cdefa3SHong Zhang   MatScalar      *ap=NULL,value=0.0,*aa = a->a;
445ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
446ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
447e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
448e2cf4d64SStefano Zampini   PetscBool      inserted          = PETSC_FALSE;
449e2cf4d64SStefano Zampini #endif
45017ab2063SBarry Smith 
4513a40ed3dSBarry Smith   PetscFunctionBegin;
45217ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
453416022c9SBarry Smith     row = im[k];
4545ef9f2a5SBarry Smith     if (row < 0) continue;
4552515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
456e32f2f54SBarry 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);
4573b2fbd54SBarry Smith #endif
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;
4652515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
466e32f2f54SBarry 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);
4673b2fbd54SBarry Smith #endif
468bfeeae90SHong Zhang       col = in[l];
469071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
470071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
47136db0b34SBarry Smith 
4722205254eSKarl Rupp       if (col <= lastcol) low = 0;
4732205254eSKarl Rupp       else high = nrow;
474e2ee6c50SBarry Smith       lastcol = col;
475416022c9SBarry Smith       while (high-low > 5) {
476416022c9SBarry Smith         t = (low+high)/2;
477416022c9SBarry Smith         if (rp[t] > col) high = t;
478416022c9SBarry Smith         else low = t;
47917ab2063SBarry Smith       }
480416022c9SBarry Smith       for (i=low; i<high; i++) {
48117ab2063SBarry Smith         if (rp[i] > col) break;
48217ab2063SBarry Smith         if (rp[i] == col) {
483876c6284SHong Zhang           if (!A->structure_only) {
4840c0d7e18SFande Kong             if (is == ADD_VALUES) {
4850c0d7e18SFande Kong               ap[i] += value;
4860c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4870c0d7e18SFande Kong             }
48817ab2063SBarry Smith             else ap[i] = value;
489e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
490e2cf4d64SStefano Zampini             inserted = PETSC_TRUE;
491e2cf4d64SStefano Zampini #endif
492720833daSHong Zhang           }
493e44c0bd4SBarry Smith           low = i + 1;
49417ab2063SBarry Smith           goto noinsert;
49517ab2063SBarry Smith         }
49617ab2063SBarry Smith       }
497dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
498c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
499e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
500720833daSHong Zhang       if (A->structure_only) {
501876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
502720833daSHong Zhang       } else {
503fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
504720833daSHong Zhang       }
505c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
506416022c9SBarry Smith       /* shift up all the later entries in this row */
507580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
50817ab2063SBarry Smith       rp[i] = col;
509580bdb30SBarry Smith       if (!A->structure_only){
510580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
511580bdb30SBarry Smith         ap[i] = value;
512580bdb30SBarry Smith       }
513416022c9SBarry Smith       low = i + 1;
514e56f5c9eSBarry Smith       A->nonzerostate++;
515e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
516e2cf4d64SStefano Zampini       inserted = PETSC_TRUE;
517e2cf4d64SStefano Zampini #endif
518e44c0bd4SBarry Smith noinsert:;
51917ab2063SBarry Smith     }
52017ab2063SBarry Smith     ailen[row] = nrow;
52117ab2063SBarry Smith   }
522e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
523c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && inserted) A->offloadmask = PETSC_OFFLOAD_CPU;
524e2cf4d64SStefano Zampini #endif
5253a40ed3dSBarry Smith   PetscFunctionReturn(0);
52617ab2063SBarry Smith }
52717ab2063SBarry Smith 
528071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
529071fcb05SBarry Smith {
530071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
531071fcb05SBarry Smith   PetscInt       *rp,k,row;
532071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
533071fcb05SBarry Smith   PetscErrorCode ierr;
534071fcb05SBarry Smith   PetscInt       *aj = a->j;
535071fcb05SBarry Smith   MatScalar      *aa = a->a,*ap;
536071fcb05SBarry Smith 
537071fcb05SBarry Smith   PetscFunctionBegin;
538071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
539071fcb05SBarry Smith     row  = im[k];
540071fcb05SBarry Smith     rp   = aj + ai[row];
541071fcb05SBarry Smith     ap   = aa + ai[row];
542071fcb05SBarry Smith     if (!A->was_assembled) {
543071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
544071fcb05SBarry Smith     }
545071fcb05SBarry Smith     if (!A->structure_only) {
546071fcb05SBarry Smith       if (v) {
547071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
548071fcb05SBarry Smith         v   += n;
549071fcb05SBarry Smith       } else {
550071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
551071fcb05SBarry Smith       }
552071fcb05SBarry Smith     }
553071fcb05SBarry Smith     ailen[row] = n;
554071fcb05SBarry Smith     a->nz      += n;
555071fcb05SBarry Smith   }
556e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
557c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
558e2cf4d64SStefano Zampini #endif
559071fcb05SBarry Smith   PetscFunctionReturn(0);
560071fcb05SBarry Smith }
561071fcb05SBarry Smith 
56281824310SBarry Smith 
563a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
5647eb43aa7SLois Curfman McInnes {
5657eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
56697f1f81fSBarry Smith   PetscInt   *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
56797f1f81fSBarry Smith   PetscInt   *ai = a->i,*ailen = a->ilen;
56854f21887SBarry Smith   MatScalar  *ap,*aa = a->a;
5697eb43aa7SLois Curfman McInnes 
5703a40ed3dSBarry Smith   PetscFunctionBegin;
5717eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
5727eb43aa7SLois Curfman McInnes     row = im[k];
573e32f2f54SBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
574e32f2f54SBarry 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);
575bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
5767eb43aa7SLois Curfman McInnes     nrow = ailen[row];
5777eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
578e32f2f54SBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
579e32f2f54SBarry 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);
580bfeeae90SHong Zhang       col  = in[l];
5817eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
5827eb43aa7SLois Curfman McInnes       while (high-low > 5) {
5837eb43aa7SLois Curfman McInnes         t = (low+high)/2;
5847eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
5857eb43aa7SLois Curfman McInnes         else low = t;
5867eb43aa7SLois Curfman McInnes       }
5877eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
5887eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
5897eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
590b49de8d1SLois Curfman McInnes           *v++ = ap[i];
5917eb43aa7SLois Curfman McInnes           goto finished;
5927eb43aa7SLois Curfman McInnes         }
5937eb43aa7SLois Curfman McInnes       }
59497e567efSBarry Smith       *v++ = 0.0;
5957eb43aa7SLois Curfman McInnes finished:;
5967eb43aa7SLois Curfman McInnes     }
5977eb43aa7SLois Curfman McInnes   }
5983a40ed3dSBarry Smith   PetscFunctionReturn(0);
5997eb43aa7SLois Curfman McInnes }
6007eb43aa7SLois Curfman McInnes 
601*3ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
60217ab2063SBarry Smith {
603*3ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *A = (Mat_SeqAIJ*)mat->data;
604*3ea6fe3dSLisandro Dalcin   PetscInt       header[4],M,N,m,nz,i;
605*3ea6fe3dSLisandro Dalcin   PetscInt       *rowlens;
6066849ba73SBarry Smith   PetscErrorCode ierr;
60717ab2063SBarry Smith 
6083a40ed3dSBarry Smith   PetscFunctionBegin;
609*3ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
6102205254eSKarl Rupp 
611*3ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
612*3ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
613*3ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
614*3ea6fe3dSLisandro Dalcin   nz = A->nz;
615416022c9SBarry Smith 
616*3ea6fe3dSLisandro Dalcin   /* write matrix header */
617*3ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
618*3ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
619*3ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,header,4,PETSC_INT);CHKERRQ(ierr);
620416022c9SBarry Smith 
621*3ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
622*3ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(m,&rowlens);CHKERRQ(ierr);
623*3ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
624*3ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT);CHKERRQ(ierr);
625*3ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
626*3ea6fe3dSLisandro Dalcin   /* store column indices */
627*3ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT);CHKERRQ(ierr);
628416022c9SBarry Smith   /* store nonzero values */
629*3ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->a,nz,PETSC_SCALAR);CHKERRQ(ierr);
630b37d52dbSMark F. Adams 
631*3ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
632*3ea6fe3dSLisandro Dalcin   ierr = MatView_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
6333a40ed3dSBarry Smith   PetscFunctionReturn(0);
63417ab2063SBarry Smith }
635416022c9SBarry Smith 
6367dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
6377dc0baabSHong Zhang {
6387dc0baabSHong Zhang   PetscErrorCode ierr;
6397dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
6407dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
6417dc0baabSHong Zhang 
6427dc0baabSHong Zhang   PetscFunctionBegin;
6437dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
6447dc0baabSHong Zhang   for (i=0; i<m; i++) {
6457dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
6467dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
6477dc0baabSHong Zhang       ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr);
6487dc0baabSHong Zhang     }
6497dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
6507dc0baabSHong Zhang   }
6517dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
6527dc0baabSHong Zhang   PetscFunctionReturn(0);
6537dc0baabSHong Zhang }
6547dc0baabSHong Zhang 
65509573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
656cd155464SBarry Smith 
657dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
658416022c9SBarry Smith {
659416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
660dfbe8321SBarry Smith   PetscErrorCode    ierr;
66160e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
662e060cb09SBarry Smith   const char        *name;
663f3ef73ceSBarry Smith   PetscViewerFormat format;
66417ab2063SBarry Smith 
6653a40ed3dSBarry Smith   PetscFunctionBegin;
6667dc0baabSHong Zhang   if (A->structure_only) {
6677dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
6687dc0baabSHong Zhang     PetscFunctionReturn(0);
6697dc0baabSHong Zhang   }
67043e49210SHong Zhang 
671b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
67271c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
67397f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
67460e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
675c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
676d00d2cf4SBarry Smith       nofinalvalue = 1;
677d00d2cf4SBarry Smith     }
678d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
679d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
68077431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
681fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
682fbfe6fa7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
683fbfe6fa7SJed Brown #else
68477431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
685fbfe6fa7SJed Brown #endif
686b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
68717ab2063SBarry Smith 
68817ab2063SBarry Smith     for (i=0; i<m; i++) {
68960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
690aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
691a9bf72d8SJed 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);
69217ab2063SBarry Smith #else
69360e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
69417ab2063SBarry Smith #endif
69517ab2063SBarry Smith       }
69617ab2063SBarry Smith     }
697d00d2cf4SBarry Smith     if (nofinalvalue) {
698c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
699c337ccceSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
700c337ccceSJed Brown #else
701d0f46423SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
702c337ccceSJed Brown #endif
703d00d2cf4SBarry Smith     }
704317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
705fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
706d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
7072950ac48SStefano Zampini   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
708cd155464SBarry Smith     PetscFunctionReturn(0);
709fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
710d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
71144cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
71277431f27SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
71360e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
714aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
71536db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
71660e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
71736db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
71860e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
71936db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
72060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
7216831982aSBarry Smith         }
72244cd7ae7SLois Curfman McInnes #else
72360e0710aSBarry Smith         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
72444cd7ae7SLois Curfman McInnes #endif
72544cd7ae7SLois Curfman McInnes       }
726b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
72744cd7ae7SLois Curfman McInnes     }
728d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
729fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
73097f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
731d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
732854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
733496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
734496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
73560e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
736496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
737aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
73836db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
739496be53dSLois Curfman McInnes #else
740496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
741496be53dSLois Curfman McInnes #endif
742496be53dSLois Curfman McInnes         }
743496be53dSLois Curfman McInnes       }
744496be53dSLois Curfman McInnes     }
7452e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
74677431f27SBarry Smith     ierr    = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
7472e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
7482205254eSKarl Rupp       if (i+4<m) {
7492205254eSKarl 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);
7502205254eSKarl Rupp       } else if (i+3<m) {
7512205254eSKarl 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);
7522205254eSKarl Rupp       } else if (i+2<m) {
7532205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
7542205254eSKarl Rupp       } else if (i+1<m) {
7552205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
7562205254eSKarl Rupp       } else if (i<m) {
7572205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
7582205254eSKarl Rupp       } else {
7592205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);
7602205254eSKarl Rupp       }
761496be53dSLois Curfman McInnes     }
762b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
763606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
764496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
76560e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
76677431f27SBarry Smith         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
767496be53dSLois Curfman McInnes       }
768b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
769496be53dSLois Curfman McInnes     }
770b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
771496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
77260e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
773496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
774aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
77536db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
77660e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
7776831982aSBarry Smith           }
778496be53dSLois Curfman McInnes #else
77960e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
780496be53dSLois Curfman McInnes #endif
781496be53dSLois Curfman McInnes         }
782496be53dSLois Curfman McInnes       }
783b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
784496be53dSLois Curfman McInnes     }
785d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
786fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
78797f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
78887828ca2SBarry Smith     PetscScalar value;
78968f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
79068f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
79168f1ed48SBarry Smith 
79268f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
79368f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
79468f1ed48SBarry Smith         realonly = PETSC_FALSE;
79568f1ed48SBarry Smith         break;
79668f1ed48SBarry Smith       }
79768f1ed48SBarry Smith     }
79868f1ed48SBarry Smith #endif
79902594712SBarry Smith 
800d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
80102594712SBarry Smith     for (i=0; i<m; i++) {
80202594712SBarry Smith       jcnt = 0;
803d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
804e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
80502594712SBarry Smith           value = a->a[cnt++];
806e24b481bSBarry Smith           jcnt++;
80702594712SBarry Smith         } else {
80802594712SBarry Smith           value = 0.0;
80902594712SBarry Smith         }
810aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
81168f1ed48SBarry Smith         if (realonly) {
81260e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
81368f1ed48SBarry Smith         } else {
81460e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
81568f1ed48SBarry Smith         }
81602594712SBarry Smith #else
81760e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
81802594712SBarry Smith #endif
81902594712SBarry Smith       }
820b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
82102594712SBarry Smith     }
822d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
8233c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
824150b93efSMatthew G. Knepley     PetscInt fshift=1;
825d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
8263c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
82719303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
8283c215bfdSMatthew Knepley #else
82919303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
8303c215bfdSMatthew Knepley #endif
831d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
8323c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
83360e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
8343c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
835a9a0e077SKarl 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);
8363c215bfdSMatthew Knepley #else
837150b93efSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
8383c215bfdSMatthew Knepley #endif
8393c215bfdSMatthew Knepley       }
8403c215bfdSMatthew Knepley     }
841d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
8423a40ed3dSBarry Smith   } else {
843d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
844d5f3da31SBarry Smith     if (A->factortype) {
84516cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
84616cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
84716cd7e1dSShri Abhyankar         /* L part */
84860e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
84916cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
85016cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
85160e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
85216cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
8536712e2f1SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
85416cd7e1dSShri Abhyankar           } else {
85560e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
85616cd7e1dSShri Abhyankar           }
85716cd7e1dSShri Abhyankar #else
85860e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
85916cd7e1dSShri Abhyankar #endif
86016cd7e1dSShri Abhyankar         }
86116cd7e1dSShri Abhyankar         /* diagonal */
86216cd7e1dSShri Abhyankar         j = a->diag[i];
86316cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
86416cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
86560e0710aSBarry 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);
86616cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
8676712e2f1SBarry 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);
86816cd7e1dSShri Abhyankar         } else {
86960e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
87016cd7e1dSShri Abhyankar         }
87116cd7e1dSShri Abhyankar #else
87260e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
87316cd7e1dSShri Abhyankar #endif
87416cd7e1dSShri Abhyankar 
87516cd7e1dSShri Abhyankar         /* U part */
87660e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
87716cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
87816cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
87960e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
88016cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
88122ab088eSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
88216cd7e1dSShri Abhyankar           } else {
88360e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
88416cd7e1dSShri Abhyankar           }
88516cd7e1dSShri Abhyankar #else
88660e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
88716cd7e1dSShri Abhyankar #endif
88816cd7e1dSShri Abhyankar         }
88916cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
89016cd7e1dSShri Abhyankar       }
89116cd7e1dSShri Abhyankar     } else {
89217ab2063SBarry Smith       for (i=0; i<m; i++) {
89377431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
89460e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
895aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
89636db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
89760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
89836db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
89960e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
9003a40ed3dSBarry Smith           } else {
90160e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
90217ab2063SBarry Smith           }
90317ab2063SBarry Smith #else
90460e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
90517ab2063SBarry Smith #endif
90617ab2063SBarry Smith         }
907b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
90817ab2063SBarry Smith       }
90916cd7e1dSShri Abhyankar     }
910d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
91117ab2063SBarry Smith   }
912b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9133a40ed3dSBarry Smith   PetscFunctionReturn(0);
914416022c9SBarry Smith }
915416022c9SBarry Smith 
9169804daf3SBarry Smith #include <petscdraw.h>
917dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
918416022c9SBarry Smith {
919480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
920416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
921dfbe8321SBarry Smith   PetscErrorCode    ierr;
922383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
923383922c3SLisandro Dalcin   int               color;
924b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
925b0a32e0cSBarry Smith   PetscViewer       viewer;
926f3ef73ceSBarry Smith   PetscViewerFormat format;
927cddf8d76SBarry Smith 
9283a40ed3dSBarry Smith   PetscFunctionBegin;
929480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
930b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
931b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
932383922c3SLisandro Dalcin 
933416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
9340513a670SBarry Smith 
935fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
936383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
9370513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
938b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
939416022c9SBarry Smith     for (i=0; i<m; i++) {
940cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
941bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
942bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
94336db0b34SBarry Smith         if (PetscRealPart(a->a[j]) >=  0.) continue;
944b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
945cddf8d76SBarry Smith       }
946cddf8d76SBarry Smith     }
947b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
948cddf8d76SBarry Smith     for (i=0; i<m; i++) {
949cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
950bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
951bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
952cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
953b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
954cddf8d76SBarry Smith       }
955cddf8d76SBarry Smith     }
956b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
957cddf8d76SBarry Smith     for (i=0; i<m; i++) {
958cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
959bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
960bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
96136db0b34SBarry Smith         if (PetscRealPart(a->a[j]) <=  0.) continue;
962b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
963416022c9SBarry Smith       }
964416022c9SBarry Smith     }
965383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
9660513a670SBarry Smith   } else {
9670513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
9680513a670SBarry Smith     /* first determine max of all nonzero values */
969b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
970383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
971b0a32e0cSBarry Smith     PetscDraw popup;
9720513a670SBarry Smith 
9730513a670SBarry Smith     for (i=0; i<nz; i++) {
9740513a670SBarry Smith       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
9750513a670SBarry Smith     }
976383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
977b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
97845f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
979383922c3SLisandro Dalcin 
980383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
9810513a670SBarry Smith     for (i=0; i<m; i++) {
982383922c3SLisandro Dalcin       y_l = m - i - 1.0;
983383922c3SLisandro Dalcin       y_r = y_l + 1.0;
984bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
985383922c3SLisandro Dalcin         x_l = a->j[j];
986383922c3SLisandro Dalcin         x_r = x_l + 1.0;
987b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(a->a[count]),minv,maxv);
988b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
9890513a670SBarry Smith         count++;
9900513a670SBarry Smith       }
9910513a670SBarry Smith     }
992383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
9930513a670SBarry Smith   }
994480ef9eaSBarry Smith   PetscFunctionReturn(0);
995480ef9eaSBarry Smith }
996cddf8d76SBarry Smith 
9979804daf3SBarry Smith #include <petscdraw.h>
998dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
999480ef9eaSBarry Smith {
1000dfbe8321SBarry Smith   PetscErrorCode ierr;
1001b0a32e0cSBarry Smith   PetscDraw      draw;
100236db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1003ace3abfcSBarry Smith   PetscBool      isnull;
1004480ef9eaSBarry Smith 
1005480ef9eaSBarry Smith   PetscFunctionBegin;
1006b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1007b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1008480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1009480ef9eaSBarry Smith 
1010d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1011480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
1012b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1013832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1014b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
10150298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1016832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
10173a40ed3dSBarry Smith   PetscFunctionReturn(0);
1018416022c9SBarry Smith }
1019416022c9SBarry Smith 
1020dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1021416022c9SBarry Smith {
1022dfbe8321SBarry Smith   PetscErrorCode ierr;
1023ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1024416022c9SBarry Smith 
10253a40ed3dSBarry Smith   PetscFunctionBegin;
1026251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1027251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1028251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1029c45a1595SBarry Smith   if (iascii) {
10303a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
10310f5bd95cSBarry Smith   } else if (isbinary) {
10323a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
10330f5bd95cSBarry Smith   } else if (isdraw) {
10343a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
103511aeaf0aSBarry Smith   }
10364108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
10373a40ed3dSBarry Smith   PetscFunctionReturn(0);
103817ab2063SBarry Smith }
103919bcc07fSBarry Smith 
1040dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
104117ab2063SBarry Smith {
1042416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
10436849ba73SBarry Smith   PetscErrorCode ierr;
1044580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1045d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
104654f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
10473447b6efSHong Zhang   PetscReal      ratio  = 0.6;
104817ab2063SBarry Smith 
10493a40ed3dSBarry Smith   PetscFunctionBegin;
10503a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1051071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1052071fcb05SBarry Smith   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) PetscFunctionReturn(0);
105317ab2063SBarry Smith 
105443ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
105517ab2063SBarry Smith   for (i=1; i<m; i++) {
1056416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
105717ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
105894a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
105917ab2063SBarry Smith     if (fshift) {
1060bfeeae90SHong Zhang       ip = aj + ai[i];
1061bfeeae90SHong Zhang       ap = aa + ai[i];
106217ab2063SBarry Smith       N  = ailen[i];
1063580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1064580bdb30SBarry Smith       if (!A->structure_only) {
1065580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
106617ab2063SBarry Smith       }
106717ab2063SBarry Smith     }
106817ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
106917ab2063SBarry Smith   }
107017ab2063SBarry Smith   if (m) {
107117ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
107217ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
107317ab2063SBarry Smith   }
10747b083b7cSBarry Smith 
107517ab2063SBarry Smith   /* reset ilen and imax for each row */
10767b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1077396832f4SHong Zhang   if (A->structure_only) {
1078071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1079071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1080396832f4SHong Zhang   } else { /* !A->structure_only */
108117ab2063SBarry Smith     for (i=0; i<m; i++) {
108217ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
10837b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
108417ab2063SBarry Smith     }
1085396832f4SHong Zhang   }
1086bfeeae90SHong Zhang   a->nz = ai[m];
108765e19b50SBarry 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);
108817ab2063SBarry Smith 
108909f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1090d0f46423SBarry 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);
1091ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1092ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
10932205254eSKarl Rupp 
10948e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1095dd5f02e7SSatish Balay   a->reallocs         = 0;
10966712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
109736db0b34SBarry Smith   a->rmax             = rmax;
10984e220ebcSLois Curfman McInnes 
1099396832f4SHong Zhang   if (!A->structure_only) {
110011e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1101396832f4SHong Zhang   }
11024108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
11033a40ed3dSBarry Smith   PetscFunctionReturn(0);
110417ab2063SBarry Smith }
110517ab2063SBarry Smith 
110699cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
110799cafbc1SBarry Smith {
110899cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
110999cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
111054f21887SBarry Smith   MatScalar      *aa = a->a;
1111acf2f550SJed Brown   PetscErrorCode ierr;
111299cafbc1SBarry Smith 
111399cafbc1SBarry Smith   PetscFunctionBegin;
111499cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
1115acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1116e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
1117c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1118e2cf4d64SStefano Zampini #endif
111999cafbc1SBarry Smith   PetscFunctionReturn(0);
112099cafbc1SBarry Smith }
112199cafbc1SBarry Smith 
112299cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
112399cafbc1SBarry Smith {
112499cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
112599cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
112654f21887SBarry Smith   MatScalar      *aa = a->a;
1127acf2f550SJed Brown   PetscErrorCode ierr;
112899cafbc1SBarry Smith 
112999cafbc1SBarry Smith   PetscFunctionBegin;
113099cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
1131acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1132e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
1133c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1134e2cf4d64SStefano Zampini #endif
113599cafbc1SBarry Smith   PetscFunctionReturn(0);
113699cafbc1SBarry Smith }
113799cafbc1SBarry Smith 
1138dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
113917ab2063SBarry Smith {
1140416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1141dfbe8321SBarry Smith   PetscErrorCode ierr;
11423a40ed3dSBarry Smith 
11433a40ed3dSBarry Smith   PetscFunctionBegin;
1144580bdb30SBarry Smith   ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
1145acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1146e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
1147c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1148e2cf4d64SStefano Zampini #endif
11493a40ed3dSBarry Smith   PetscFunctionReturn(0);
115017ab2063SBarry Smith }
1151416022c9SBarry Smith 
1152dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
115317ab2063SBarry Smith {
1154416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1155dfbe8321SBarry Smith   PetscErrorCode ierr;
1156d5d45c9bSBarry Smith 
11573a40ed3dSBarry Smith   PetscFunctionBegin;
1158aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1159d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
116017ab2063SBarry Smith #endif
1161e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
11626bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
11636bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
116405b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1165d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1166071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1167071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1168846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
116971f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
117005b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
11716bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
117205b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
11736bf464f9SBarry Smith   ierr = ISColoringDestroy(&a->coloring);CHKERRQ(ierr);
1174cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
11750b7e3e3dSHong Zhang   ierr = PetscFree(a->matmult_abdense);CHKERRQ(ierr);
1176a30b2313SHong Zhang 
11774108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1178bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1179901853e0SKris Buschelman 
1180dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1181bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1182bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1183bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1184bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1185bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1186bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
1187af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1188af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1189af8000cdSHong Zhang #endif
119063c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
119163c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
11923dad0653Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMatMult_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
119363c07aadSStefano Zampini #endif
1194b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1195c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1196c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1197bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1198bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1199846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1200bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1201bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
120275d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_is_seqaij_C",NULL);CHKERRQ(ierr);
12033a40ed3dSBarry Smith   PetscFunctionReturn(0);
120417ab2063SBarry Smith }
120517ab2063SBarry Smith 
1206ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
120717ab2063SBarry Smith {
1208416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
12094846f1f5SKris Buschelman   PetscErrorCode ierr;
12103a40ed3dSBarry Smith 
12113a40ed3dSBarry Smith   PetscFunctionBegin;
1212a65d3064SKris Buschelman   switch (op) {
1213a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
12144e0d8c25SBarry Smith     a->roworiented = flg;
1215a65d3064SKris Buschelman     break;
1216a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1217a9817697SBarry Smith     a->keepnonzeropattern = flg;
1218a65d3064SKris Buschelman     break;
1219512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1220512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1221a65d3064SKris Buschelman     break;
1222a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
12234e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1224a65d3064SKris Buschelman     break;
1225a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
12264e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1227a65d3064SKris Buschelman     break;
122828b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
122928b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
123028b2fa4aSMatthew Knepley     break;
1231a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
12324e0d8c25SBarry Smith     a->ignorezeroentries = flg;
12330df259c2SBarry Smith     break;
12343d472b54SHong Zhang   case MAT_SPD:
1235b1646e73SJed Brown   case MAT_SYMMETRIC:
1236b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1237b1646e73SJed Brown   case MAT_HERMITIAN:
1238b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1239957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
12405021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
12415021d80fSJed Brown     break;
12424e0d8c25SBarry Smith   case MAT_NEW_DIAGONALS:
1243a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1244a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1245290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1246a65d3064SKris Buschelman     break;
1247b87ac2d8SJed Brown   case MAT_USE_INODES:
1248b87ac2d8SJed Brown     /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */
1249b87ac2d8SJed Brown     break;
1250c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1251c10200c1SHong Zhang     A->submat_singleis = flg;
1252c10200c1SHong Zhang     break;
1253071fcb05SBarry Smith   case MAT_SORTED_FULL:
1254071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1255071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1256071fcb05SBarry Smith     break;
1257a65d3064SKris Buschelman   default:
1258e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1259a65d3064SKris Buschelman   }
12604108e4d5SBarry Smith   ierr = MatSetOption_SeqAIJ_Inode(A,op,flg);CHKERRQ(ierr);
12613a40ed3dSBarry Smith   PetscFunctionReturn(0);
126217ab2063SBarry Smith }
126317ab2063SBarry Smith 
1264dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
126517ab2063SBarry Smith {
1266416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
12676849ba73SBarry Smith   PetscErrorCode ierr;
1268fdc842d1SBarry Smith   PetscInt       i,j,n,*ai=a->i,*aj=a->j;
1269fdc842d1SBarry Smith   PetscScalar    *aa=a->a,*x;
127017ab2063SBarry Smith 
12713a40ed3dSBarry Smith   PetscFunctionBegin;
1272d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1273e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
127435e7444dSHong Zhang 
1275d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1276d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1277fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
12782c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1279fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
128035e7444dSHong Zhang     PetscFunctionReturn(0);
128135e7444dSHong Zhang   }
128235e7444dSHong Zhang 
1283fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
128435e7444dSHong Zhang   for (i=0; i<n; i++) {
1285fdc842d1SBarry Smith     x[i] = 0.0;
128635e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
128735e7444dSHong Zhang       if (aj[j] == i) {
128835e7444dSHong Zhang         x[i] = aa[j];
128917ab2063SBarry Smith         break;
129017ab2063SBarry Smith       }
129117ab2063SBarry Smith     }
129217ab2063SBarry Smith   }
1293fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
12943a40ed3dSBarry Smith   PetscFunctionReturn(0);
129517ab2063SBarry Smith }
129617ab2063SBarry Smith 
1297c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1298dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
129917ab2063SBarry Smith {
1300416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1301d9ca1df4SBarry Smith   PetscScalar       *y;
1302d9ca1df4SBarry Smith   const PetscScalar *x;
1303dfbe8321SBarry Smith   PetscErrorCode    ierr;
1304d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
13055c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1306d9ca1df4SBarry Smith   const MatScalar   *v;
1307a77337e4SBarry Smith   PetscScalar       alpha;
1308d9ca1df4SBarry Smith   PetscInt          n,i,j;
1309d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
13103447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1311ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
13125c897100SBarry Smith #endif
131317ab2063SBarry Smith 
13143a40ed3dSBarry Smith   PetscFunctionBegin;
13152e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1316d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
13171ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
13185c897100SBarry Smith 
13195c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1320bfeeae90SHong Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
13215c897100SBarry Smith #else
13223447b6efSHong Zhang   if (usecprow) {
13233447b6efSHong Zhang     m    = cprow.nrows;
13243447b6efSHong Zhang     ii   = cprow.i;
13257b2bb3b9SHong Zhang     ridx = cprow.rindex;
13263447b6efSHong Zhang   } else {
13273447b6efSHong Zhang     ii = a->i;
13283447b6efSHong Zhang   }
132917ab2063SBarry Smith   for (i=0; i<m; i++) {
13303447b6efSHong Zhang     idx = a->j + ii[i];
13313447b6efSHong Zhang     v   = a->a + ii[i];
13323447b6efSHong Zhang     n   = ii[i+1] - ii[i];
13333447b6efSHong Zhang     if (usecprow) {
13347b2bb3b9SHong Zhang       alpha = x[ridx[i]];
13353447b6efSHong Zhang     } else {
133617ab2063SBarry Smith       alpha = x[i];
13373447b6efSHong Zhang     }
133804fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
133917ab2063SBarry Smith   }
13405c897100SBarry Smith #endif
1341dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1342d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
13431ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
13443a40ed3dSBarry Smith   PetscFunctionReturn(0);
134517ab2063SBarry Smith }
134617ab2063SBarry Smith 
1347dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
13485c897100SBarry Smith {
1349dfbe8321SBarry Smith   PetscErrorCode ierr;
13505c897100SBarry Smith 
13515c897100SBarry Smith   PetscFunctionBegin;
1352170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
13535c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
13545c897100SBarry Smith   PetscFunctionReturn(0);
13555c897100SBarry Smith }
13565c897100SBarry Smith 
1357c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
135878b84d54SShri Abhyankar 
1359dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
136017ab2063SBarry Smith {
1361416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1362d9fead3dSBarry Smith   PetscScalar       *y;
136354f21887SBarry Smith   const PetscScalar *x;
136454f21887SBarry Smith   const MatScalar   *aa;
1365dfbe8321SBarry Smith   PetscErrorCode    ierr;
1366003131ecSBarry Smith   PetscInt          m=A->rmap->n;
13670298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
13687b083b7cSBarry Smith   PetscInt          n,i;
1369362ced78SSatish Balay   PetscScalar       sum;
1370ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
137117ab2063SBarry Smith 
1372b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
137397952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1374fee21e36SBarry Smith #endif
1375fee21e36SBarry Smith 
13763a40ed3dSBarry Smith   PetscFunctionBegin;
13773649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
13781ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1379416022c9SBarry Smith   ii   = a->i;
13804eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1381580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
138297952fefSHong Zhang     m    = a->compressedrow.nrows;
138397952fefSHong Zhang     ii   = a->compressedrow.i;
138497952fefSHong Zhang     ridx = a->compressedrow.rindex;
138597952fefSHong Zhang     for (i=0; i<m; i++) {
138697952fefSHong Zhang       n           = ii[i+1] - ii[i];
138797952fefSHong Zhang       aj          = a->j + ii[i];
138897952fefSHong Zhang       aa          = a->a + ii[i];
138997952fefSHong Zhang       sum         = 0.0;
1390003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1391003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
139297952fefSHong Zhang       y[*ridx++] = sum;
139397952fefSHong Zhang     }
139497952fefSHong Zhang   } else { /* do not use compressed row format */
1395b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
13963d3eaba7SBarry Smith     aj   = a->j;
13973d3eaba7SBarry Smith     aa   = a->a;
1398b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1399b05257ddSBarry Smith #else
140017ab2063SBarry Smith     for (i=0; i<m; i++) {
1401003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1402003131ecSBarry Smith       aj          = a->j + ii[i];
1403003131ecSBarry Smith       aa          = a->a + ii[i];
140417ab2063SBarry Smith       sum         = 0.0;
1405003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
140617ab2063SBarry Smith       y[i] = sum;
140717ab2063SBarry Smith     }
14088d195f9aSBarry Smith #endif
1409b05257ddSBarry Smith   }
14107b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
14113649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14121ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
14133a40ed3dSBarry Smith   PetscFunctionReturn(0);
141417ab2063SBarry Smith }
141517ab2063SBarry Smith 
1416b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1417b434eb95SMatthew G. Knepley {
1418b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1419b434eb95SMatthew G. Knepley   PetscScalar       *y;
1420b434eb95SMatthew G. Knepley   const PetscScalar *x;
1421b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1422b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1423b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1424b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1425b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1426b434eb95SMatthew G. Knepley   PetscScalar       sum;
1427b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1428b434eb95SMatthew G. Knepley 
1429b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1430b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1431b434eb95SMatthew G. Knepley #endif
1432b434eb95SMatthew G. Knepley 
1433b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1434b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1435b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1436b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1437b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1438b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1439b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1440b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1441b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1442b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1443b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1444b434eb95SMatthew G. Knepley       sum         = 0.0;
1445b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1446b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1447b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1448b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1449b434eb95SMatthew G. Knepley     }
1450b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
14513d3eaba7SBarry Smith     ii = a->i;
1452b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1453b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1454b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1455b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1456b434eb95SMatthew G. Knepley       sum         = 0.0;
1457b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1458b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1459b434eb95SMatthew G. Knepley       y[i] = sum;
1460b434eb95SMatthew G. Knepley     }
1461b434eb95SMatthew G. Knepley   }
1462b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1463b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1464b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1465b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1466b434eb95SMatthew G. Knepley }
1467b434eb95SMatthew G. Knepley 
1468b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1469b434eb95SMatthew G. Knepley {
1470b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1471b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1472b434eb95SMatthew G. Knepley   const PetscScalar *x;
1473b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1474b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1475b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1476b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1477b434eb95SMatthew G. Knepley   PetscScalar       sum;
1478b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1479b434eb95SMatthew G. Knepley 
1480b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1481b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1482d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1483b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1484b434eb95SMatthew G. Knepley     if (zz != yy) {
1485580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1486b434eb95SMatthew G. Knepley     }
1487b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1488b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1489b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1490b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1491b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1492b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1493b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1494b434eb95SMatthew G. Knepley       sum = y[*ridx];
1495b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1496b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1497b434eb95SMatthew G. Knepley     }
1498b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
14993d3eaba7SBarry Smith     ii = a->i;
1500b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1501b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1502b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1503b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1504b434eb95SMatthew G. Knepley       sum = y[i];
1505b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1506b434eb95SMatthew G. Knepley       z[i] = sum;
1507b434eb95SMatthew G. Knepley     }
1508b434eb95SMatthew G. Knepley   }
1509b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1510b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1511d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1512b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1513b434eb95SMatthew G. Knepley }
1514b434eb95SMatthew G. Knepley 
1515c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1516dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
151717ab2063SBarry Smith {
1518416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1519f15663dcSBarry Smith   PetscScalar       *y,*z;
1520f15663dcSBarry Smith   const PetscScalar *x;
152154f21887SBarry Smith   const MatScalar   *aa;
1522dfbe8321SBarry Smith   PetscErrorCode    ierr;
1523d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1524d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1525362ced78SSatish Balay   PetscScalar       sum;
1526ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
15279ea0dfa2SSatish Balay 
15283a40ed3dSBarry Smith   PetscFunctionBegin;
1529f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1530d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
15314eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
15324eb6d288SHong Zhang     if (zz != yy) {
1533580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
15344eb6d288SHong Zhang     }
153597952fefSHong Zhang     m    = a->compressedrow.nrows;
153697952fefSHong Zhang     ii   = a->compressedrow.i;
153797952fefSHong Zhang     ridx = a->compressedrow.rindex;
153897952fefSHong Zhang     for (i=0; i<m; i++) {
153997952fefSHong Zhang       n   = ii[i+1] - ii[i];
154097952fefSHong Zhang       aj  = a->j + ii[i];
154197952fefSHong Zhang       aa  = a->a + ii[i];
154297952fefSHong Zhang       sum = y[*ridx];
1543f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
154497952fefSHong Zhang       z[*ridx++] = sum;
154597952fefSHong Zhang     }
154697952fefSHong Zhang   } else { /* do not use compressed row format */
15473d3eaba7SBarry Smith     ii = a->i;
1548f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
15493d3eaba7SBarry Smith     aj = a->j;
15503d3eaba7SBarry Smith     aa = a->a;
1551f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1552f15663dcSBarry Smith #else
155317ab2063SBarry Smith     for (i=0; i<m; i++) {
1554f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1555f15663dcSBarry Smith       aj  = a->j + ii[i];
1556f15663dcSBarry Smith       aa  = a->a + ii[i];
155717ab2063SBarry Smith       sum = y[i];
1558f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
155917ab2063SBarry Smith       z[i] = sum;
156017ab2063SBarry Smith     }
156102ab625aSSatish Balay #endif
1562f15663dcSBarry Smith   }
1563dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1564f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1565d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
15663a40ed3dSBarry Smith   PetscFunctionReturn(0);
156717ab2063SBarry Smith }
156817ab2063SBarry Smith 
156917ab2063SBarry Smith /*
157017ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
157117ab2063SBarry Smith */
1572dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
157317ab2063SBarry Smith {
1574416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
15756849ba73SBarry Smith   PetscErrorCode ierr;
1576d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
157717ab2063SBarry Smith 
15783a40ed3dSBarry Smith   PetscFunctionBegin;
157909f38230SBarry Smith   if (!a->diag) {
1580785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
15813bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
158209f38230SBarry Smith   }
1583d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
158409f38230SBarry Smith     a->diag[i] = a->i[i+1];
1585bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1586bfeeae90SHong Zhang       if (a->j[j] == i) {
158709f38230SBarry Smith         a->diag[i] = j;
158817ab2063SBarry Smith         break;
158917ab2063SBarry Smith       }
159017ab2063SBarry Smith     }
159117ab2063SBarry Smith   }
15923a40ed3dSBarry Smith   PetscFunctionReturn(0);
159317ab2063SBarry Smith }
159417ab2063SBarry Smith 
159561ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
159661ecd0c6SBarry Smith {
159761ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
159861ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
159961ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
160061ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
160161ecd0c6SBarry Smith   PetscErrorCode    ierr;
160261ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
160361ecd0c6SBarry Smith 
160461ecd0c6SBarry Smith   PetscFunctionBegin;
160561ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
160661ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
160761ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
160861ecd0c6SBarry Smith     PetscFunctionReturn(0);
160961ecd0c6SBarry Smith   }
161061ecd0c6SBarry Smith 
161161ecd0c6SBarry Smith   if (a->diagonaldense) {
161261ecd0c6SBarry Smith     cnt = 0;
161361ecd0c6SBarry Smith   } else {
161461ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
161561ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
161661ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
161761ecd0c6SBarry Smith         cnt++;
161861ecd0c6SBarry Smith         mdiag[i] = 1;
161961ecd0c6SBarry Smith       }
162061ecd0c6SBarry Smith     }
162161ecd0c6SBarry Smith   }
162261ecd0c6SBarry Smith   if (!cnt) {
162361ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
162461ecd0c6SBarry Smith   } else {
1625b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1626b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
162761ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
162861ecd0c6SBarry Smith 
162961ecd0c6SBarry Smith     a->a = NULL;
163061ecd0c6SBarry Smith     a->j = NULL;
163161ecd0c6SBarry Smith     a->i = NULL;
163261ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
163361ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
163461ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1635447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
163661ecd0c6SBarry Smith     }
163761ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
163861ecd0c6SBarry Smith 
163961ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
164061ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
164161ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1642447d62f5SStefano Zampini       if (i < A->cmap->n) {
164361ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
164461ecd0c6SBarry Smith       }
1645447d62f5SStefano Zampini     }
164661ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
164761ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
164861ecd0c6SBarry Smith     if (singlemalloc) {
164961ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
165061ecd0c6SBarry Smith     } else {
165161ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
165261ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
165361ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
165461ecd0c6SBarry Smith     }
165561ecd0c6SBarry Smith   }
165661ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
165761ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
165861ecd0c6SBarry Smith   PetscFunctionReturn(0);
165961ecd0c6SBarry Smith }
166061ecd0c6SBarry Smith 
1661be5855fcSBarry Smith /*
1662be5855fcSBarry Smith      Checks for missing diagonals
1663be5855fcSBarry Smith */
1664ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1665be5855fcSBarry Smith {
1666be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
16677734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1668994fe344SLisandro Dalcin   PetscErrorCode ierr;
1669be5855fcSBarry Smith 
1670be5855fcSBarry Smith   PetscFunctionBegin;
167109f38230SBarry Smith   *missing = PETSC_FALSE;
16727734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
167309f38230SBarry Smith     *missing = PETSC_TRUE;
167409f38230SBarry Smith     if (d) *d = 0;
1675994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
167609f38230SBarry Smith   } else {
167701445905SHong Zhang     PetscInt n;
167801445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1679f1e2ffcdSBarry Smith     diag = a->diag;
168001445905SHong Zhang     for (i=0; i<n; i++) {
16817734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
168209f38230SBarry Smith         *missing = PETSC_TRUE;
168309f38230SBarry Smith         if (d) *d = i;
1684994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1685358d2f5dSShri Abhyankar         break;
168609f38230SBarry Smith       }
1687be5855fcSBarry Smith     }
1688be5855fcSBarry Smith   }
1689be5855fcSBarry Smith   PetscFunctionReturn(0);
1690be5855fcSBarry Smith }
1691be5855fcSBarry Smith 
16920da83c2eSBarry Smith #include <petscblaslapack.h>
16930da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
16940da83c2eSBarry Smith 
16950da83c2eSBarry Smith /*
16960da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
16970da83c2eSBarry Smith */
16980da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
16990da83c2eSBarry Smith {
17000da83c2eSBarry Smith   PetscErrorCode  ierr;
17010da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
17020da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
17030da83c2eSBarry Smith   const PetscReal shift = 0.0;
17040da83c2eSBarry Smith   PetscInt        ipvt[5];
17050da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
17060da83c2eSBarry Smith 
17070da83c2eSBarry Smith   PetscFunctionBegin;
17080da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
17090da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
17100da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
17110da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
17120da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
17130da83c2eSBarry Smith   }
17140da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
17150da83c2eSBarry Smith   if (bsizemax > 7) {
17160da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
17170da83c2eSBarry Smith   }
17180da83c2eSBarry Smith   ncnt = 0;
17190da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
17200da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
17210da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
17220da83c2eSBarry Smith     switch (bsizes[i]) {
17230da83c2eSBarry Smith     case 1:
17240da83c2eSBarry Smith       *diag = 1.0/(*diag);
17250da83c2eSBarry Smith       break;
17260da83c2eSBarry Smith     case 2:
17270da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17280da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17290da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
17300da83c2eSBarry Smith       break;
17310da83c2eSBarry Smith     case 3:
17320da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17330da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17340da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
17350da83c2eSBarry Smith       break;
17360da83c2eSBarry Smith     case 4:
17370da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17380da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17390da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
17400da83c2eSBarry Smith       break;
17410da83c2eSBarry Smith     case 5:
17420da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17430da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17440da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
17450da83c2eSBarry Smith       break;
17460da83c2eSBarry Smith     case 6:
17470da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17480da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17490da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
17500da83c2eSBarry Smith       break;
17510da83c2eSBarry Smith     case 7:
17520da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17530da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17540da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
17550da83c2eSBarry Smith       break;
17560da83c2eSBarry Smith     default:
17570da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17580da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17590da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
17600da83c2eSBarry Smith     }
17610da83c2eSBarry Smith     ncnt   += bsizes[i];
17620da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
17630da83c2eSBarry Smith   }
17640da83c2eSBarry Smith   if (bsizemax > 7) {
17650da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
17660da83c2eSBarry Smith   }
17670da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
17680da83c2eSBarry Smith   PetscFunctionReturn(0);
17690da83c2eSBarry Smith }
17700da83c2eSBarry Smith 
1771422a814eSBarry Smith /*
1772422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1773422a814eSBarry Smith */
17747087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
177571f1c65dSBarry Smith {
177671f1c65dSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*) A->data;
177771f1c65dSBarry Smith   PetscErrorCode ierr;
1778d0f46423SBarry Smith   PetscInt       i,*diag,m = A->rmap->n;
177954f21887SBarry Smith   MatScalar      *v = a->a;
178054f21887SBarry Smith   PetscScalar    *idiag,*mdiag;
178171f1c65dSBarry Smith 
178271f1c65dSBarry Smith   PetscFunctionBegin;
178371f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
178471f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
178571f1c65dSBarry Smith   diag = a->diag;
178671f1c65dSBarry Smith   if (!a->idiag) {
1787dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
17883bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr);
178971f1c65dSBarry Smith     v    = a->a;
179071f1c65dSBarry Smith   }
179171f1c65dSBarry Smith   mdiag = a->mdiag;
179271f1c65dSBarry Smith   idiag = a->idiag;
179371f1c65dSBarry Smith 
1794422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
179571f1c65dSBarry Smith     for (i=0; i<m; i++) {
179671f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1797899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1798899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1799899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
18007b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18017b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
18027b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1803a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1804899639b0SHong Zhang       }
180571f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
180671f1c65dSBarry Smith     }
180771f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
180871f1c65dSBarry Smith   } else {
180971f1c65dSBarry Smith     for (i=0; i<m; i++) {
181071f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
181171f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
181271f1c65dSBarry Smith     }
1813dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
181471f1c65dSBarry Smith   }
181571f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
181671f1c65dSBarry Smith   PetscFunctionReturn(0);
181771f1c65dSBarry Smith }
181871f1c65dSBarry Smith 
1819c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
182041f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
182117ab2063SBarry Smith {
1822416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1823e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
18243d3eaba7SBarry Smith   const MatScalar   *v,*idiag=0,*mdiag;
182554f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1826dfbe8321SBarry Smith   PetscErrorCode    ierr;
18273d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
182897f1f81fSBarry Smith   const PetscInt    *idx,*diag;
182917ab2063SBarry Smith 
18303a40ed3dSBarry Smith   PetscFunctionBegin;
1831b965ef7fSBarry Smith   its = its*lits;
183291723122SBarry Smith 
183371f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
183471f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
183571f1c65dSBarry Smith   a->fshift = fshift;
183671f1c65dSBarry Smith   a->omega  = omega;
1837ed480e8bSBarry Smith 
183871f1c65dSBarry Smith   diag  = a->diag;
183971f1c65dSBarry Smith   t     = a->ssor_work;
1840ed480e8bSBarry Smith   idiag = a->idiag;
184171f1c65dSBarry Smith   mdiag = a->mdiag;
1842ed480e8bSBarry Smith 
18431ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
18443649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
1845ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
184617ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
184717ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1848ed480e8bSBarry Smith     bs = b;
184917ab2063SBarry Smith     for (i=0; i<m; i++) {
185071f1c65dSBarry Smith       d   = fshift + mdiag[i];
1851416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1852ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
1853ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
185417ab2063SBarry Smith       sum = b[i]*d/omega;
1855003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
185617ab2063SBarry Smith       x[i] = sum;
185717ab2063SBarry Smith     }
18581ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
18593649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1860efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
18613a40ed3dSBarry Smith     PetscFunctionReturn(0);
186217ab2063SBarry Smith   }
1863c783ea89SBarry Smith 
18642205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
18652205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
18664c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
1867887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
186817ab2063SBarry Smith 
186917ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
187017ab2063SBarry Smith 
1871887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
187217ab2063SBarry Smith     */
187317ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
187417ab2063SBarry Smith 
187517ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
187617ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
1877416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1878ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
1879ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
188017ab2063SBarry Smith       sum = b[i];
1881e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
1882ed480e8bSBarry Smith       x[i] = sum*idiag[i];
188317ab2063SBarry Smith     }
188417ab2063SBarry Smith 
188517ab2063SBarry Smith     /*  t = b - (2*E - D)x */
1886416022c9SBarry Smith     v = a->a;
18872205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
188817ab2063SBarry Smith 
188917ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
1890ed480e8bSBarry Smith     ts   = t;
1891416022c9SBarry Smith     diag = a->diag;
189217ab2063SBarry Smith     for (i=0; i<m; i++) {
1893416022c9SBarry Smith       n   = diag[i] - a->i[i];
1894ed480e8bSBarry Smith       idx = a->j + a->i[i];
1895ed480e8bSBarry Smith       v   = a->a + a->i[i];
189617ab2063SBarry Smith       sum = t[i];
1897003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
1898ed480e8bSBarry Smith       t[i] = sum*idiag[i];
1899733d66baSBarry Smith       /*  x = x + t */
1900733d66baSBarry Smith       x[i] += t[i];
190117ab2063SBarry Smith     }
190217ab2063SBarry Smith 
1903dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
19041ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
19053649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
19063a40ed3dSBarry Smith     PetscFunctionReturn(0);
190717ab2063SBarry Smith   }
190817ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
190917ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
191017ab2063SBarry Smith       for (i=0; i<m; i++) {
1911416022c9SBarry Smith         n   = diag[i] - a->i[i];
1912ed480e8bSBarry Smith         idx = a->j + a->i[i];
1913ed480e8bSBarry Smith         v   = a->a + a->i[i];
191417ab2063SBarry Smith         sum = b[i];
1915e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
19165c99c7daSBarry Smith         t[i] = sum;
1917ed480e8bSBarry Smith         x[i] = sum*idiag[i];
191817ab2063SBarry Smith       }
19195c99c7daSBarry Smith       xb   = t;
1920efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
19213a40ed3dSBarry Smith     } else xb = b;
192217ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
192317ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
1924416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
1925ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
1926ed480e8bSBarry Smith         v   = a->a + diag[i] + 1;
192717ab2063SBarry Smith         sum = xb[i];
1928e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
19295c99c7daSBarry Smith         if (xb == b) {
1930ed480e8bSBarry Smith           x[i] = sum*idiag[i];
19315c99c7daSBarry Smith         } else {
1932b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
193317ab2063SBarry Smith         }
19345c99c7daSBarry Smith       }
1935b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
193617ab2063SBarry Smith     }
193717ab2063SBarry Smith     its--;
193817ab2063SBarry Smith   }
193917ab2063SBarry Smith   while (its--) {
194017ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
194117ab2063SBarry Smith       for (i=0; i<m; i++) {
1942b19a5dc2SMark Adams         /* lower */
1943b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
1944ed480e8bSBarry Smith         idx = a->j + a->i[i];
1945ed480e8bSBarry Smith         v   = a->a + a->i[i];
194617ab2063SBarry Smith         sum = b[i];
1947e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1948b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
1949b19a5dc2SMark Adams         /* upper */
1950b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
1951b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
1952b19a5dc2SMark Adams         v   = a->a + diag[i] + 1;
1953b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1954b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
195517ab2063SBarry Smith       }
1956b19a5dc2SMark Adams       xb   = t;
19579f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1958b19a5dc2SMark Adams     } else xb = b;
195917ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
196017ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
1961b19a5dc2SMark Adams         sum = xb[i];
1962b19a5dc2SMark Adams         if (xb == b) {
1963b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
1964416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
1965ed480e8bSBarry Smith           idx = a->j + a->i[i];
1966ed480e8bSBarry Smith           v   = a->a + a->i[i];
1967e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
1968ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1969b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
1970b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
1971b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
1972b19a5dc2SMark Adams           v   = a->a + diag[i] + 1;
1973b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
1974b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
197517ab2063SBarry Smith         }
1976b19a5dc2SMark Adams       }
1977b19a5dc2SMark Adams       if (xb == b) {
19789f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1979b19a5dc2SMark Adams       } else {
1980b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
1981b19a5dc2SMark Adams       }
198217ab2063SBarry Smith     }
198317ab2063SBarry Smith   }
19841ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
19853649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1986365a8a9eSBarry Smith   PetscFunctionReturn(0);
198717ab2063SBarry Smith }
198817ab2063SBarry Smith 
19892af78befSBarry Smith 
1990dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
199117ab2063SBarry Smith {
1992416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
19934e220ebcSLois Curfman McInnes 
19943a40ed3dSBarry Smith   PetscFunctionBegin;
19954e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
19963966268fSBarry Smith   info->nz_allocated = a->maxnz;
19973966268fSBarry Smith   info->nz_used      = a->nz;
19983966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
19993966268fSBarry Smith   info->assemblies   = A->num_ass;
20003966268fSBarry Smith   info->mallocs      = A->info.mallocs;
20017adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2002d5f3da31SBarry Smith   if (A->factortype) {
20034e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
20044e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
20054e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
20064e220ebcSLois Curfman McInnes   } else {
20074e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
20084e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
20094e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
20104e220ebcSLois Curfman McInnes   }
20113a40ed3dSBarry Smith   PetscFunctionReturn(0);
201217ab2063SBarry Smith }
201317ab2063SBarry Smith 
20142b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
201517ab2063SBarry Smith {
2016416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2017c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
20186849ba73SBarry Smith   PetscErrorCode    ierr;
201997b48c8fSBarry Smith   const PetscScalar *xx;
202097b48c8fSBarry Smith   PetscScalar       *bb;
2021c7da8527SEric Chamberland   PetscInt          d = 0;
202217ab2063SBarry Smith 
20233a40ed3dSBarry Smith   PetscFunctionBegin;
202497b48c8fSBarry Smith   if (x && b) {
202597b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
202697b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
202797b48c8fSBarry Smith     for (i=0; i<N; i++) {
202897b48c8fSBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2029447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
203097b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
203197b48c8fSBarry Smith     }
203297b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
203397b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
203497b48c8fSBarry Smith   }
203597b48c8fSBarry Smith 
2036a9817697SBarry Smith   if (a->keepnonzeropattern) {
2037f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
2038e32f2f54SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2039580bdb30SBarry Smith       ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2040f1e2ffcdSBarry Smith     }
2041f4df32b1SMatthew Knepley     if (diag != 0.0) {
2042c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2043c7da8527SEric Chamberland         d = rows[i];
2044447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2045c7da8527SEric 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);
2046c7da8527SEric Chamberland       }
2047f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2048447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2049f4df32b1SMatthew Knepley         a->a[a->diag[rows[i]]] = diag;
2050f1e2ffcdSBarry Smith       }
2051f1e2ffcdSBarry Smith     }
2052f1e2ffcdSBarry Smith   } else {
2053f4df32b1SMatthew Knepley     if (diag != 0.0) {
205417ab2063SBarry Smith       for (i=0; i<N; i++) {
2055e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
20567ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2057447d62f5SStefano Zampini 	  if (rows[i] >= A->cmap->n) {
2058447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2059447d62f5SStefano Zampini           } else {
2060416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
2061f4df32b1SMatthew Knepley             a->a[a->i[rows[i]]] = diag;
2062bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2063447d62f5SStefano Zampini           }
2064447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2065f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
206617ab2063SBarry Smith         }
206717ab2063SBarry Smith       }
20683a40ed3dSBarry Smith     } else {
206917ab2063SBarry Smith       for (i=0; i<N; i++) {
2070e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2071416022c9SBarry Smith         a->ilen[rows[i]] = 0;
207217ab2063SBarry Smith       }
207317ab2063SBarry Smith     }
2074e56f5c9eSBarry Smith     A->nonzerostate++;
2075f1e2ffcdSBarry Smith   }
2076e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2077c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2078e2cf4d64SStefano Zampini #endif
20794099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20803a40ed3dSBarry Smith   PetscFunctionReturn(0);
208117ab2063SBarry Smith }
208217ab2063SBarry Smith 
20836e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
20846e169961SBarry Smith {
20856e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
20866e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
20876e169961SBarry Smith   PetscErrorCode    ierr;
20882b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
20896e169961SBarry Smith   const PetscScalar *xx;
20906e169961SBarry Smith   PetscScalar       *bb;
20916e169961SBarry Smith 
20926e169961SBarry Smith   PetscFunctionBegin;
20936e169961SBarry Smith   if (x && b) {
20946e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
20956e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
20962b40b63fSBarry Smith     vecs = PETSC_TRUE;
20976e169961SBarry Smith   }
20981795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
20996e169961SBarry Smith   for (i=0; i<N; i++) {
21006e169961SBarry Smith     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2101580bdb30SBarry Smith     ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
21022205254eSKarl Rupp 
21036e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
21046e169961SBarry Smith   }
21056e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
21066e169961SBarry Smith     if (!zeroed[i]) {
21076e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
21084cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
21092b40b63fSBarry Smith           if (vecs) bb[i] -= a->a[j]*xx[a->j[j]];
21106e169961SBarry Smith           a->a[j] = 0.0;
21116e169961SBarry Smith         }
21126e169961SBarry Smith       }
21134cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
21146e169961SBarry Smith   }
21156e169961SBarry Smith   if (x && b) {
21166e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
21176e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
21186e169961SBarry Smith   }
21196e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
21206e169961SBarry Smith   if (diag != 0.0) {
21216e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
21221d5a398dSstefano_zampini     if (missing) {
21231d5a398dSstefano_zampini       for (i=0; i<N; i++) {
21244cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
21254cf107fdSStefano 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]);
21261d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
21271d5a398dSstefano_zampini       }
21281d5a398dSstefano_zampini     } else {
21296e169961SBarry Smith       for (i=0; i<N; i++) {
21306e169961SBarry Smith         a->a[a->diag[rows[i]]] = diag;
21316e169961SBarry Smith       }
21326e169961SBarry Smith     }
21331d5a398dSstefano_zampini   }
2134e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2135c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2136e2cf4d64SStefano Zampini #endif
21374099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
21386e169961SBarry Smith   PetscFunctionReturn(0);
21396e169961SBarry Smith }
21406e169961SBarry Smith 
2141a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
214217ab2063SBarry Smith {
2143416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
214497f1f81fSBarry Smith   PetscInt   *itmp;
214517ab2063SBarry Smith 
21463a40ed3dSBarry Smith   PetscFunctionBegin;
2147e32f2f54SBarry Smith   if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row);
214817ab2063SBarry Smith 
2149416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
2150bfeeae90SHong Zhang   if (v) *v = a->a + a->i[row];
215117ab2063SBarry Smith   if (idx) {
2152bfeeae90SHong Zhang     itmp = a->j + a->i[row];
215326fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
215417ab2063SBarry Smith     else *idx = 0;
215517ab2063SBarry Smith   }
21563a40ed3dSBarry Smith   PetscFunctionReturn(0);
215717ab2063SBarry Smith }
215817ab2063SBarry Smith 
2159bfeeae90SHong Zhang /* remove this function? */
2160a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
216117ab2063SBarry Smith {
21623a40ed3dSBarry Smith   PetscFunctionBegin;
21633a40ed3dSBarry Smith   PetscFunctionReturn(0);
216417ab2063SBarry Smith }
216517ab2063SBarry Smith 
2166dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
216717ab2063SBarry Smith {
2168416022c9SBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
216954f21887SBarry Smith   MatScalar      *v  = a->a;
217036db0b34SBarry Smith   PetscReal      sum = 0.0;
21716849ba73SBarry Smith   PetscErrorCode ierr;
217297f1f81fSBarry Smith   PetscInt       i,j;
217317ab2063SBarry Smith 
21743a40ed3dSBarry Smith   PetscFunctionBegin;
217517ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2176570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2177570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
2178570b7f6dSBarry Smith     *nrm = BLASnrm2_(&nz,v,&one);
2179570b7f6dSBarry Smith #else
2180416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
218136db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
218217ab2063SBarry Smith     }
21838f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2184570b7f6dSBarry Smith #endif
218551f70360SJed Brown     ierr = PetscLogFlops(2*a->nz);CHKERRQ(ierr);
21863a40ed3dSBarry Smith   } else if (type == NORM_1) {
218736db0b34SBarry Smith     PetscReal *tmp;
218897f1f81fSBarry Smith     PetscInt  *jj = a->j;
21891795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2190064f8208SBarry Smith     *nrm = 0.0;
2191416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2192bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
219317ab2063SBarry Smith     }
2194d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2195064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
219617ab2063SBarry Smith     }
2197606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
219851f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
21993a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2200064f8208SBarry Smith     *nrm = 0.0;
2201d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
2202bfeeae90SHong Zhang       v   = a->a + a->i[j];
220317ab2063SBarry Smith       sum = 0.0;
2204416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
2205cddf8d76SBarry Smith         sum += PetscAbsScalar(*v); v++;
220617ab2063SBarry Smith       }
2207064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
220817ab2063SBarry Smith     }
220951f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2210f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
22113a40ed3dSBarry Smith   PetscFunctionReturn(0);
221217ab2063SBarry Smith }
221317ab2063SBarry Smith 
22144e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
22154e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
22164e938277SHong Zhang {
22174e938277SHong Zhang   PetscErrorCode ierr;
22184e938277SHong Zhang   PetscInt       i,j,anzj;
22194e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
22204e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
22214e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
22224e938277SHong Zhang 
22234e938277SHong Zhang   PetscFunctionBegin;
22244e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2225854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2226785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2227785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
22284e938277SHong Zhang 
22294e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
22304e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
223126fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
22324e938277SHong Zhang   /* Form ati for csr format of A^T. */
223326fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
22344e938277SHong Zhang 
22354e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2236580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
22374e938277SHong Zhang 
22384e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
22394e938277SHong Zhang   for (i=0;i<am;i++) {
22404e938277SHong Zhang     anzj = ai[i+1] - ai[i];
22414e938277SHong Zhang     for (j=0;j<anzj;j++) {
22424e938277SHong Zhang       atj[atfill[*aj]] = i;
22434e938277SHong Zhang       atfill[*aj++]   += 1;
22444e938277SHong Zhang     }
22454e938277SHong Zhang   }
22464e938277SHong Zhang 
22474e938277SHong Zhang   /* Clean up temporary space and complete requests. */
22484e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2249ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
225033d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2251b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2252a2f3521dSMark F. Adams 
22534e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
22544e938277SHong Zhang   b->free_a  = PETSC_FALSE;
22554e938277SHong Zhang   b->free_ij = PETSC_TRUE;
22564e938277SHong Zhang   b->nonew   = 0;
22574e938277SHong Zhang   PetscFunctionReturn(0);
22584e938277SHong Zhang }
22594e938277SHong Zhang 
22607087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2261cd0d46ebSvictorle {
22623d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
226354f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
226454f21887SBarry Smith   MatScalar      *va,*vb;
22656849ba73SBarry Smith   PetscErrorCode ierr;
226697f1f81fSBarry Smith   PetscInt       ma,na,mb,nb, i;
2267cd0d46ebSvictorle 
2268cd0d46ebSvictorle   PetscFunctionBegin;
2269cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2270cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
22715485867bSBarry Smith   if (ma!=nb || na!=mb) {
22725485867bSBarry Smith     *f = PETSC_FALSE;
22735485867bSBarry Smith     PetscFunctionReturn(0);
22745485867bSBarry Smith   }
2275cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2276cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2277cd0d46ebSvictorle   va   = aij->a; vb = bij->a;
2278785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2279785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2280cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2281cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2282cd0d46ebSvictorle 
2283cd0d46ebSvictorle   *f = PETSC_TRUE;
2284cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2285cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
228697f1f81fSBarry Smith       PetscInt    idc,idr;
22875485867bSBarry Smith       PetscScalar vc,vr;
2288cd0d46ebSvictorle       /* column/row index/value */
22895485867bSBarry Smith       idc = adx[aptr[i]];
22905485867bSBarry Smith       idr = bdx[bptr[idc]];
22915485867bSBarry Smith       vc  = va[aptr[i]];
22925485867bSBarry Smith       vr  = vb[bptr[idc]];
22935485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
22945485867bSBarry Smith         *f = PETSC_FALSE;
22955485867bSBarry Smith         goto done;
2296cd0d46ebSvictorle       } else {
22975485867bSBarry Smith         aptr[i]++;
22985485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2299cd0d46ebSvictorle       }
2300cd0d46ebSvictorle     }
2301cd0d46ebSvictorle   }
2302cd0d46ebSvictorle done:
2303cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
23043aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
2305cd0d46ebSvictorle   PetscFunctionReturn(0);
2306cd0d46ebSvictorle }
2307cd0d46ebSvictorle 
23087087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
23091cbb95d3SBarry Smith {
23103d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
231154f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
231254f21887SBarry Smith   MatScalar      *va,*vb;
23131cbb95d3SBarry Smith   PetscErrorCode ierr;
23141cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
23151cbb95d3SBarry Smith 
23161cbb95d3SBarry Smith   PetscFunctionBegin;
23171cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
23181cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
23191cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
23201cbb95d3SBarry Smith     *f = PETSC_FALSE;
23211cbb95d3SBarry Smith     PetscFunctionReturn(0);
23221cbb95d3SBarry Smith   }
23231cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
23241cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
23251cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2326785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2327785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
23281cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
23291cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
23301cbb95d3SBarry Smith 
23311cbb95d3SBarry Smith   *f = PETSC_TRUE;
23321cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
23331cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
23341cbb95d3SBarry Smith       PetscInt    idc,idr;
23351cbb95d3SBarry Smith       PetscScalar vc,vr;
23361cbb95d3SBarry Smith       /* column/row index/value */
23371cbb95d3SBarry Smith       idc = adx[aptr[i]];
23381cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
23391cbb95d3SBarry Smith       vc  = va[aptr[i]];
23401cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
23411cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
23421cbb95d3SBarry Smith         *f = PETSC_FALSE;
23431cbb95d3SBarry Smith         goto done;
23441cbb95d3SBarry Smith       } else {
23451cbb95d3SBarry Smith         aptr[i]++;
23461cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
23471cbb95d3SBarry Smith       }
23481cbb95d3SBarry Smith     }
23491cbb95d3SBarry Smith   }
23501cbb95d3SBarry Smith done:
23511cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
23521cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
23531cbb95d3SBarry Smith   PetscFunctionReturn(0);
23541cbb95d3SBarry Smith }
23551cbb95d3SBarry Smith 
2356ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
23579e29f15eSvictorle {
2358dfbe8321SBarry Smith   PetscErrorCode ierr;
23596e111a19SKarl Rupp 
23609e29f15eSvictorle   PetscFunctionBegin;
23615485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
23629e29f15eSvictorle   PetscFunctionReturn(0);
23639e29f15eSvictorle }
23649e29f15eSvictorle 
2365ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
23661cbb95d3SBarry Smith {
23671cbb95d3SBarry Smith   PetscErrorCode ierr;
23686e111a19SKarl Rupp 
23691cbb95d3SBarry Smith   PetscFunctionBegin;
23701cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
23711cbb95d3SBarry Smith   PetscFunctionReturn(0);
23721cbb95d3SBarry Smith }
23731cbb95d3SBarry Smith 
2374dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
237517ab2063SBarry Smith {
2376416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2377fff8e43fSBarry Smith   const PetscScalar *l,*r;
2378fff8e43fSBarry Smith   PetscScalar       x;
237954f21887SBarry Smith   MatScalar         *v;
2380dfbe8321SBarry Smith   PetscErrorCode    ierr;
2381fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2382fff8e43fSBarry Smith   const PetscInt    *jj;
238317ab2063SBarry Smith 
23843a40ed3dSBarry Smith   PetscFunctionBegin;
238517ab2063SBarry Smith   if (ll) {
23863ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
23873ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2388e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
2389e32f2f54SBarry Smith     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2390fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
2391416022c9SBarry Smith     v    = a->a;
239217ab2063SBarry Smith     for (i=0; i<m; i++) {
239317ab2063SBarry Smith       x = l[i];
2394416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
23952205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
239617ab2063SBarry Smith     }
2397fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2398efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
239917ab2063SBarry Smith   }
240017ab2063SBarry Smith   if (rr) {
2401e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
2402e32f2f54SBarry Smith     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2403fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
2404416022c9SBarry Smith     v    = a->a; jj = a->j;
24052205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
2406fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2407efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
240817ab2063SBarry Smith   }
2409acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
2410e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2411c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2412e2cf4d64SStefano Zampini #endif
24133a40ed3dSBarry Smith   PetscFunctionReturn(0);
241417ab2063SBarry Smith }
241517ab2063SBarry Smith 
24167dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
241717ab2063SBarry Smith {
2418db02288aSLois Curfman McInnes   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*c;
24196849ba73SBarry Smith   PetscErrorCode ierr;
2420d0f46423SBarry Smith   PetscInt       *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
242197f1f81fSBarry Smith   PetscInt       row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
24225d0c19d7SBarry Smith   const PetscInt *irow,*icol;
24235d0c19d7SBarry Smith   PetscInt       nrows,ncols;
242497f1f81fSBarry Smith   PetscInt       *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
242554f21887SBarry Smith   MatScalar      *a_new,*mat_a;
2426416022c9SBarry Smith   Mat            C;
2427cdc6f3adSToby Isaac   PetscBool      stride;
242817ab2063SBarry Smith 
24293a40ed3dSBarry Smith   PetscFunctionBegin;
243099141d43SSatish Balay 
243117ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2432b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2433b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
243417ab2063SBarry Smith 
2435251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2436ff718158SBarry Smith   if (stride) {
2437ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2438ff718158SBarry Smith   } else {
2439ff718158SBarry Smith     first = 0;
2440ff718158SBarry Smith     step  = 0;
2441ff718158SBarry Smith   }
2442fee21e36SBarry Smith   if (stride && step == 1) {
244302834360SBarry Smith     /* special case of contiguous rows */
2444dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
244502834360SBarry Smith     /* loop over new rows determining lens and starting points */
244602834360SBarry Smith     for (i=0; i<nrows; i++) {
2447bfeeae90SHong Zhang       kstart = ai[irow[i]];
2448a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2449a91a9bebSLisandro Dalcin       starts[i] = kstart;
245002834360SBarry Smith       for (k=kstart; k<kend; k++) {
2451bfeeae90SHong Zhang         if (aj[k] >= first) {
245202834360SBarry Smith           starts[i] = k;
245302834360SBarry Smith           break;
245402834360SBarry Smith         }
245502834360SBarry Smith       }
2456a2744918SBarry Smith       sum = 0;
245702834360SBarry Smith       while (k < kend) {
2458bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2459a2744918SBarry Smith         sum++;
246002834360SBarry Smith       }
2461a2744918SBarry Smith       lens[i] = sum;
246202834360SBarry Smith     }
246302834360SBarry Smith     /* create submatrix */
2464cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
246597f1f81fSBarry Smith       PetscInt n_cols,n_rows;
246608480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2467e32f2f54SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2468d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
246908480c60SBarry Smith       C    = *B;
24703a40ed3dSBarry Smith     } else {
24713bef6203SJed Brown       PetscInt rbs,cbs;
2472ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2473f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
24743bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
24753bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
24763bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
24777adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2478ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
247908480c60SBarry Smith     }
2480db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2481db02288aSLois Curfman McInnes 
248202834360SBarry Smith     /* loop over rows inserting into submatrix */
2483db02288aSLois Curfman McInnes     a_new = c->a;
2484db02288aSLois Curfman McInnes     j_new = c->j;
2485db02288aSLois Curfman McInnes     i_new = c->i;
2486bfeeae90SHong Zhang 
248702834360SBarry Smith     for (i=0; i<nrows; i++) {
2488a2744918SBarry Smith       ii    = starts[i];
2489a2744918SBarry Smith       lensi = lens[i];
2490a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2491a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
249202834360SBarry Smith       }
2493580bdb30SBarry Smith       ierr       = PetscArraycpy(a_new,a->a + starts[i],lensi);CHKERRQ(ierr);
2494a2744918SBarry Smith       a_new     += lensi;
2495a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2496a2744918SBarry Smith       c->ilen[i] = lensi;
249702834360SBarry Smith     }
24980e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
24993a40ed3dSBarry Smith   } else {
250002834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
25011795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2502854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
25034dcab191SBarry Smith     for (i=0; i<ncols; i++) {
25044dcab191SBarry Smith #if defined(PETSC_USE_DEBUG)
25054dcab191SBarry Smith       if (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);
25064dcab191SBarry Smith #endif
25074dcab191SBarry Smith       smap[icol[i]] = i+1;
25084dcab191SBarry Smith     }
25094dcab191SBarry Smith 
251002834360SBarry Smith     /* determine lens of each row */
251102834360SBarry Smith     for (i=0; i<nrows; i++) {
2512bfeeae90SHong Zhang       kstart  = ai[irow[i]];
251302834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
251402834360SBarry Smith       lens[i] = 0;
251502834360SBarry Smith       for (k=kstart; k<kend; k++) {
2516bfeeae90SHong Zhang         if (smap[aj[k]]) {
251702834360SBarry Smith           lens[i]++;
251802834360SBarry Smith         }
251902834360SBarry Smith       }
252002834360SBarry Smith     }
252117ab2063SBarry Smith     /* Create and fill new matrix */
2522a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2523ace3abfcSBarry Smith       PetscBool equal;
25240f5bd95cSBarry Smith 
252599141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2526e32f2f54SBarry Smith       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2527580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
2528f23aa3ddSBarry Smith       if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2529580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
253008480c60SBarry Smith       C    = *B;
25313a40ed3dSBarry Smith     } else {
25323bef6203SJed Brown       PetscInt rbs,cbs;
2533ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2534f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
25353bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
25363bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
25373bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
25387adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2539ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
254008480c60SBarry Smith     }
254199141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
254217ab2063SBarry Smith     for (i=0; i<nrows; i++) {
254399141d43SSatish Balay       row      = irow[i];
2544bfeeae90SHong Zhang       kstart   = ai[row];
254599141d43SSatish Balay       kend     = kstart + a->ilen[row];
2546bfeeae90SHong Zhang       mat_i    = c->i[i];
254799141d43SSatish Balay       mat_j    = c->j + mat_i;
254899141d43SSatish Balay       mat_a    = c->a + mat_i;
254999141d43SSatish Balay       mat_ilen = c->ilen + i;
255017ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2551bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2552ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
255399141d43SSatish Balay           *mat_a++ = a->a[k];
255499141d43SSatish Balay           (*mat_ilen)++;
255599141d43SSatish Balay 
255617ab2063SBarry Smith         }
255717ab2063SBarry Smith       }
255817ab2063SBarry Smith     }
255902834360SBarry Smith     /* Free work space */
256002834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2561606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2562606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2563cdc6f3adSToby Isaac     /* sort */
2564cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2565cdc6f3adSToby Isaac       PetscInt ilen;
2566cdc6f3adSToby Isaac 
2567cdc6f3adSToby Isaac       mat_i = c->i[i];
2568cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2569cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2570cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2571390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2572cdc6f3adSToby Isaac     }
257302834360SBarry Smith   }
2574305c6ccfSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2575b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr);
2576305c6ccfSStefano Zampini #endif
25776d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
25786d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
257917ab2063SBarry Smith 
258017ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2581416022c9SBarry Smith   *B   = C;
25823a40ed3dSBarry Smith   PetscFunctionReturn(0);
258317ab2063SBarry Smith }
258417ab2063SBarry Smith 
2585fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
258682d44351SHong Zhang {
258782d44351SHong Zhang   PetscErrorCode ierr;
258882d44351SHong Zhang   Mat            B;
258982d44351SHong Zhang 
259082d44351SHong Zhang   PetscFunctionBegin;
2591c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
259282d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
259382d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
259433d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
259582d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
259682d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
259782d44351SHong Zhang     *subMat = B;
2598c2d650bdSHong Zhang   } else {
2599c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2600c2d650bdSHong Zhang   }
260182d44351SHong Zhang   PetscFunctionReturn(0);
260282d44351SHong Zhang }
260382d44351SHong Zhang 
26049a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2605a871dcd8SBarry Smith {
260663b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2607dfbe8321SBarry Smith   PetscErrorCode ierr;
260863b91edcSBarry Smith   Mat            outA;
2609ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
261063b91edcSBarry Smith 
26113a40ed3dSBarry Smith   PetscFunctionBegin;
2612e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
26131df811f5SHong Zhang 
2614b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2615b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2616a871dcd8SBarry Smith 
261763b91edcSBarry Smith   outA             = inA;
2618d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2619f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2620f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
26212205254eSKarl Rupp 
2622c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
26236bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
26242205254eSKarl Rupp 
2625c3122656SLisandro Dalcin   a->row = row;
26262205254eSKarl Rupp 
2627c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
26286bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
26292205254eSKarl Rupp 
2630c3122656SLisandro Dalcin   a->col = col;
263163b91edcSBarry Smith 
263236db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
26336bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
26344c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
26353bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2636f0ec6fceSSatish Balay 
263794a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2638854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
26393bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
264094a9d846SBarry Smith   }
264163b91edcSBarry Smith 
2642f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2643137fb511SHong Zhang   if (row_identity && col_identity) {
2644ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2645137fb511SHong Zhang   } else {
2646719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2647137fb511SHong Zhang   }
26483a40ed3dSBarry Smith   PetscFunctionReturn(0);
2649a871dcd8SBarry Smith }
2650a871dcd8SBarry Smith 
2651f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2652f0b747eeSBarry Smith {
2653f0b747eeSBarry Smith   Mat_SeqAIJ     *a     = (Mat_SeqAIJ*)inA->data;
2654f4df32b1SMatthew Knepley   PetscScalar    oalpha = alpha;
2655efee365bSSatish Balay   PetscErrorCode ierr;
2656c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
26573a40ed3dSBarry Smith 
26583a40ed3dSBarry Smith   PetscFunctionBegin;
2659c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
26608b83055fSJed Brown   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&oalpha,a->a,&one));
2661efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2662acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
2663e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2664c70f7ee4SJunchao Zhang   if (inA->offloadmask != PETSC_OFFLOAD_UNALLOCATED) inA->offloadmask = PETSC_OFFLOAD_CPU;
2665e2cf4d64SStefano Zampini #endif
26663a40ed3dSBarry Smith   PetscFunctionReturn(0);
2667f0b747eeSBarry Smith }
2668f0b747eeSBarry Smith 
2669f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
267016b64355SHong Zhang {
267116b64355SHong Zhang   PetscErrorCode ierr;
267216b64355SHong Zhang   PetscInt       i;
267316b64355SHong Zhang 
267416b64355SHong Zhang   PetscFunctionBegin;
267516b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
267616b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
267716b64355SHong Zhang 
267816b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
267916b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
268016b64355SHong Zhang     }
268116b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
268216b64355SHong Zhang 
268316b64355SHong Zhang     if (submatj->rbuf1) {
268416b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
268516b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
268616b64355SHong Zhang     }
268716b64355SHong Zhang 
268816b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
268916b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
269016b64355SHong Zhang     }
269116b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
269216b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
269316b64355SHong Zhang   }
269416b64355SHong Zhang 
269516b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
269616b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
269716b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
269816b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
269916b64355SHong Zhang #else
270016b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
270116b64355SHong Zhang #endif
270216b64355SHong Zhang 
270316b64355SHong Zhang   if (!submatj->allcolumns) {
270416b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
270516b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
270616b64355SHong Zhang #else
270716b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
270816b64355SHong Zhang #endif
270916b64355SHong Zhang   }
271016b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
271116b64355SHong Zhang 
271216b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
271316b64355SHong Zhang   PetscFunctionReturn(0);
271416b64355SHong Zhang }
271516b64355SHong Zhang 
27160fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
271716b64355SHong Zhang {
271816b64355SHong Zhang   PetscErrorCode ierr;
271916b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
27205c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
272116b64355SHong Zhang 
272216b64355SHong Zhang   PetscFunctionBegin;
272334136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2724f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
272516b64355SHong Zhang   PetscFunctionReturn(0);
272616b64355SHong Zhang }
272716b64355SHong Zhang 
27282d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
27292d033e1fSHong Zhang {
27302d033e1fSHong Zhang   PetscErrorCode ierr;
27312d033e1fSHong Zhang   PetscInt       i;
27320fb991dcSHong Zhang   Mat            C;
27330fb991dcSHong Zhang   Mat_SeqAIJ     *c;
27340fb991dcSHong Zhang   Mat_SubSppt    *submatj;
27352d033e1fSHong Zhang 
27362d033e1fSHong Zhang   PetscFunctionBegin;
27372d033e1fSHong Zhang   for (i=0; i<n; i++) {
27380fb991dcSHong Zhang     C       = (*mat)[i];
27390fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
27400fb991dcSHong Zhang     submatj = c->submatis1;
27412d033e1fSHong Zhang     if (submatj) {
2742682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
274334136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2744f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
274534136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
27462d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
27472d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
27482d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2749682e4c99SStefano Zampini       }
27502d033e1fSHong Zhang     } else {
27512d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
27522d033e1fSHong Zhang     }
27532d033e1fSHong Zhang   }
275486e85357SHong Zhang 
275563a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
275663a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
275763a75b2aSHong Zhang 
27582d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
27592d033e1fSHong Zhang   PetscFunctionReturn(0);
27602d033e1fSHong Zhang }
27612d033e1fSHong Zhang 
27627dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2763cddf8d76SBarry Smith {
2764dfbe8321SBarry Smith   PetscErrorCode ierr;
276597f1f81fSBarry Smith   PetscInt       i;
2766cddf8d76SBarry Smith 
27673a40ed3dSBarry Smith   PetscFunctionBegin;
2768cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2769df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2770cddf8d76SBarry Smith   }
2771cddf8d76SBarry Smith 
2772cddf8d76SBarry Smith   for (i=0; i<n; i++) {
27737dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2774cddf8d76SBarry Smith   }
27753a40ed3dSBarry Smith   PetscFunctionReturn(0);
2776cddf8d76SBarry Smith }
2777cddf8d76SBarry Smith 
277897f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
27794dcbc457SBarry Smith {
2780e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
27816849ba73SBarry Smith   PetscErrorCode ierr;
27825d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
27835d0c19d7SBarry Smith   const PetscInt *idx;
278497f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2785f1af5d2fSBarry Smith   PetscBT        table;
2786bbd702dbSSatish Balay 
27873a40ed3dSBarry Smith   PetscFunctionBegin;
2788d0f46423SBarry Smith   m  = A->rmap->n;
2789e4d965acSSatish Balay   ai = a->i;
2790bfeeae90SHong Zhang   aj = a->j;
27918a047759SSatish Balay 
2792e32f2f54SBarry Smith   if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
279306763907SSatish Balay 
2794854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
279553b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
279606763907SSatish Balay 
2797e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2798b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2799e4d965acSSatish Balay     isz  = 0;
28006831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2801e4d965acSSatish Balay 
2802e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
28034dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2804b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
2805e4d965acSSatish Balay 
2806dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2807e4d965acSSatish Balay     for (j=0; j<n; ++j) {
28082205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
28094dcbc457SBarry Smith     }
281006763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
28116bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
2812e4d965acSSatish Balay 
281304a348a9SBarry Smith     k = 0;
281404a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
281504a348a9SBarry Smith       n = isz;
281606763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2817e4d965acSSatish Balay         row   = nidx[k];
2818e4d965acSSatish Balay         start = ai[row];
2819e4d965acSSatish Balay         end   = ai[row+1];
282004a348a9SBarry Smith         for (l = start; l<end; l++) {
2821efb16452SHong Zhang           val = aj[l];
28222205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
2823e4d965acSSatish Balay         }
2824e4d965acSSatish Balay       }
2825e4d965acSSatish Balay     }
282670b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
2827e4d965acSSatish Balay   }
282894bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
2829606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
28303a40ed3dSBarry Smith   PetscFunctionReturn(0);
28314dcbc457SBarry Smith }
283217ab2063SBarry Smith 
28330513a670SBarry Smith /* -------------------------------------------------------------- */
2834dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
28350513a670SBarry Smith {
28360513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
28376849ba73SBarry Smith   PetscErrorCode ierr;
28383b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
28395d0c19d7SBarry Smith   const PetscInt *row,*col;
28405d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
284156cd22aeSBarry Smith   IS             icolp,irowp;
28420298fd71SBarry Smith   PetscInt       *cwork = NULL;
28430298fd71SBarry Smith   PetscScalar    *vwork = NULL;
28440513a670SBarry Smith 
28453a40ed3dSBarry Smith   PetscFunctionBegin;
28464c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
284756cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
28484c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
284956cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
28500513a670SBarry Smith 
28510513a670SBarry Smith   /* determine lengths of permuted rows */
2852854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
28532205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
2854ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
2855f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
285633d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
28577adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2858ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
2859606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
28600513a670SBarry Smith 
2861785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
28620513a670SBarry Smith   for (i=0; i<m; i++) {
286332ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
28642205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
2865cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
286632ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
28670513a670SBarry Smith   }
2868606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
28692205254eSKarl Rupp 
28703c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
28712205254eSKarl Rupp 
28729fe5e383SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2873b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr);
28749fe5e383SStefano Zampini #endif
28750513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28760513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
287756cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
287856cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
28796bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
28806bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
28816768869dSprj-   if (rowp == colp) {
28826768869dSprj-     if (A->symmetric) {
28836768869dSprj-       ierr = MatSetOption(*B,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
28846768869dSprj-     }
28856768869dSprj-     if (A->hermitian) {
28866768869dSprj-       ierr = MatSetOption(*B,MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr);
28876768869dSprj-     }
28886768869dSprj-   }
28893a40ed3dSBarry Smith   PetscFunctionReturn(0);
28900513a670SBarry Smith }
28910513a670SBarry Smith 
2892dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
2893cb5b572fSBarry Smith {
2894dfbe8321SBarry Smith   PetscErrorCode ierr;
2895cb5b572fSBarry Smith 
2896cb5b572fSBarry Smith   PetscFunctionBegin;
289733f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
289833f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
2899be6bf707SBarry Smith     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2900be6bf707SBarry Smith     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
2901be6bf707SBarry Smith 
29024d805d7cSStefano 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]);
2903580bdb30SBarry Smith     ierr = PetscArraycpy(b->a,a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
2904cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
2905cb5b572fSBarry Smith   } else {
2906cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
2907cb5b572fSBarry Smith   }
2908cb5b572fSBarry Smith   PetscFunctionReturn(0);
2909cb5b572fSBarry Smith }
2910cb5b572fSBarry Smith 
29114994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
2912273d9f13SBarry Smith {
2913dfbe8321SBarry Smith   PetscErrorCode ierr;
2914273d9f13SBarry Smith 
2915273d9f13SBarry Smith   PetscFunctionBegin;
2916ab93d7beSBarry Smith   ierr =  MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);CHKERRQ(ierr);
2917273d9f13SBarry Smith   PetscFunctionReturn(0);
2918273d9f13SBarry Smith }
2919273d9f13SBarry Smith 
2920f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
29216c0721eeSBarry Smith {
29226c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
29236e111a19SKarl Rupp 
29246c0721eeSBarry Smith   PetscFunctionBegin;
29256c0721eeSBarry Smith   *array = a->a;
29266c0721eeSBarry Smith   PetscFunctionReturn(0);
29276c0721eeSBarry Smith }
29286c0721eeSBarry Smith 
2929f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
29306c0721eeSBarry Smith {
29316c0721eeSBarry Smith   PetscFunctionBegin;
2932f38c1e66SStefano Zampini   *array = NULL;
29336c0721eeSBarry Smith   PetscFunctionReturn(0);
29346c0721eeSBarry Smith }
2935273d9f13SBarry Smith 
29368229c054SShri Abhyankar /*
29378229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
29388229c054SShri Abhyankar    have different nonzero structure.
29398229c054SShri Abhyankar */
2940b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
2941ec7775f6SShri Abhyankar {
2942b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
2943ec7775f6SShri Abhyankar 
2944ec7775f6SShri Abhyankar   PetscFunctionBegin;
2945ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
2946ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
2947b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
2948b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
2949b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
29508af7cee1SJed Brown     nnz[i] = 0;
29518af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
2952b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
2953b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
29548af7cee1SJed Brown       nnz[i]++;
29558af7cee1SJed Brown     }
29568af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
2957ec7775f6SShri Abhyankar   }
2958ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
2959ec7775f6SShri Abhyankar }
2960ec7775f6SShri Abhyankar 
2961b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
2962b264fe52SHong Zhang {
2963b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
2964b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
2965b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
2966b264fe52SHong Zhang   PetscErrorCode ierr;
2967b264fe52SHong Zhang 
2968b264fe52SHong Zhang   PetscFunctionBegin;
2969b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
2970b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
2971b264fe52SHong Zhang   PetscFunctionReturn(0);
2972b264fe52SHong Zhang }
2973b264fe52SHong Zhang 
2974f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
2975ac90fabeSBarry Smith {
2976dfbe8321SBarry Smith   PetscErrorCode ierr;
2977ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
2978c5df96a5SBarry Smith   PetscBLASInt   one=1,bnz;
2979ac90fabeSBarry Smith 
2980ac90fabeSBarry Smith   PetscFunctionBegin;
2981c5df96a5SBarry Smith   ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
2982ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
2983f4df32b1SMatthew Knepley     PetscScalar alpha = a;
29848b83055fSJed Brown     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one));
2985acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
2986a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
2987e2cf4d64SStefano Zampini     /* the MatAXPY_Basic* subroutines calls MatAssembly, so the matrix on the GPU
2988e2cf4d64SStefano Zampini        will be updated */
2989e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2990c70f7ee4SJunchao Zhang     if (Y->offloadmask != PETSC_OFFLOAD_UNALLOCATED) {
2991c70f7ee4SJunchao Zhang       Y->offloadmask = PETSC_OFFLOAD_CPU;
2992e2cf4d64SStefano Zampini     }
2993e2cf4d64SStefano Zampini #endif
2994ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2995ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
2996ac90fabeSBarry Smith   } else {
29978229c054SShri Abhyankar     Mat      B;
29988229c054SShri Abhyankar     PetscInt *nnz;
2999785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3000ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3001bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
30024aa94f47SShri Abhyankar     ierr = MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);CHKERRQ(ierr);
300333d57670SJed Brown     ierr = MatSetBlockSizesFromMats(B,Y,Y);CHKERRQ(ierr);
3004176df525SBarry Smith     ierr = MatSetType(B,(MatType) ((PetscObject)Y)->type_name);CHKERRQ(ierr);
30058229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3006ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3007ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
300828be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
30098229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3010ac90fabeSBarry Smith   }
3011ac90fabeSBarry Smith   PetscFunctionReturn(0);
3012ac90fabeSBarry Smith }
3013ac90fabeSBarry Smith 
30147087cfbeSBarry Smith PetscErrorCode  MatConjugate_SeqAIJ(Mat mat)
3015354c94deSBarry Smith {
3016354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3017354c94deSBarry Smith   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)mat->data;
3018354c94deSBarry Smith   PetscInt    i,nz;
3019354c94deSBarry Smith   PetscScalar *a;
3020354c94deSBarry Smith 
3021354c94deSBarry Smith   PetscFunctionBegin;
3022354c94deSBarry Smith   nz = aij->nz;
3023354c94deSBarry Smith   a  = aij->a;
30242205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
3025e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
3026c70f7ee4SJunchao Zhang   if (mat->offloadmask != PETSC_OFFLOAD_UNALLOCATED) mat->offloadmask = PETSC_OFFLOAD_CPU;
3027e2cf4d64SStefano Zampini #endif
3028354c94deSBarry Smith #else
3029354c94deSBarry Smith   PetscFunctionBegin;
3030354c94deSBarry Smith #endif
3031354c94deSBarry Smith   PetscFunctionReturn(0);
3032354c94deSBarry Smith }
3033354c94deSBarry Smith 
3034985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3035e34fafa9SBarry Smith {
3036e34fafa9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3037e34fafa9SBarry Smith   PetscErrorCode ierr;
3038d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3039e34fafa9SBarry Smith   PetscReal      atmp;
3040985db425SBarry Smith   PetscScalar    *x;
3041e34fafa9SBarry Smith   MatScalar      *aa;
3042e34fafa9SBarry Smith 
3043e34fafa9SBarry Smith   PetscFunctionBegin;
3044e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3045e34fafa9SBarry Smith   aa = a->a;
3046e34fafa9SBarry Smith   ai = a->i;
3047e34fafa9SBarry Smith   aj = a->j;
3048e34fafa9SBarry Smith 
3049985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3050e34fafa9SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3051e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3052e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3053e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3054e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
30559189402eSHong Zhang     x[i]  = 0.0;
3056e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3057985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3058985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3059985db425SBarry Smith       aa++; aj++;
3060985db425SBarry Smith     }
3061985db425SBarry Smith   }
3062985db425SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3063985db425SBarry Smith   PetscFunctionReturn(0);
3064985db425SBarry Smith }
3065985db425SBarry Smith 
3066985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3067985db425SBarry Smith {
3068985db425SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3069985db425SBarry Smith   PetscErrorCode ierr;
3070d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3071985db425SBarry Smith   PetscScalar    *x;
3072985db425SBarry Smith   MatScalar      *aa;
3073985db425SBarry Smith 
3074985db425SBarry Smith   PetscFunctionBegin;
3075e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3076985db425SBarry Smith   aa = a->a;
3077985db425SBarry Smith   ai = a->i;
3078985db425SBarry Smith   aj = a->j;
3079985db425SBarry Smith 
3080985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3081985db425SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3082985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3083e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3084985db425SBarry Smith   for (i=0; i<m; i++) {
3085985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3086d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3087985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3088985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3089985db425SBarry Smith       x[i] = 0.0;
3090985db425SBarry Smith       if (idx) {
3091985db425SBarry Smith         idx[i] = 0; /* in case ncols is zero */
3092985db425SBarry Smith         for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */
3093985db425SBarry Smith           if (aj[j] > j) {
3094985db425SBarry Smith             idx[i] = j;
3095985db425SBarry Smith             break;
3096985db425SBarry Smith           }
3097985db425SBarry Smith         }
3098985db425SBarry Smith       }
3099985db425SBarry Smith     }
3100985db425SBarry Smith     for (j=0; j<ncols; j++) {
3101985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3102985db425SBarry Smith       aa++; aj++;
3103985db425SBarry Smith     }
3104985db425SBarry Smith   }
3105985db425SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3106985db425SBarry Smith   PetscFunctionReturn(0);
3107985db425SBarry Smith }
3108985db425SBarry Smith 
3109c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3110c87e5d42SMatthew Knepley {
3111c87e5d42SMatthew Knepley   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3112c87e5d42SMatthew Knepley   PetscErrorCode ierr;
3113c87e5d42SMatthew Knepley   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3114c87e5d42SMatthew Knepley   PetscReal      atmp;
3115c87e5d42SMatthew Knepley   PetscScalar    *x;
3116c87e5d42SMatthew Knepley   MatScalar      *aa;
3117c87e5d42SMatthew Knepley 
3118c87e5d42SMatthew Knepley   PetscFunctionBegin;
3119e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3120c87e5d42SMatthew Knepley   aa = a->a;
3121c87e5d42SMatthew Knepley   ai = a->i;
3122c87e5d42SMatthew Knepley   aj = a->j;
3123c87e5d42SMatthew Knepley 
3124c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3125c87e5d42SMatthew Knepley   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3126c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
312760e0710aSBarry Smith   if (n != A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", A->rmap->n, n);
3128c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3129c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3130289a08f5SMatthew Knepley     if (ncols) {
3131289a08f5SMatthew Knepley       /* Get first nonzero */
3132289a08f5SMatthew Knepley       for (j = 0; j < ncols; j++) {
3133289a08f5SMatthew Knepley         atmp = PetscAbsScalar(aa[j]);
31342205254eSKarl Rupp         if (atmp > 1.0e-12) {
31352205254eSKarl Rupp           x[i] = atmp;
31362205254eSKarl Rupp           if (idx) idx[i] = aj[j];
31372205254eSKarl Rupp           break;
31382205254eSKarl Rupp         }
3139289a08f5SMatthew Knepley       }
314012431cb0SMatthew G Knepley       if (j == ncols) {x[i] = PetscAbsScalar(*aa); if (idx) idx[i] = *aj;}
3141289a08f5SMatthew Knepley     } else {
3142289a08f5SMatthew Knepley       x[i] = 0.0; if (idx) idx[i] = 0;
3143289a08f5SMatthew Knepley     }
3144c87e5d42SMatthew Knepley     for (j = 0; j < ncols; j++) {
3145c87e5d42SMatthew Knepley       atmp = PetscAbsScalar(*aa);
3146289a08f5SMatthew Knepley       if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3147c87e5d42SMatthew Knepley       aa++; aj++;
3148c87e5d42SMatthew Knepley     }
3149c87e5d42SMatthew Knepley   }
3150c87e5d42SMatthew Knepley   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3151c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3152c87e5d42SMatthew Knepley }
3153c87e5d42SMatthew Knepley 
3154985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3155985db425SBarry Smith {
3156985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3157985db425SBarry Smith   PetscErrorCode  ierr;
3158d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3159d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3160985db425SBarry Smith   PetscScalar     *x;
3161d9ca1df4SBarry Smith   const MatScalar *aa;
3162985db425SBarry Smith 
3163985db425SBarry Smith   PetscFunctionBegin;
3164e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3165985db425SBarry Smith   aa = a->a;
3166985db425SBarry Smith   ai = a->i;
3167985db425SBarry Smith   aj = a->j;
3168985db425SBarry Smith 
3169985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3170985db425SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3171985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3172e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3173985db425SBarry Smith   for (i=0; i<m; i++) {
3174985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3175d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3176985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3177985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3178985db425SBarry Smith       x[i] = 0.0;
3179985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3180985db425SBarry Smith         idx[i] = 0; /* in case ncols is zero */
3181985db425SBarry Smith         for (j=0; j<ncols; j++) {
3182985db425SBarry Smith           if (aj[j] > j) {
3183985db425SBarry Smith             idx[i] = j;
3184985db425SBarry Smith             break;
3185985db425SBarry Smith           }
3186985db425SBarry Smith         }
3187985db425SBarry Smith       }
3188985db425SBarry Smith     }
3189985db425SBarry Smith     for (j=0; j<ncols; j++) {
3190985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3191985db425SBarry Smith       aa++; aj++;
3192e34fafa9SBarry Smith     }
3193e34fafa9SBarry Smith   }
3194e34fafa9SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3195e34fafa9SBarry Smith   PetscFunctionReturn(0);
3196e34fafa9SBarry Smith }
3197bbead8a2SBarry Smith 
3198713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3199bbead8a2SBarry Smith {
3200bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3201bbead8a2SBarry Smith   PetscErrorCode  ierr;
320233d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3203bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
32040da83c2eSBarry Smith   const PetscReal shift = 0.0;
32051a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3206bbead8a2SBarry Smith 
3207bbead8a2SBarry Smith   PetscFunctionBegin;
3208a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
32094a0d0026SBarry Smith   if (a->ibdiagvalid) {
32104a0d0026SBarry Smith     if (values) *values = a->ibdiag;
32114a0d0026SBarry Smith     PetscFunctionReturn(0);
32124a0d0026SBarry Smith   }
3213bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3214bbead8a2SBarry Smith   if (!a->ibdiag) {
3215785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
32163bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3217bbead8a2SBarry Smith   }
3218bbead8a2SBarry Smith   diag = a->ibdiag;
3219bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3220bbead8a2SBarry Smith   /* factor and invert each block */
3221bbead8a2SBarry Smith   switch (bs) {
3222bbead8a2SBarry Smith   case 1:
3223bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3224bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3225ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3226ec1892c8SHong Zhang         if (allowzeropivot) {
32277b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32287b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
32297b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
32307b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
32317b6c816cSBarry 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);
3232ec1892c8SHong Zhang       }
3233bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3234bbead8a2SBarry Smith     }
3235bbead8a2SBarry Smith     break;
3236bbead8a2SBarry Smith   case 2:
3237bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3238bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3239bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3240a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32417b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
324296b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3243bbead8a2SBarry Smith       diag += 4;
3244bbead8a2SBarry Smith     }
3245bbead8a2SBarry Smith     break;
3246bbead8a2SBarry Smith   case 3:
3247bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3248bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3249bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3250a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32517b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
325296b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3253bbead8a2SBarry Smith       diag += 9;
3254bbead8a2SBarry Smith     }
3255bbead8a2SBarry Smith     break;
3256bbead8a2SBarry Smith   case 4:
3257bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3258bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3259bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3260a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32617b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
326296b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3263bbead8a2SBarry Smith       diag += 16;
3264bbead8a2SBarry Smith     }
3265bbead8a2SBarry Smith     break;
3266bbead8a2SBarry Smith   case 5:
3267bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3268bbead8a2SBarry 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;
3269bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3270a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32717b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
327296b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3273bbead8a2SBarry Smith       diag += 25;
3274bbead8a2SBarry Smith     }
3275bbead8a2SBarry Smith     break;
3276bbead8a2SBarry Smith   case 6:
3277bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3278bbead8a2SBarry 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;
3279bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3280a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32817b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
328296b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3283bbead8a2SBarry Smith       diag += 36;
3284bbead8a2SBarry Smith     }
3285bbead8a2SBarry Smith     break;
3286bbead8a2SBarry Smith   case 7:
3287bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3288bbead8a2SBarry 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;
3289bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3290a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32917b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
329296b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3293bbead8a2SBarry Smith       diag += 49;
3294bbead8a2SBarry Smith     }
3295bbead8a2SBarry Smith     break;
3296bbead8a2SBarry Smith   default:
3297dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3298bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3299bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3300bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3301bbead8a2SBarry Smith       }
3302bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
33035f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
33047b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
330596b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3306bbead8a2SBarry Smith       diag += bs2;
3307bbead8a2SBarry Smith     }
3308bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3309bbead8a2SBarry Smith   }
3310bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3311bbead8a2SBarry Smith   PetscFunctionReturn(0);
3312bbead8a2SBarry Smith }
3313bbead8a2SBarry Smith 
331473a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
331573a71a0fSBarry Smith {
331673a71a0fSBarry Smith   PetscErrorCode ierr;
331773a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
331873a71a0fSBarry Smith   PetscScalar    a;
331973a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
332073a71a0fSBarry Smith 
332173a71a0fSBarry Smith   PetscFunctionBegin;
332273a71a0fSBarry Smith   if (!x->assembled) {
332373a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
332473a71a0fSBarry Smith     for (i=0; i<m; i++) {
332573a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
332673a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
332773a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
332873a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
332973a71a0fSBarry Smith       }
333073a71a0fSBarry Smith     }
3331e2ce353bSJunchao Zhang   } else {
3332e2ce353bSJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);}
3333e2ce353bSJunchao Zhang   }
333473a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
333573a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
333673a71a0fSBarry Smith   PetscFunctionReturn(0);
333773a71a0fSBarry Smith }
333873a71a0fSBarry Smith 
3339679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3340679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3341679944adSJunchao Zhang {
3342679944adSJunchao Zhang   PetscErrorCode ierr;
3343679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3344679944adSJunchao Zhang   PetscScalar    a;
3345679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3346679944adSJunchao Zhang 
3347679944adSJunchao Zhang   PetscFunctionBegin;
3348679944adSJunchao Zhang   nskip = high - low;
3349679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3350679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3351679944adSJunchao Zhang   for (i=0; i<m; i++) {
3352679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3353679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3354679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3355679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3356679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3357679944adSJunchao Zhang     }
3358e2ce353bSJunchao Zhang   }
3359679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3360679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3361679944adSJunchao Zhang   PetscFunctionReturn(0);
3362679944adSJunchao Zhang }
3363679944adSJunchao Zhang 
3364679944adSJunchao Zhang 
3365682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
33660a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3367cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3368cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3369cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
337097304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
33717c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
33727c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3373db4efbfdSBarry Smith                                         0,
3374db4efbfdSBarry Smith                                         0,
3375db4efbfdSBarry Smith                                         0,
3376db4efbfdSBarry Smith                                 /* 10*/ 0,
3377cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3378cb5b572fSBarry Smith                                         0,
337941f059aeSBarry Smith                                         MatSOR_SeqAIJ,
338091e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
338197304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3382cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3383cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3384cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3385cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
338697304618SKris Buschelman                                 /* 20*/ 0,
3387cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3388cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3389cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3390d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3391db4efbfdSBarry Smith                                         0,
3392db4efbfdSBarry Smith                                         0,
3393db4efbfdSBarry Smith                                         0,
3394db4efbfdSBarry Smith                                         0,
33954994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3396db4efbfdSBarry Smith                                         0,
3397db4efbfdSBarry Smith                                         0,
33988c778c55SBarry Smith                                         0,
33998c778c55SBarry Smith                                         0,
3400d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3401cb5b572fSBarry Smith                                         0,
3402cb5b572fSBarry Smith                                         0,
3403cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3404cb5b572fSBarry Smith                                         0,
3405d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
34067dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3407cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3408cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3409cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3410d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3411cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
34127d68702bSBarry Smith                                         MatShift_SeqAIJ,
341379299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
34146e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
341573a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
34163b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
34173b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
34183b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3419a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
342093dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3421b9617806SBarry Smith                                         0,
34220513a670SBarry Smith                                         0,
3423cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3424cda55fadSBarry Smith                                         0,
3425d519adbfSMatthew Knepley                                 /* 59*/ 0,
3426b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3427b9b97703SBarry Smith                                         MatView_SeqAIJ,
3428357abbc8SBarry Smith                                         0,
3429321b30b9SSatish Balay                                         MatMatMatMult_SeqAIJ_SeqAIJ_SeqAIJ,
3430321b30b9SSatish Balay                                 /* 64*/ MatMatMatMultSymbolic_SeqAIJ_SeqAIJ_SeqAIJ,
3431321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3432ee4f033dSBarry Smith                                         0,
3433ee4f033dSBarry Smith                                         0,
3434ee4f033dSBarry Smith                                         0,
3435d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3436c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3437ee4f033dSBarry Smith                                         0,
3438dcf5cc72SBarry Smith                                         0,
34392c93a97aSBarry Smith                                         0,
34402c93a97aSBarry Smith                                 /* 74*/ 0,
34413acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
344297304618SKris Buschelman                                         0,
344397304618SKris Buschelman                                         0,
344497304618SKris Buschelman                                         0,
34456ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
344697304618SKris Buschelman                                         0,
344797304618SKris Buschelman                                         0,
344897304618SKris Buschelman                                         0,
3449bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3450d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
34511cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
34526284ec50SHong Zhang                                         0,
34536284ec50SHong Zhang                                         0,
3454bc011b1eSHong Zhang                                         0,
3455d519adbfSMatthew Knepley                                 /* 89*/ MatMatMult_SeqAIJ_SeqAIJ,
345626be0446SHong Zhang                                         MatMatMultSymbolic_SeqAIJ_SeqAIJ,
345726be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
345865e8a0caSHong Zhang                                         MatPtAP_SeqAIJ_SeqAIJ,
34598fa4b5a6SHong Zhang                                         MatPtAPSymbolic_SeqAIJ_SeqAIJ_SparseAxpy,
34608fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
34616fc122caSHong Zhang                                         MatMatTransposeMult_SeqAIJ_SeqAIJ,
34626fc122caSHong Zhang                                         MatMatTransposeMultSymbolic_SeqAIJ_SeqAIJ,
34636fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
34642121bac1SHong Zhang                                         0,
34652121bac1SHong Zhang                                 /* 99*/ 0,
3466609c6c4dSKris Buschelman                                         0,
3467609c6c4dSKris Buschelman                                         0,
346887d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
346987d4246cSBarry Smith                                         0,
3470d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
347199cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3472f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3473f5edf698SHong Zhang                                         0,
34742bebee5dSHong Zhang                                         0,
3475cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3476985db425SBarry Smith                                         0,
34772af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
34782af78befSBarry Smith                                         0,
3479599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3480d519adbfSMatthew Knepley                                 /*114*/ 0,
3481599ef60dSHong Zhang                                         0,
34823c2a7987SHong Zhang                                         0,
3483fe97e370SBarry Smith                                         0,
3484fbdbba38SShri Abhyankar                                         0,
3485fbdbba38SShri Abhyankar                                 /*119*/ 0,
3486fbdbba38SShri Abhyankar                                         0,
3487fbdbba38SShri Abhyankar                                         0,
348882d44351SHong Zhang                                         0,
3489b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
34900716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3491bbead8a2SBarry Smith                                         MatGetColumnNorms_SeqAIJ,
349237868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
34930da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
349437868618SMatthew G Knepley                                         0,
34955df89d91SHong Zhang                                 /*129*/ 0,
349675648e8dSHong Zhang                                         MatTransposeMatMult_SeqAIJ_SeqAIJ,
349775648e8dSHong Zhang                                         MatTransposeMatMultSymbolic_SeqAIJ_SeqAIJ,
349875648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3499b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3500b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
35012b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
35022b8ad9a3SHong Zhang                                         MatRARt_SeqAIJ_SeqAIJ,
35032b8ad9a3SHong Zhang                                         MatRARtSymbolic_SeqAIJ_SeqAIJ,
35043964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
35053964eb88SJed Brown                                  /*139*/0,
3506f9426fe0SMark Adams                                         0,
35071919a2e2SJed Brown                                         0,
35083a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
35099c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
35102d033e1fSHong Zhang                                  /*144*/MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
35112d033e1fSHong Zhang                                         MatDestroySubMatrices_SeqAIJ
35129e29f15eSvictorle };
351317ab2063SBarry Smith 
35147087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3515bef8e0ddSBarry Smith {
3516bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
351797f1f81fSBarry Smith   PetscInt   i,nz,n;
3518bef8e0ddSBarry Smith 
3519bef8e0ddSBarry Smith   PetscFunctionBegin;
3520bef8e0ddSBarry Smith   nz = aij->maxnz;
3521d0f46423SBarry Smith   n  = mat->rmap->n;
3522bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3523bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3524bef8e0ddSBarry Smith   }
3525bef8e0ddSBarry Smith   aij->nz = nz;
3526bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3527bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3528bef8e0ddSBarry Smith   }
3529bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3530bef8e0ddSBarry Smith }
3531bef8e0ddSBarry Smith 
3532a3bb6f32SFande Kong /*
3533e8b528d9SFande Kong  * When a sparse matrix has many zero columns, we should compact them out to save the space
3534a3bb6f32SFande Kong  * This happens in MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3535a3bb6f32SFande Kong  * */
3536a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3537a3bb6f32SFande Kong {
3538a3bb6f32SFande Kong   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
3539a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3540a3bb6f32SFande Kong   PetscTablePosition tpos;
3541a3bb6f32SFande Kong   PetscInt           gid,lid,i,j,ncols,ec;
3542a3bb6f32SFande Kong   PetscInt           *garray;
3543a3bb6f32SFande Kong   PetscErrorCode  ierr;
3544a3bb6f32SFande Kong 
3545a3bb6f32SFande Kong   PetscFunctionBegin;
3546a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3547a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3548a3bb6f32SFande Kong   /* use a table */
3549a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3550a3bb6f32SFande Kong   ec = 0;
3551a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3552a3bb6f32SFande Kong     ncols = aij->i[i+1] - aij->i[i];
3553a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3554a3bb6f32SFande Kong       PetscInt data,gid1 = aij->j[aij->i[i] + j] + 1;
3555a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3556a3bb6f32SFande Kong       if (!data) {
3557a3bb6f32SFande Kong         /* one based table */
3558a3bb6f32SFande Kong         ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3559a3bb6f32SFande Kong       }
3560a3bb6f32SFande Kong     }
3561a3bb6f32SFande Kong   }
3562a3bb6f32SFande Kong   /* form array of columns we need */
3563a3bb6f32SFande Kong   ierr = PetscMalloc1(ec+1,&garray);CHKERRQ(ierr);
3564a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3565a3bb6f32SFande Kong   while (tpos) {
3566a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3567a3bb6f32SFande Kong     gid--;
3568a3bb6f32SFande Kong     lid--;
3569a3bb6f32SFande Kong     garray[lid] = gid;
3570a3bb6f32SFande Kong   }
3571a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3572a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3573a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3574a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3575a3bb6f32SFande Kong   }
3576a3bb6f32SFande Kong   /* compact out the extra columns in B */
3577a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3578a3bb6f32SFande Kong 	ncols = aij->i[i+1] - aij->i[i];
3579a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3580a3bb6f32SFande Kong       PetscInt gid1 = aij->j[aij->i[i] + j] + 1;
3581a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3582a3bb6f32SFande Kong       lid--;
3583a3bb6f32SFande Kong       aij->j[aij->i[i] + j] = lid;
3584a3bb6f32SFande Kong     }
3585a3bb6f32SFande Kong   }
3586ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3587ca5434daSLawrence Mitchell   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3588a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
3589a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3590a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3591a3bb6f32SFande Kong   PetscFunctionReturn(0);
3592a3bb6f32SFande Kong }
3593a3bb6f32SFande Kong 
3594bef8e0ddSBarry Smith /*@
3595bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3596bef8e0ddSBarry Smith        in the matrix.
3597bef8e0ddSBarry Smith 
3598bef8e0ddSBarry Smith   Input Parameters:
3599bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3600bef8e0ddSBarry Smith -  indices - the column indices
3601bef8e0ddSBarry Smith 
360215091d37SBarry Smith   Level: advanced
360315091d37SBarry Smith 
3604bef8e0ddSBarry Smith   Notes:
3605bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3606bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3607bef8e0ddSBarry Smith   of the MatSetValues() operation.
3608bef8e0ddSBarry Smith 
3609bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3610d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3611bef8e0ddSBarry Smith 
3612bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3613bef8e0ddSBarry Smith 
3614b9617806SBarry Smith     The indices should start with zero, not one.
3615b9617806SBarry Smith 
3616bef8e0ddSBarry Smith @*/
36177087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3618bef8e0ddSBarry Smith {
36194ac538c5SBarry Smith   PetscErrorCode ierr;
3620bef8e0ddSBarry Smith 
3621bef8e0ddSBarry Smith   PetscFunctionBegin;
36220700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
36234482741eSBarry Smith   PetscValidPointer(indices,2);
36244ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3625bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3626bef8e0ddSBarry Smith }
3627bef8e0ddSBarry Smith 
3628be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3629be6bf707SBarry Smith 
36307087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3631be6bf707SBarry Smith {
3632be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
36336849ba73SBarry Smith   PetscErrorCode ierr;
3634d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3635be6bf707SBarry Smith 
3636be6bf707SBarry Smith   PetscFunctionBegin;
3637169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3638be6bf707SBarry Smith 
3639be6bf707SBarry Smith   /* allocate space for values if not already there */
3640be6bf707SBarry Smith   if (!aij->saved_values) {
3641854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
36423bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3643be6bf707SBarry Smith   }
3644be6bf707SBarry Smith 
3645be6bf707SBarry Smith   /* copy values over */
3646580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3647be6bf707SBarry Smith   PetscFunctionReturn(0);
3648be6bf707SBarry Smith }
3649be6bf707SBarry Smith 
3650be6bf707SBarry Smith /*@
3651be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3652be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3653be6bf707SBarry Smith        nonlinear portion.
3654be6bf707SBarry Smith 
3655be6bf707SBarry Smith    Collect on Mat
3656be6bf707SBarry Smith 
3657be6bf707SBarry Smith   Input Parameters:
36580e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3659be6bf707SBarry Smith 
366015091d37SBarry Smith   Level: advanced
366115091d37SBarry Smith 
3662be6bf707SBarry Smith   Common Usage, with SNESSolve():
3663be6bf707SBarry Smith $    Create Jacobian matrix
3664be6bf707SBarry Smith $    Set linear terms into matrix
3665be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3666be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3667be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3668512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3669be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3670be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3671be6bf707SBarry Smith $    In your Jacobian routine
3672be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3673be6bf707SBarry Smith $      Set nonlinear terms in matrix
3674be6bf707SBarry Smith 
3675be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3676be6bf707SBarry Smith $    // build linear portion of Jacobian
3677512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3678be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3679be6bf707SBarry Smith $    loop over nonlinear iterations
3680be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3681be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3682be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3683be6bf707SBarry Smith $       Solve linear system with Jacobian
3684be6bf707SBarry Smith $    endloop
3685be6bf707SBarry Smith 
3686be6bf707SBarry Smith   Notes:
3687be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3688512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3689be6bf707SBarry Smith     calling this routine.
3690be6bf707SBarry Smith 
36910c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
36920c468ba9SBarry Smith     and does not allocated additional space.
36930c468ba9SBarry Smith 
3694be6bf707SBarry Smith .seealso: MatRetrieveValues()
3695be6bf707SBarry Smith 
3696be6bf707SBarry Smith @*/
36977087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3698be6bf707SBarry Smith {
36994ac538c5SBarry Smith   PetscErrorCode ierr;
3700be6bf707SBarry Smith 
3701be6bf707SBarry Smith   PetscFunctionBegin;
37020700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3703e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3704e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
37054ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3706be6bf707SBarry Smith   PetscFunctionReturn(0);
3707be6bf707SBarry Smith }
3708be6bf707SBarry Smith 
37097087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3710be6bf707SBarry Smith {
3711be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
37126849ba73SBarry Smith   PetscErrorCode ierr;
3713d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3714be6bf707SBarry Smith 
3715be6bf707SBarry Smith   PetscFunctionBegin;
3716169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3717f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3718be6bf707SBarry Smith   /* copy values over */
3719580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3720be6bf707SBarry Smith   PetscFunctionReturn(0);
3721be6bf707SBarry Smith }
3722be6bf707SBarry Smith 
3723be6bf707SBarry Smith /*@
3724be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3725be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3726be6bf707SBarry Smith        nonlinear portion.
3727be6bf707SBarry Smith 
3728be6bf707SBarry Smith    Collect on Mat
3729be6bf707SBarry Smith 
3730be6bf707SBarry Smith   Input Parameters:
3731386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3732be6bf707SBarry Smith 
373315091d37SBarry Smith   Level: advanced
373415091d37SBarry Smith 
3735be6bf707SBarry Smith .seealso: MatStoreValues()
3736be6bf707SBarry Smith 
3737be6bf707SBarry Smith @*/
37387087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3739be6bf707SBarry Smith {
37404ac538c5SBarry Smith   PetscErrorCode ierr;
3741be6bf707SBarry Smith 
3742be6bf707SBarry Smith   PetscFunctionBegin;
37430700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3744e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3745e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
37464ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3747be6bf707SBarry Smith   PetscFunctionReturn(0);
3748be6bf707SBarry Smith }
3749be6bf707SBarry Smith 
3750f83d6046SBarry Smith 
3751be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
375217ab2063SBarry Smith /*@C
3753682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
37540d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
37556e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
375651c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
37572bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
375817ab2063SBarry Smith 
3759d083f849SBarry Smith    Collective
3760db81eaa0SLois Curfman McInnes 
376117ab2063SBarry Smith    Input Parameters:
3762db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
376317ab2063SBarry Smith .  m - number of rows
376417ab2063SBarry Smith .  n - number of columns
376517ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
376651c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
37670298fd71SBarry Smith          (possibly different for each row) or NULL
376817ab2063SBarry Smith 
376917ab2063SBarry Smith    Output Parameter:
3770416022c9SBarry Smith .  A - the matrix
377117ab2063SBarry Smith 
3772175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3773f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3774175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3775175b88e8SBarry Smith 
3776b259b22eSLois Curfman McInnes    Notes:
377749a6f317SBarry Smith    If nnz is given then nz is ignored
377849a6f317SBarry Smith 
377917ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
378017ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
37810002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
378244cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
378317ab2063SBarry Smith 
378417ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
37850298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
37863d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
37876da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
378817ab2063SBarry Smith 
3789682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
37904fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3791682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
37926c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
37936c7ebb05SLois Curfman McInnes 
37946c7ebb05SLois Curfman McInnes    Options Database Keys:
3795698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
37969db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
379717ab2063SBarry Smith 
3798027ccd11SLois Curfman McInnes    Level: intermediate
3799027ccd11SLois Curfman McInnes 
380069b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
380136db0b34SBarry Smith 
380217ab2063SBarry Smith @*/
38037087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
380417ab2063SBarry Smith {
3805dfbe8321SBarry Smith   PetscErrorCode ierr;
38066945ee14SBarry Smith 
38073a40ed3dSBarry Smith   PetscFunctionBegin;
3808f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3809117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3810c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
3811d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
3812273d9f13SBarry Smith   PetscFunctionReturn(0);
3813273d9f13SBarry Smith }
3814273d9f13SBarry Smith 
3815273d9f13SBarry Smith /*@C
3816273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3817273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
3818273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
3819273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
3820273d9f13SBarry Smith 
3821d083f849SBarry Smith    Collective
3822273d9f13SBarry Smith 
3823273d9f13SBarry Smith    Input Parameters:
38241c4f3114SJed Brown +  B - The matrix
3825273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
3826273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
38270298fd71SBarry Smith          (possibly different for each row) or NULL
3828273d9f13SBarry Smith 
3829273d9f13SBarry Smith    Notes:
383049a6f317SBarry Smith      If nnz is given then nz is ignored
383149a6f317SBarry Smith 
3832273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
3833273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
3834273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
3835273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
3836273d9f13SBarry Smith 
3837273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
38380298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
3839273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
3840273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
3841273d9f13SBarry Smith 
3842aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
3843aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3844aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
3845aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
3846aa95bbe8SBarry Smith 
3847a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
3848a96a251dSBarry Smith    entries or columns indices
3849a96a251dSBarry Smith 
3850273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
3851273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
3852273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
3853273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
3854273d9f13SBarry Smith 
3855273d9f13SBarry Smith    Options Database Keys:
3856698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
385747b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3858273d9f13SBarry Smith 
3859273d9f13SBarry Smith    Level: intermediate
3860273d9f13SBarry Smith 
386169b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo()
3862273d9f13SBarry Smith 
3863273d9f13SBarry Smith @*/
38647087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
3865273d9f13SBarry Smith {
38664ac538c5SBarry Smith   PetscErrorCode ierr;
3867a23d5eceSKris Buschelman 
3868a23d5eceSKris Buschelman   PetscFunctionBegin;
38696ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
38706ba663aaSJed Brown   PetscValidType(B,1);
38714ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
3872a23d5eceSKris Buschelman   PetscFunctionReturn(0);
3873a23d5eceSKris Buschelman }
3874a23d5eceSKris Buschelman 
38757087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
3876a23d5eceSKris Buschelman {
3877273d9f13SBarry Smith   Mat_SeqAIJ     *b;
38782576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
38796849ba73SBarry Smith   PetscErrorCode ierr;
388097f1f81fSBarry Smith   PetscInt       i;
3881273d9f13SBarry Smith 
3882273d9f13SBarry Smith   PetscFunctionBegin;
38832576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
3884a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
3885c461c341SBarry Smith     skipallocation = PETSC_TRUE;
3886c461c341SBarry Smith     nz             = 0;
3887c461c341SBarry Smith   }
388826283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
388926283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
3890899cda47SBarry Smith 
3891435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
389260e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
3893071fcb05SBarry Smith #if defined(PETSC_USE_DEBUG)
3894b73539f3SBarry Smith   if (nnz) {
3895d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
389660e0710aSBarry 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]);
389760e0710aSBarry 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);
3898b73539f3SBarry Smith     }
3899b73539f3SBarry Smith   }
3900071fcb05SBarry Smith #endif
3901b73539f3SBarry Smith 
3902273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
39032205254eSKarl Rupp 
3904273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
3905273d9f13SBarry Smith 
3906ab93d7beSBarry Smith   if (!skipallocation) {
39072ee49352SLisandro Dalcin     if (!b->imax) {
3908071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
3909071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3910071fcb05SBarry Smith     }
3911071fcb05SBarry Smith     if (!b->ilen) {
3912071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
3913071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
3914071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3915071fcb05SBarry Smith     } else {
3916071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
39172ee49352SLisandro Dalcin     }
3918846b4da1SFande Kong     if (!b->ipre) {
3919846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
3920846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3921846b4da1SFande Kong     }
3922273d9f13SBarry Smith     if (!nnz) {
3923435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
3924c62bd62aSJed Brown       else if (nz < 0) nz = 1;
39255d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
3926d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
3927d0f46423SBarry Smith       nz = nz*B->rmap->n;
3928273d9f13SBarry Smith     } else {
3929c73702f5SBarry Smith       PetscInt64 nz64 = 0;
3930c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
3931c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
3932273d9f13SBarry Smith     }
3933ab93d7beSBarry Smith 
3934273d9f13SBarry Smith     /* allocate the matrix space */
393553dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
39362ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
3937396832f4SHong Zhang     if (B->structure_only) {
39385848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
39395848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
3940396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
3941396832f4SHong Zhang     } else {
3942dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
39433bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
3944396832f4SHong Zhang     }
3945bfeeae90SHong Zhang     b->i[0] = 0;
3946d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
39475da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
39485da197adSKris Buschelman     }
3949396832f4SHong Zhang     if (B->structure_only) {
3950396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
3951396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
3952396832f4SHong Zhang     } else {
3953273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
3954e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
3955396832f4SHong Zhang     }
3956e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
3957c461c341SBarry Smith   } else {
3958e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
3959e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
3960c461c341SBarry Smith   }
3961273d9f13SBarry Smith 
3962846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
3963846b4da1SFande Kong     /* reserve user-requested sparsity */
3964580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
3965846b4da1SFande Kong   }
3966846b4da1SFande Kong 
3967846b4da1SFande Kong 
3968273d9f13SBarry Smith   b->nz               = 0;
3969273d9f13SBarry Smith   b->maxnz            = nz;
3970273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
39712205254eSKarl Rupp   if (realalloc) {
39722205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
39732205254eSKarl Rupp   }
3974cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
3975cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
3976273d9f13SBarry Smith   PetscFunctionReturn(0);
3977273d9f13SBarry Smith }
3978273d9f13SBarry Smith 
3979846b4da1SFande Kong 
3980846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
3981846b4da1SFande Kong {
3982846b4da1SFande Kong   Mat_SeqAIJ     *a;
3983a5bbaf83SFande Kong   PetscInt       i;
3984846b4da1SFande Kong   PetscErrorCode ierr;
3985846b4da1SFande Kong 
3986846b4da1SFande Kong   PetscFunctionBegin;
3987846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
398814d0e64fSAlex Lindsay 
398914d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
399014d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
399114d0e64fSAlex Lindsay 
3992846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
39932c814fdeSFande Kong   /* if no saved info, we error out */
3994fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
39952c814fdeSFande Kong 
3996fb4dc15dSAlex 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");
39972c814fdeSFande Kong 
3998580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
3999580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4000846b4da1SFande Kong   a->i[0] = 0;
4001846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4002846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4003846b4da1SFande Kong   }
4004846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4005846b4da1SFande Kong   a->nz               = 0;
4006846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4007846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4008846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4009846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4010846b4da1SFande Kong   PetscFunctionReturn(0);
4011846b4da1SFande Kong }
4012846b4da1SFande Kong 
401358d36128SBarry Smith /*@
4014a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4015a1661176SMatthew Knepley 
4016a1661176SMatthew Knepley    Input Parameters:
4017a1661176SMatthew Knepley +  B - the matrix
4018a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4019a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4020a1661176SMatthew Knepley -  v - optional values in the matrix
4021a1661176SMatthew Knepley 
4022a1661176SMatthew Knepley    Level: developer
4023a1661176SMatthew Knepley 
402458d36128SBarry Smith    The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
402558d36128SBarry Smith 
4026c1c1d628SHong Zhang .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ
4027a1661176SMatthew Knepley @*/
4028a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4029a1661176SMatthew Knepley {
4030a1661176SMatthew Knepley   PetscErrorCode ierr;
4031a1661176SMatthew Knepley 
4032a1661176SMatthew Knepley   PetscFunctionBegin;
40330700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40346ba663aaSJed Brown   PetscValidType(B,1);
40354ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4036a1661176SMatthew Knepley   PetscFunctionReturn(0);
4037a1661176SMatthew Knepley }
4038a1661176SMatthew Knepley 
40397087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4040a1661176SMatthew Knepley {
4041a1661176SMatthew Knepley   PetscInt       i;
4042a1661176SMatthew Knepley   PetscInt       m,n;
4043a1661176SMatthew Knepley   PetscInt       nz;
4044a1661176SMatthew Knepley   PetscInt       *nnz, nz_max = 0;
4045a1661176SMatthew Knepley   PetscErrorCode ierr;
4046a1661176SMatthew Knepley 
4047a1661176SMatthew Knepley   PetscFunctionBegin;
404865e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
4049779a8d59SSatish Balay 
4050779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4051779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4052779a8d59SSatish Balay 
4053779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4054854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4055a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4056b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
4057a1661176SMatthew Knepley     nz_max = PetscMax(nz_max, nz);
405865e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
4059a1661176SMatthew Knepley     nnz[i] = nz;
4060a1661176SMatthew Knepley   }
4061a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4062a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4063a1661176SMatthew Knepley 
4064a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4065071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4066a1661176SMatthew Knepley   }
4067a1661176SMatthew Knepley 
4068a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4069a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4070a1661176SMatthew Knepley 
40717827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4072a1661176SMatthew Knepley   PetscFunctionReturn(0);
4073a1661176SMatthew Knepley }
4074a1661176SMatthew Knepley 
4075c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4076af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4077170fe5c8SBarry Smith 
4078170fe5c8SBarry Smith /*
4079170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4080170fe5c8SBarry Smith 
4081170fe5c8SBarry Smith                n                       p                          p
4082170fe5c8SBarry Smith         (              )       (              )         (                  )
4083170fe5c8SBarry Smith       m (      A       )  *  n (       B      )   =   m (         C        )
4084170fe5c8SBarry Smith         (              )       (              )         (                  )
4085170fe5c8SBarry Smith 
4086170fe5c8SBarry Smith */
4087170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4088170fe5c8SBarry Smith {
4089170fe5c8SBarry Smith   PetscErrorCode    ierr;
4090170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4091170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4092170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
40931de00fd4SBarry Smith   PetscInt          i,n,m,q,p;
4094170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4095170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4096170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
4097170fe5c8SBarry Smith 
4098170fe5c8SBarry Smith   PetscFunctionBegin;
4099d0f46423SBarry Smith   m    = A->rmap->n;
4100d0f46423SBarry Smith   n    = A->cmap->n;
4101d0f46423SBarry Smith   p    = B->cmap->n;
4102170fe5c8SBarry Smith   a    = sub_a->v;
4103170fe5c8SBarry Smith   b    = sub_b->a;
4104170fe5c8SBarry Smith   c    = sub_c->v;
4105580bdb30SBarry Smith   ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
4106170fe5c8SBarry Smith 
4107170fe5c8SBarry Smith   ii  = sub_b->i;
4108170fe5c8SBarry Smith   idx = sub_b->j;
4109170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4110170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4111170fe5c8SBarry Smith     while (q-->0) {
4112170fe5c8SBarry Smith       c_q = c + m*(*idx);
4113170fe5c8SBarry Smith       a_q = a + m*i;
4114854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4115170fe5c8SBarry Smith       idx++;
4116170fe5c8SBarry Smith       b++;
4117170fe5c8SBarry Smith     }
4118170fe5c8SBarry Smith   }
4119170fe5c8SBarry Smith   PetscFunctionReturn(0);
4120170fe5c8SBarry Smith }
4121170fe5c8SBarry Smith 
4122170fe5c8SBarry Smith PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C)
4123170fe5c8SBarry Smith {
4124170fe5c8SBarry Smith   PetscErrorCode ierr;
4125d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
4126170fe5c8SBarry Smith   Mat            Cmat;
4127170fe5c8SBarry Smith 
4128170fe5c8SBarry Smith   PetscFunctionBegin;
412960e0710aSBarry 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);
4130ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),&Cmat);CHKERRQ(ierr);
4131170fe5c8SBarry Smith   ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr);
413233d57670SJed Brown   ierr = MatSetBlockSizesFromMats(Cmat,A,B);CHKERRQ(ierr);
4133170fe5c8SBarry Smith   ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr);
41340298fd71SBarry Smith   ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr);
4135d73949e8SHong Zhang 
4136d73949e8SHong Zhang   Cmat->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
41372205254eSKarl Rupp 
4138170fe5c8SBarry Smith   *C = Cmat;
4139170fe5c8SBarry Smith   PetscFunctionReturn(0);
4140170fe5c8SBarry Smith }
4141170fe5c8SBarry Smith 
4142170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
4143150d2497SBarry Smith PETSC_INTERN PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
4144170fe5c8SBarry Smith {
4145170fe5c8SBarry Smith   PetscErrorCode ierr;
4146170fe5c8SBarry Smith 
4147170fe5c8SBarry Smith   PetscFunctionBegin;
4148170fe5c8SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
41493ff4c91cSHong Zhang     ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
4150170fe5c8SBarry Smith     ierr = MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);CHKERRQ(ierr);
41513ff4c91cSHong Zhang     ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
4152170fe5c8SBarry Smith   }
41533ff4c91cSHong Zhang   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
4154170fe5c8SBarry Smith   ierr = MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);CHKERRQ(ierr);
41553ff4c91cSHong Zhang   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
4156170fe5c8SBarry Smith   PetscFunctionReturn(0);
4157170fe5c8SBarry Smith }
4158170fe5c8SBarry Smith 
4159170fe5c8SBarry Smith 
41600bad9183SKris Buschelman /*MC
4161fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
41620bad9183SKris Buschelman    based on compressed sparse row format.
41630bad9183SKris Buschelman 
41640bad9183SKris Buschelman    Options Database Keys:
41650bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
41660bad9183SKris Buschelman 
41670bad9183SKris Buschelman    Level: beginner
41680bad9183SKris Buschelman 
41690cd7f59aSBarry Smith    Notes:
41700cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
41710cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
41720cd7f59aSBarry Smith     in the matrix
41730cd7f59aSBarry Smith 
41740cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
41750cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
41760cd7f59aSBarry Smith 
41770cd7f59aSBarry Smith   Developer Notes:
41780cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
41790cd7f59aSBarry Smith 
4180f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
41810bad9183SKris Buschelman M*/
41820bad9183SKris Buschelman 
4183ccd284c7SBarry Smith /*MC
4184ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4185ccd284c7SBarry Smith 
4186ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4187ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
41880cd7f59aSBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4189ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4190ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4191ccd284c7SBarry Smith 
4192ccd284c7SBarry Smith    Options Database Keys:
4193ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4194ccd284c7SBarry Smith 
419595452b02SPatrick Sanan   Developer Notes:
4196ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4197ccd284c7SBarry Smith    enough exist.
4198ccd284c7SBarry Smith 
4199ccd284c7SBarry Smith   Level: beginner
4200ccd284c7SBarry Smith 
4201ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4202ccd284c7SBarry Smith M*/
4203ccd284c7SBarry Smith 
4204ccd284c7SBarry Smith /*MC
4205ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4206ccd284c7SBarry Smith 
4207ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4208ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4209ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4210ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4211ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4212ccd284c7SBarry Smith 
4213ccd284c7SBarry Smith    Options Database Keys:
4214ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4215ccd284c7SBarry Smith 
4216ccd284c7SBarry Smith   Level: beginner
4217ccd284c7SBarry Smith 
4218ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4219ccd284c7SBarry Smith M*/
4220ccd284c7SBarry Smith 
42217906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
42227906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
42237906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
42247906f579SHong Zhang #endif
42257906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
42267906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
42277906f579SHong Zhang PETSC_INTERN PetscErrorCode MatMatMatMult_Transpose_AIJ_AIJ(Mat,Mat,Mat,MatReuse,PetscReal,Mat*);
42287906f579SHong Zhang #endif
42297906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat,MatType,MatReuse,Mat*);
42307906f579SHong Zhang 
4231d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4232c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
423375d48cdbSStefano Zampini PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat,Mat,MatReuse,PetscReal,Mat*);
42347906f579SHong Zhang 
42358c778c55SBarry Smith /*@C
42368f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
42378c778c55SBarry Smith 
42388c778c55SBarry Smith    Not Collective
42398c778c55SBarry Smith 
42408c778c55SBarry Smith    Input Parameter:
4241579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
42428c778c55SBarry Smith 
42438c778c55SBarry Smith    Output Parameter:
42448c778c55SBarry Smith .   array - pointer to the data
42458c778c55SBarry Smith 
42468c778c55SBarry Smith    Level: intermediate
42478c778c55SBarry Smith 
4248774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
42498c778c55SBarry Smith @*/
42508c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
42518c778c55SBarry Smith {
42528c778c55SBarry Smith   PetscErrorCode ierr;
42538c778c55SBarry Smith 
42548c778c55SBarry Smith   PetscFunctionBegin;
42558c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
42568c778c55SBarry Smith   PetscFunctionReturn(0);
42578c778c55SBarry Smith }
42588c778c55SBarry Smith 
425921e72a00SBarry Smith /*@C
42608f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
42618f1ea47aSStefano Zampini 
42628f1ea47aSStefano Zampini    Not Collective
42638f1ea47aSStefano Zampini 
42648f1ea47aSStefano Zampini    Input Parameter:
42658f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
42668f1ea47aSStefano Zampini 
42678f1ea47aSStefano Zampini    Output Parameter:
42688f1ea47aSStefano Zampini .   array - pointer to the data
42698f1ea47aSStefano Zampini 
42708f1ea47aSStefano Zampini    Level: intermediate
42718f1ea47aSStefano Zampini 
42728f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
42738f1ea47aSStefano Zampini @*/
42748f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
42758f1ea47aSStefano Zampini {
42768f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4277c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
42788f1ea47aSStefano Zampini #endif
42798f1ea47aSStefano Zampini   PetscErrorCode ierr;
42808f1ea47aSStefano Zampini 
42818f1ea47aSStefano Zampini   PetscFunctionBegin;
42828f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4283c70f7ee4SJunchao Zhang   oval = A->offloadmask;
42848f1ea47aSStefano Zampini #endif
42858f1ea47aSStefano Zampini   ierr = MatSeqAIJGetArray(A,(PetscScalar**)array);CHKERRQ(ierr);
42868f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4287c70f7ee4SJunchao Zhang   if (oval == PETSC_OFFLOAD_GPU || oval == PETSC_OFFLOAD_BOTH) A->offloadmask = PETSC_OFFLOAD_BOTH;
42888f1ea47aSStefano Zampini #endif
42898f1ea47aSStefano Zampini   PetscFunctionReturn(0);
42908f1ea47aSStefano Zampini }
42918f1ea47aSStefano Zampini 
42928f1ea47aSStefano Zampini /*@C
42938f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
42948f1ea47aSStefano Zampini 
42958f1ea47aSStefano Zampini    Not Collective
42968f1ea47aSStefano Zampini 
42978f1ea47aSStefano Zampini    Input Parameter:
42988f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
42998f1ea47aSStefano Zampini 
43008f1ea47aSStefano Zampini    Output Parameter:
43018f1ea47aSStefano Zampini .   array - pointer to the data
43028f1ea47aSStefano Zampini 
43038f1ea47aSStefano Zampini    Level: intermediate
43048f1ea47aSStefano Zampini 
43058f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
43068f1ea47aSStefano Zampini @*/
43078f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
43088f1ea47aSStefano Zampini {
43098f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4310c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
43118f1ea47aSStefano Zampini #endif
43128f1ea47aSStefano Zampini   PetscErrorCode ierr;
43138f1ea47aSStefano Zampini 
43148f1ea47aSStefano Zampini   PetscFunctionBegin;
43158f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4316c70f7ee4SJunchao Zhang   oval = A->offloadmask;
43178f1ea47aSStefano Zampini #endif
43188f1ea47aSStefano Zampini   ierr = MatSeqAIJRestoreArray(A,(PetscScalar**)array);CHKERRQ(ierr);
43198f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4320c70f7ee4SJunchao Zhang   A->offloadmask = oval;
43218f1ea47aSStefano Zampini #endif
43228f1ea47aSStefano Zampini   PetscFunctionReturn(0);
43238f1ea47aSStefano Zampini }
43248f1ea47aSStefano Zampini 
43258f1ea47aSStefano Zampini /*@C
432621e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
432721e72a00SBarry Smith 
432821e72a00SBarry Smith    Not Collective
432921e72a00SBarry Smith 
433021e72a00SBarry Smith    Input Parameter:
4331579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
433221e72a00SBarry Smith 
433321e72a00SBarry Smith    Output Parameter:
433421e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
433521e72a00SBarry Smith 
433621e72a00SBarry Smith    Level: intermediate
433721e72a00SBarry Smith 
433821e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
433921e72a00SBarry Smith @*/
434021e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
434121e72a00SBarry Smith {
434221e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
434321e72a00SBarry Smith 
434421e72a00SBarry Smith   PetscFunctionBegin;
434521e72a00SBarry Smith   *nz = aij->rmax;
434621e72a00SBarry Smith   PetscFunctionReturn(0);
434721e72a00SBarry Smith }
434821e72a00SBarry Smith 
43498c778c55SBarry Smith /*@C
4350579dbff0SBarry Smith    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
43518c778c55SBarry Smith 
43528c778c55SBarry Smith    Not Collective
43538c778c55SBarry Smith 
43548c778c55SBarry Smith    Input Parameters:
4355a2b725a8SWilliam Gropp +  mat - a MATSEQAIJ matrix
4356a2b725a8SWilliam Gropp -  array - pointer to the data
43578c778c55SBarry Smith 
43588c778c55SBarry Smith    Level: intermediate
43598c778c55SBarry Smith 
4360774cf152SJed Brown .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
43618c778c55SBarry Smith @*/
43628c778c55SBarry Smith PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
43638c778c55SBarry Smith {
43648c778c55SBarry Smith   PetscErrorCode ierr;
43658c778c55SBarry Smith 
43668c778c55SBarry Smith   PetscFunctionBegin;
43678c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
43688c778c55SBarry Smith   PetscFunctionReturn(0);
43698c778c55SBarry Smith }
43708c778c55SBarry Smith 
437134b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
437202fe1965SBarry Smith PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat);
437302fe1965SBarry Smith #endif
437402fe1965SBarry Smith 
43758cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4376273d9f13SBarry Smith {
4377273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4378dfbe8321SBarry Smith   PetscErrorCode ierr;
437938baddfdSBarry Smith   PetscMPIInt    size;
4380273d9f13SBarry Smith 
4381273d9f13SBarry Smith   PetscFunctionBegin;
4382ce94432eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr);
4383e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4384273d9f13SBarry Smith 
4385b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
43862205254eSKarl Rupp 
4387b0a32e0cSBarry Smith   B->data = (void*)b;
43882205254eSKarl Rupp 
4389549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4390071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
43912205254eSKarl Rupp 
4392416022c9SBarry Smith   b->row                = 0;
4393416022c9SBarry Smith   b->col                = 0;
439482bf6240SBarry Smith   b->icol               = 0;
4395b810aeb4SBarry Smith   b->reallocs           = 0;
439636db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4397f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4398416022c9SBarry Smith   b->nonew              = 0;
4399416022c9SBarry Smith   b->diag               = 0;
4400416022c9SBarry Smith   b->solve_work         = 0;
44012a1b7f2aSHong Zhang   B->spptr              = 0;
4402be6bf707SBarry Smith   b->saved_values       = 0;
4403d7f994e1SBarry Smith   b->idiag              = 0;
440471f1c65dSBarry Smith   b->mdiag              = 0;
440571f1c65dSBarry Smith   b->ssor_work          = 0;
440671f1c65dSBarry Smith   b->omega              = 1.0;
440771f1c65dSBarry Smith   b->fshift             = 0.0;
440871f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4409bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4410a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
441117ab2063SBarry Smith 
441235d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4413bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr);
4414bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr);
44158c778c55SBarry Smith 
4416b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4417bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4418bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4419b3866ffcSBarry Smith #endif
442017f1a0eaSHong Zhang 
4421bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4422bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4423bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4424bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4425bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4426bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
44274dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
44289779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
44294a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4430191b95cbSRichard Tran Mills #endif
443134b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
443202fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
443302fe1965SBarry Smith #endif
4434bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4435af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4436af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4437af8000cdSHong Zhang #endif
443863c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
443963c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
44403dad0653Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMatMult_transpose_seqaij_seqaij_C",MatMatMatMult_Transpose_AIJ_AIJ);CHKERRQ(ierr);
444163c07aadSStefano Zampini #endif
4442b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4443d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4444c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4445bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4446bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4447bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4448846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4449bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4450bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
4451bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqdense_seqaij_C",MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr);
4452bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C",MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr);
4453bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C",MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr);
445475d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_is_seqaij_C",MatPtAP_IS_XAIJ);CHKERRQ(ierr);
44554108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
445617667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
44574099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
44583a40ed3dSBarry Smith   PetscFunctionReturn(0);
445917ab2063SBarry Smith }
446017ab2063SBarry Smith 
4461b24902e0SBarry Smith /*
4462b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4463b24902e0SBarry Smith */
4464ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
446517ab2063SBarry Smith {
4466416022c9SBarry Smith   Mat_SeqAIJ     *c,*a = (Mat_SeqAIJ*)A->data;
44676849ba73SBarry Smith   PetscErrorCode ierr;
4468071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
446917ab2063SBarry Smith 
44703a40ed3dSBarry Smith   PetscFunctionBegin;
4471273d9f13SBarry Smith   c = (Mat_SeqAIJ*)C->data;
4472273d9f13SBarry Smith 
4473d5f3da31SBarry Smith   C->factortype = A->factortype;
4474416022c9SBarry Smith   c->row        = 0;
4475416022c9SBarry Smith   c->col        = 0;
447682bf6240SBarry Smith   c->icol       = 0;
44776ad4291fSHong Zhang   c->reallocs   = 0;
447817ab2063SBarry Smith 
44796ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
448017ab2063SBarry Smith 
4481aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4482aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4483eec197d1SBarry Smith 
4484071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4485071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4486071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4487071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
44883bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
448917ab2063SBarry Smith 
449017ab2063SBarry Smith   /* allocate the matrix space */
4491f77e22a1SHong Zhang   if (mallocmatspace) {
4492dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
44933bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
44942205254eSKarl Rupp 
4495f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
44962205254eSKarl Rupp 
4497580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
449817ab2063SBarry Smith     if (m > 0) {
4499580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4500be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
4501580bdb30SBarry Smith         ierr = PetscArraycpy(c->a,a->a,a->i[m]);CHKERRQ(ierr);
4502be6bf707SBarry Smith       } else {
4503580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
450417ab2063SBarry Smith       }
450508480c60SBarry Smith     }
4506f77e22a1SHong Zhang   }
450717ab2063SBarry Smith 
45086ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4509416022c9SBarry Smith   c->roworiented       = a->roworiented;
4510416022c9SBarry Smith   c->nonew             = a->nonew;
4511416022c9SBarry Smith   if (a->diag) {
4512854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4513071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
45143bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4515071fcb05SBarry Smith   } else c->diag = NULL;
45162205254eSKarl Rupp 
45176ad4291fSHong Zhang   c->solve_work         = 0;
45186ad4291fSHong Zhang   c->saved_values       = 0;
45196ad4291fSHong Zhang   c->idiag              = 0;
452071f1c65dSBarry Smith   c->ssor_work          = 0;
4521a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4522e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4523e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
45246ad4291fSHong Zhang 
4525893ad86cSHong Zhang   c->rmax         = a->rmax;
4526416022c9SBarry Smith   c->nz           = a->nz;
45278ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4528273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4529754ec7b1SSatish Balay 
45306ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
45316ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4532cd6b891eSBarry Smith   if (a->compressedrow.use) {
45336ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4534dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4535580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4536580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
453727ea64f8SHong Zhang   } else {
453827ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
45390298fd71SBarry Smith     c->compressedrow.i      = NULL;
45400298fd71SBarry Smith     c->compressedrow.rindex = NULL;
45416ad4291fSHong Zhang   }
4542ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4543e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
45444846f1f5SKris Buschelman 
45452205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4546140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
45473a40ed3dSBarry Smith   PetscFunctionReturn(0);
454817ab2063SBarry Smith }
454917ab2063SBarry Smith 
4550b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4551b24902e0SBarry Smith {
4552b24902e0SBarry Smith   PetscErrorCode ierr;
4553b24902e0SBarry Smith 
4554b24902e0SBarry Smith   PetscFunctionBegin;
4555ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
45564b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4557cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
455833d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4559cfd3f464SBarry Smith   }
4560a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4561f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4562b24902e0SBarry Smith   PetscFunctionReturn(0);
4563b24902e0SBarry Smith }
4564b24902e0SBarry Smith 
4565112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4566fbdbba38SShri Abhyankar {
456752f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
456852f91c60SVaclav Hapla   PetscErrorCode ierr;
456952f91c60SVaclav Hapla 
457052f91c60SVaclav Hapla   PetscFunctionBegin;
457152f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
457252f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4573c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4574c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
457552f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
457652f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
457752f91c60SVaclav Hapla   if (isbinary) {
457852f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
457952f91c60SVaclav Hapla   } else if (ishdf5) {
458052f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
458152f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
458252f91c60SVaclav Hapla #else
458352f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
458452f91c60SVaclav Hapla #endif
458552f91c60SVaclav Hapla   } else {
458652f91c60SVaclav 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);
458752f91c60SVaclav Hapla   }
458852f91c60SVaclav Hapla   PetscFunctionReturn(0);
458952f91c60SVaclav Hapla }
459052f91c60SVaclav Hapla 
4591*3ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
459252f91c60SVaclav Hapla {
4593*3ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
4594fbdbba38SShri Abhyankar   PetscErrorCode ierr;
4595*3ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4596fbdbba38SShri Abhyankar 
4597fbdbba38SShri Abhyankar   PetscFunctionBegin;
4598*3ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4599bbead8a2SBarry Smith 
4600*3ea6fe3dSLisandro Dalcin   /* read in matrix header */
4601*3ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
4602*3ea6fe3dSLisandro Dalcin   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4603fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
4604*3ea6fe3dSLisandro Dalcin   if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%D) in file is negative",M);
4605*3ea6fe3dSLisandro Dalcin   if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%D) in file is negative",N);
4606bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4607fbdbba38SShri Abhyankar 
4608*3ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
4609*3ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
4610*3ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
4611*3ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
4612*3ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
4613*3ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
4614*3ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
4615*3ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
4616*3ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
4617*3ea6fe3dSLisandro Dalcin 
4618*3ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
4619*3ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4620*3ea6fe3dSLisandro 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);
4621*3ea6fe3dSLisandro Dalcin 
4622fbdbba38SShri Abhyankar   /* read in row lengths */
4623*3ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
4624*3ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
4625*3ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
4626*3ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
4627*3ea6fe3dSLisandro 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);
4628*3ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
4629*3ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
4630*3ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
463160e0710aSBarry 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);
4632*3ea6fe3dSLisandro Dalcin   /* store row lengths */
4633*3ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
4634*3ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
4635fbdbba38SShri Abhyankar 
4636*3ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
4637*3ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
4638*3ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
4639*3ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
4640*3ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
4641*3ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4642fbdbba38SShri Abhyankar 
4643*3ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4644*3ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4645fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4646fbdbba38SShri Abhyankar }
4647fbdbba38SShri Abhyankar 
4648ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
46497264ac53SSatish Balay {
46507264ac53SSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4651dfbe8321SBarry Smith   PetscErrorCode ierr;
4652eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4653eeffb40dSHong Zhang   PetscInt k;
4654eeffb40dSHong Zhang #endif
46557264ac53SSatish Balay 
46563a40ed3dSBarry Smith   PetscFunctionBegin;
4657bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4658d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4659ca44d042SBarry Smith     *flg = PETSC_FALSE;
4660ca44d042SBarry Smith     PetscFunctionReturn(0);
4661bcd2baecSBarry Smith   }
46627264ac53SSatish Balay 
46637264ac53SSatish Balay   /* if the a->i are the same */
4664580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4665abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
46667264ac53SSatish Balay 
46677264ac53SSatish Balay   /* if a->j are the same */
4668580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
4669abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
4670bcd2baecSBarry Smith 
4671bcd2baecSBarry Smith   /* if a->a are the same */
4672eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4673eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
4674eeffb40dSHong Zhang     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) {
4675eeffb40dSHong Zhang       *flg = PETSC_FALSE;
46763a40ed3dSBarry Smith       PetscFunctionReturn(0);
4677eeffb40dSHong Zhang     }
4678eeffb40dSHong Zhang   }
4679eeffb40dSHong Zhang #else
4680580bdb30SBarry Smith   ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr);
4681eeffb40dSHong Zhang #endif
4682eeffb40dSHong Zhang   PetscFunctionReturn(0);
46837264ac53SSatish Balay }
468436db0b34SBarry Smith 
468505869f15SSatish Balay /*@
468636db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
468736db0b34SBarry Smith               provided by the user.
468836db0b34SBarry Smith 
4689d083f849SBarry Smith       Collective
469036db0b34SBarry Smith 
469136db0b34SBarry Smith    Input Parameters:
469236db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
469336db0b34SBarry Smith .   m - number of rows
469436db0b34SBarry Smith .   n - number of columns
4695483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
469636db0b34SBarry Smith .   j - column indices
469736db0b34SBarry Smith -   a - matrix values
469836db0b34SBarry Smith 
469936db0b34SBarry Smith    Output Parameter:
470036db0b34SBarry Smith .   mat - the matrix
470136db0b34SBarry Smith 
470236db0b34SBarry Smith    Level: intermediate
470336db0b34SBarry Smith 
470436db0b34SBarry Smith    Notes:
47050551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
4706292fb18eSBarry Smith     once the matrix is destroyed and not before
470736db0b34SBarry Smith 
470836db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
470936db0b34SBarry Smith 
4710bfeeae90SHong Zhang        The i and j indices are 0 based
471136db0b34SBarry Smith 
4712a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
4713a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
47148eef79e4SBarry Smith     as shown
4715a4552177SSatish Balay 
47168eef79e4SBarry Smith $        1 0 0
47178eef79e4SBarry Smith $        2 0 3
47188eef79e4SBarry Smith $        4 5 6
47198eef79e4SBarry Smith $
47208eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
47218eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
47228eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
4723a4552177SSatish Balay 
47249985e31cSBarry Smith 
472569b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
472636db0b34SBarry Smith 
472736db0b34SBarry Smith @*/
4728c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
472936db0b34SBarry Smith {
4730dfbe8321SBarry Smith   PetscErrorCode ierr;
4731cbcfb4deSHong Zhang   PetscInt       ii;
473236db0b34SBarry Smith   Mat_SeqAIJ     *aij;
4733cbcfb4deSHong Zhang #if defined(PETSC_USE_DEBUG)
4734cbcfb4deSHong Zhang   PetscInt jj;
4735cbcfb4deSHong Zhang #endif
473636db0b34SBarry Smith 
473736db0b34SBarry Smith   PetscFunctionBegin;
473841096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4739f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
4740f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
4741a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
4742ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
4743ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr);
4744ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
4745071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
4746071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
4747ab93d7beSBarry Smith 
474836db0b34SBarry Smith   aij->i            = i;
474936db0b34SBarry Smith   aij->j            = j;
475036db0b34SBarry Smith   aij->a            = a;
475136db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
475236db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4753e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
4754e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
475536db0b34SBarry Smith 
475636db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
475736db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
47582515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
475960e0710aSBarry 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]);
47609985e31cSBarry Smith     for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4761a061629eSStefano 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);
4762a061629eSStefano 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);
47639985e31cSBarry Smith     }
476436db0b34SBarry Smith #endif
476536db0b34SBarry Smith   }
47662515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
476736db0b34SBarry Smith   for (ii=0; ii<aij->i[m]; ii++) {
476860e0710aSBarry Smith     if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
476960e0710aSBarry 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]);
477036db0b34SBarry Smith   }
477136db0b34SBarry Smith #endif
477236db0b34SBarry Smith 
4773b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4774b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
477536db0b34SBarry Smith   PetscFunctionReturn(0);
477636db0b34SBarry Smith }
477780ef6e79SMatthew G Knepley /*@C
4778d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
47798a0b0e6bSVictor Minden               provided by the user.
47808a0b0e6bSVictor Minden 
4781d083f849SBarry Smith       Collective
47828a0b0e6bSVictor Minden 
47838a0b0e6bSVictor Minden    Input Parameters:
47848a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
47858a0b0e6bSVictor Minden .   m   - number of rows
47868a0b0e6bSVictor Minden .   n   - number of columns
47878a0b0e6bSVictor Minden .   i   - row indices
47888a0b0e6bSVictor Minden .   j   - column indices
47891230e6d1SVictor Minden .   a   - matrix values
47901230e6d1SVictor Minden .   nz  - number of nonzeros
47911230e6d1SVictor Minden -   idx - 0 or 1 based
47928a0b0e6bSVictor Minden 
47938a0b0e6bSVictor Minden    Output Parameter:
47948a0b0e6bSVictor Minden .   mat - the matrix
47958a0b0e6bSVictor Minden 
47968a0b0e6bSVictor Minden    Level: intermediate
47978a0b0e6bSVictor Minden 
47988a0b0e6bSVictor Minden    Notes:
47998a0b0e6bSVictor Minden        The i and j indices are 0 based
48008a0b0e6bSVictor Minden 
48018a0b0e6bSVictor Minden        The format which is used for the sparse matrix input, is equivalent to a
48028a0b0e6bSVictor Minden     row-major ordering.. i.e for the following matrix, the input data expected is
48038a0b0e6bSVictor Minden     as shown:
48048a0b0e6bSVictor Minden 
48058a0b0e6bSVictor Minden         1 0 0
48068a0b0e6bSVictor Minden         2 0 3
48078a0b0e6bSVictor Minden         4 5 6
48088a0b0e6bSVictor Minden 
48098a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
48108a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
48118a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
48128a0b0e6bSVictor Minden 
48138a0b0e6bSVictor Minden 
481469b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
48158a0b0e6bSVictor Minden 
48168a0b0e6bSVictor Minden @*/
4817c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
48188a0b0e6bSVictor Minden {
48198a0b0e6bSVictor Minden   PetscErrorCode ierr;
4820d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
48218a0b0e6bSVictor Minden 
48228a0b0e6bSVictor Minden 
48238a0b0e6bSVictor Minden   PetscFunctionBegin;
48241795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
48251230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
4826c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
48271230e6d1SVictor Minden   }
48288a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
48298a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
48308a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
48311230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
48321230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
48331230e6d1SVictor Minden     if (idx) {
48341230e6d1SVictor Minden       row = i[ii] - 1;
48351230e6d1SVictor Minden       col = j[ii] - 1;
48361230e6d1SVictor Minden     } else {
48371230e6d1SVictor Minden       row = i[ii];
48381230e6d1SVictor Minden       col = j[ii];
48398a0b0e6bSVictor Minden     }
48401230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
48418a0b0e6bSVictor Minden   }
48428a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
48438a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4844d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
48458a0b0e6bSVictor Minden   PetscFunctionReturn(0);
48468a0b0e6bSVictor Minden }
484736db0b34SBarry Smith 
4848acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
4849acf2f550SJed Brown {
4850acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
4851acf2f550SJed Brown   PetscErrorCode ierr;
4852acf2f550SJed Brown 
4853acf2f550SJed Brown   PetscFunctionBegin;
4854acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
4855acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
48562205254eSKarl Rupp 
4857acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
4858acf2f550SJed Brown   PetscFunctionReturn(0);
4859acf2f550SJed Brown }
4860acf2f550SJed Brown 
48619c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
48629c8f2541SHong Zhang {
48639c8f2541SHong Zhang   PetscErrorCode ierr;
48648761c3d6SHong Zhang   PetscMPIInt    size;
48659c8f2541SHong Zhang 
48669c8f2541SHong Zhang   PetscFunctionBegin;
48678761c3d6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
48687bbdc51dSHong Zhang   if (size == 1) {
48697bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
48707bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
48717bbdc51dSHong Zhang     } else {
48728761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
48737bbdc51dSHong Zhang     }
48748761c3d6SHong Zhang   } else {
48759c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
48768761c3d6SHong Zhang   }
48779c8f2541SHong Zhang   PetscFunctionReturn(0);
48789c8f2541SHong Zhang }
48799c8f2541SHong Zhang 
488081824310SBarry Smith /*
488153dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
488253dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
488353dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
488453dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
488553dd7562SDmitry Karpeev  */
488653dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
488753dd7562SDmitry Karpeev {
488853dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
488953dd7562SDmitry Karpeev   PetscErrorCode ierr;
489053dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
489153dd7562SDmitry Karpeev   PetscBool      seqaij;
489253dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
489353dd7562SDmitry Karpeev   PetscScalar    v;
489453dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
489553dd7562SDmitry Karpeev 
489653dd7562SDmitry Karpeev   PetscFunctionBegin;
489753dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
489853dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
48994099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
490053dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
490153dd7562SDmitry Karpeev   if (rowemb) {
490253dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
490353dd7562SDmitry 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);
490453dd7562SDmitry Karpeev   } else {
49056c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
490653dd7562SDmitry Karpeev   }
490753dd7562SDmitry Karpeev   if (colemb) {
490853dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
490953dd7562SDmitry 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);
491053dd7562SDmitry Karpeev   } else {
491153dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
491253dd7562SDmitry Karpeev   }
491353dd7562SDmitry Karpeev 
491453dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
491553dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
491653dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
491753dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
491853dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
491953dd7562SDmitry Karpeev     }
492053dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
492153dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
492253dd7562SDmitry Karpeev   }
492353dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
492453dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
492553dd7562SDmitry Karpeev   }
492653dd7562SDmitry Karpeev   count = 0;
492753dd7562SDmitry Karpeev   rowindices = NULL;
492853dd7562SDmitry Karpeev   colindices = NULL;
492953dd7562SDmitry Karpeev   if (rowemb) {
493053dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
493153dd7562SDmitry Karpeev   }
493253dd7562SDmitry Karpeev   if (colemb) {
493353dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
493453dd7562SDmitry Karpeev   }
493553dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
493653dd7562SDmitry Karpeev     PetscInt row;
493753dd7562SDmitry Karpeev     row = i;
493853dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
493953dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
494053dd7562SDmitry Karpeev       PetscInt col;
494153dd7562SDmitry Karpeev       col  = Baij->j[count];
494253dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
494353dd7562SDmitry Karpeev       v    = Baij->a[count];
494453dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
494553dd7562SDmitry Karpeev       ++count;
494653dd7562SDmitry Karpeev     }
494753dd7562SDmitry Karpeev   }
494853dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
494953dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
495053dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
495153dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
495253dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
495353dd7562SDmitry Karpeev   PetscFunctionReturn(0);
495453dd7562SDmitry Karpeev }
495553dd7562SDmitry Karpeev 
49564099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
49574099cc6bSBarry Smith 
49584099cc6bSBarry Smith /*@C
49594099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
49604099cc6bSBarry Smith 
49614099cc6bSBarry Smith    Collective on Mat
49624099cc6bSBarry Smith 
49634099cc6bSBarry Smith    Input Parameters:
49644099cc6bSBarry Smith +  mat      - the matrix object
49654099cc6bSBarry Smith -  matype   - matrix type
49664099cc6bSBarry Smith 
49674099cc6bSBarry Smith    Options Database Key:
49684099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
49694099cc6bSBarry Smith 
49704099cc6bSBarry Smith 
49714099cc6bSBarry Smith   Level: intermediate
49724099cc6bSBarry Smith 
49734099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
49744099cc6bSBarry Smith @*/
49754099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
49764099cc6bSBarry Smith {
4977fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
49784099cc6bSBarry Smith   PetscBool      sametype;
49794099cc6bSBarry Smith 
49804099cc6bSBarry Smith   PetscFunctionBegin;
49814099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
49824099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
49834099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
49844099cc6bSBarry Smith 
49854099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
49864099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
49874099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
49884099cc6bSBarry Smith   PetscFunctionReturn(0);
49894099cc6bSBarry Smith }
49904099cc6bSBarry Smith 
49914099cc6bSBarry Smith 
49924099cc6bSBarry Smith /*@C
49934099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
49944099cc6bSBarry Smith 
49954099cc6bSBarry Smith    Not Collective
49964099cc6bSBarry Smith 
49974099cc6bSBarry Smith    Input Parameters:
49984099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
49994099cc6bSBarry Smith -  function - routine to convert to subtype
50004099cc6bSBarry Smith 
50014099cc6bSBarry Smith    Notes:
50024099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
50034099cc6bSBarry Smith 
50044099cc6bSBarry Smith 
50054099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
50064099cc6bSBarry Smith $     -mat_seqaij_type my_mat
50074099cc6bSBarry Smith 
50084099cc6bSBarry Smith    Level: advanced
50094099cc6bSBarry Smith 
50104099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
50114099cc6bSBarry Smith 
50124099cc6bSBarry Smith 
50134099cc6bSBarry Smith   Level: advanced
50144099cc6bSBarry Smith @*/
5015388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
50164099cc6bSBarry Smith {
50174099cc6bSBarry Smith   PetscErrorCode ierr;
50184099cc6bSBarry Smith 
50194099cc6bSBarry Smith   PetscFunctionBegin;
50209cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
50214099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
50224099cc6bSBarry Smith   PetscFunctionReturn(0);
50234099cc6bSBarry Smith }
50244099cc6bSBarry Smith 
50254099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
50264099cc6bSBarry Smith 
50274099cc6bSBarry Smith /*@C
50284099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
50294099cc6bSBarry Smith 
50304099cc6bSBarry Smith   Not Collective
50314099cc6bSBarry Smith 
50324099cc6bSBarry Smith   Level: advanced
50334099cc6bSBarry Smith 
50344099cc6bSBarry Smith   Developers Note: CUSP and CUSPARSE do not yet support the  MatConvert_SeqAIJ..() paradigm and thus cannot be registered here
50354099cc6bSBarry Smith 
50364099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
50374099cc6bSBarry Smith @*/
50384099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
50394099cc6bSBarry Smith {
50404099cc6bSBarry Smith   PetscErrorCode ierr;
50414099cc6bSBarry Smith 
50424099cc6bSBarry Smith   PetscFunctionBegin;
50434099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
50444099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
50454099cc6bSBarry Smith 
50464099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
50474099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
50484dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
50499779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
50506b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5051485f9817SRichard Tran Mills #endif
50524099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
50534099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
50544099cc6bSBarry Smith #endif
50554099cc6bSBarry Smith   PetscFunctionReturn(0);
50564099cc6bSBarry Smith }
505753dd7562SDmitry Karpeev 
505853dd7562SDmitry Karpeev /*
505981824310SBarry Smith     Special version for direct calls from Fortran
506081824310SBarry Smith */
5061af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
506281824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
506381824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
506481824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
506581824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
506681824310SBarry Smith #endif
506781824310SBarry Smith 
506881824310SBarry Smith /* Change these macros so can be used in void function */
506981824310SBarry Smith #undef CHKERRQ
5070ce94432eSBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr)
507181824310SBarry Smith #undef SETERRQ2
5072e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
50734994cf47SJed Brown #undef SETERRQ3
50744994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
507581824310SBarry Smith 
507619caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
507781824310SBarry Smith {
507881824310SBarry Smith   Mat            A  = *AA;
507981824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
508081824310SBarry Smith   InsertMode     is = *isis;
508181824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
508281824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
508381824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
508481824310SBarry Smith   PetscErrorCode ierr;
508581824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
508654f21887SBarry Smith   MatScalar      *ap,value,*aa;
5087ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5088ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
508981824310SBarry Smith 
509081824310SBarry Smith   PetscFunctionBegin;
50914994cf47SJed Brown   MatCheckPreallocated(A,1);
509281824310SBarry Smith   imax  = a->imax;
509381824310SBarry Smith   ai    = a->i;
509481824310SBarry Smith   ailen = a->ilen;
509581824310SBarry Smith   aj    = a->j;
509681824310SBarry Smith   aa    = a->a;
509781824310SBarry Smith 
509881824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
509981824310SBarry Smith     row = im[k];
510081824310SBarry Smith     if (row < 0) continue;
510181824310SBarry Smith #if defined(PETSC_USE_DEBUG)
5102ce94432eSBarry Smith     if (row >= A->rmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
510381824310SBarry Smith #endif
510481824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
510581824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
510681824310SBarry Smith     low  = 0;
510781824310SBarry Smith     high = nrow;
510881824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
510981824310SBarry Smith       if (in[l] < 0) continue;
511081824310SBarry Smith #if defined(PETSC_USE_DEBUG)
5111ce94432eSBarry Smith       if (in[l] >= A->cmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
511281824310SBarry Smith #endif
511381824310SBarry Smith       col = in[l];
51142205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
51152205254eSKarl Rupp       else value = v[k + l*m];
51162205254eSKarl Rupp 
511781824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
511881824310SBarry Smith 
51192205254eSKarl Rupp       if (col <= lastcol) low = 0;
51202205254eSKarl Rupp       else high = nrow;
512181824310SBarry Smith       lastcol = col;
512281824310SBarry Smith       while (high-low > 5) {
512381824310SBarry Smith         t = (low+high)/2;
512481824310SBarry Smith         if (rp[t] > col) high = t;
512581824310SBarry Smith         else             low  = t;
512681824310SBarry Smith       }
512781824310SBarry Smith       for (i=low; i<high; i++) {
512881824310SBarry Smith         if (rp[i] > col) break;
512981824310SBarry Smith         if (rp[i] == col) {
513081824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
513181824310SBarry Smith           else                  ap[i] = value;
513281824310SBarry Smith           goto noinsert;
513381824310SBarry Smith         }
513481824310SBarry Smith       }
513581824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
513681824310SBarry Smith       if (nonew == 1) goto noinsert;
5137ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5138fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
513981824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
514081824310SBarry Smith       /* shift up all the later entries in this row */
514181824310SBarry Smith       for (ii=N; ii>=i; ii--) {
514281824310SBarry Smith         rp[ii+1] = rp[ii];
514381824310SBarry Smith         ap[ii+1] = ap[ii];
514481824310SBarry Smith       }
514581824310SBarry Smith       rp[i] = col;
514681824310SBarry Smith       ap[i] = value;
5147e56f5c9eSBarry Smith       A->nonzerostate++;
514881824310SBarry Smith noinsert:;
514981824310SBarry Smith       low = i + 1;
515081824310SBarry Smith     }
515181824310SBarry Smith     ailen[row] = nrow;
515281824310SBarry Smith   }
515381824310SBarry Smith   PetscFunctionReturnVoid();
515481824310SBarry Smith }
5155