xref: /petsc/src/mat/impls/aij/seq/aij.c (revision b5bb3eec4afc66d739e2568c3e52fd3dc52b55fe)
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;
17779299369SBarry Smith 
17879299369SBarry Smith   PetscFunctionBegin;
17909f38230SBarry Smith   if (Y->assembled) {
1800298fd71SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr);
18109f38230SBarry Smith     if (!missing) {
18279299369SBarry Smith       diag = aij->diag;
18399e65526SBarry Smith       ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr);
18479299369SBarry Smith       if (is == INSERT_VALUES) {
18579299369SBarry Smith         for (i=0; i<m; i++) {
18679299369SBarry Smith           aa[diag[i]] = v[i];
18779299369SBarry Smith         }
18879299369SBarry Smith       } else {
18979299369SBarry Smith         for (i=0; i<m; i++) {
19079299369SBarry Smith           aa[diag[i]] += v[i];
19179299369SBarry Smith         }
19279299369SBarry Smith       }
19399e65526SBarry Smith       ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr);
19479299369SBarry Smith       PetscFunctionReturn(0);
19579299369SBarry Smith     }
196acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
19709f38230SBarry Smith   }
19809f38230SBarry Smith   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
19909f38230SBarry Smith   PetscFunctionReturn(0);
20009f38230SBarry Smith }
20179299369SBarry Smith 
2021a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
20317ab2063SBarry Smith {
204416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
205dfbe8321SBarry Smith   PetscErrorCode ierr;
20697f1f81fSBarry Smith   PetscInt       i,ishift;
20717ab2063SBarry Smith 
2083a40ed3dSBarry Smith   PetscFunctionBegin;
209d0f46423SBarry Smith   *m = A->rmap->n;
2103a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
211bfeeae90SHong Zhang   ishift = 0;
21253e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2132462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
214bfeeae90SHong Zhang   } else if (oshift == 1) {
2151a83f524SJed Brown     PetscInt *tia;
216d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2173b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
218854ce69bSBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr);
2191a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2201a83f524SJed Brown     *ia = tia;
221ecc77c7aSBarry Smith     if (ja) {
2221a83f524SJed Brown       PetscInt *tja;
223854ce69bSBarry Smith       ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr);
2241a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2251a83f524SJed Brown       *ja = tja;
226ecc77c7aSBarry Smith     }
2276945ee14SBarry Smith   } else {
228ecc77c7aSBarry Smith     *ia = a->i;
229ecc77c7aSBarry Smith     if (ja) *ja = a->j;
230a2ce50c7SBarry Smith   }
2313a40ed3dSBarry Smith   PetscFunctionReturn(0);
232a2744918SBarry Smith }
233a2744918SBarry Smith 
2341a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2356945ee14SBarry Smith {
236dfbe8321SBarry Smith   PetscErrorCode ierr;
2376945ee14SBarry Smith 
2383a40ed3dSBarry Smith   PetscFunctionBegin;
2393a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
240bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
241606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
242ecc77c7aSBarry Smith     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
243bcd2baecSBarry Smith   }
2443a40ed3dSBarry Smith   PetscFunctionReturn(0);
24517ab2063SBarry Smith }
24617ab2063SBarry Smith 
2471a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2483b2fbd54SBarry Smith {
2493b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
250dfbe8321SBarry Smith   PetscErrorCode ierr;
251d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
25297f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2533b2fbd54SBarry Smith 
2543a40ed3dSBarry Smith   PetscFunctionBegin;
255899cda47SBarry Smith   *nn = n;
2563a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2573b2fbd54SBarry Smith   if (symmetric) {
2582462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
2593b2fbd54SBarry Smith   } else {
260b9e7e5c1SBarry Smith     ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
261854ce69bSBarry Smith     ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
262b9e7e5c1SBarry Smith     ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
2633b2fbd54SBarry Smith     jj   = a->j;
2643b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
265bfeeae90SHong Zhang       collengths[jj[i]]++;
2663b2fbd54SBarry Smith     }
2673b2fbd54SBarry Smith     cia[0] = oshift;
2683b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2693b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2703b2fbd54SBarry Smith     }
271580bdb30SBarry Smith     ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
2723b2fbd54SBarry Smith     jj   = a->j;
273a93ec695SBarry Smith     for (row=0; row<m; row++) {
274a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
275a93ec695SBarry Smith       for (i=0; i<mr; i++) {
276bfeeae90SHong Zhang         col = *jj++;
2772205254eSKarl Rupp 
2783b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2793b2fbd54SBarry Smith       }
2803b2fbd54SBarry Smith     }
281606d414cSSatish Balay     ierr = PetscFree(collengths);CHKERRQ(ierr);
2823b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
2833b2fbd54SBarry Smith   }
2843a40ed3dSBarry Smith   PetscFunctionReturn(0);
2853b2fbd54SBarry Smith }
2863b2fbd54SBarry Smith 
2871a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2883b2fbd54SBarry Smith {
289dfbe8321SBarry Smith   PetscErrorCode ierr;
290606d414cSSatish Balay 
2913a40ed3dSBarry Smith   PetscFunctionBegin;
2923a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2933b2fbd54SBarry Smith 
294606d414cSSatish Balay   ierr = PetscFree(*ia);CHKERRQ(ierr);
295606d414cSSatish Balay   ierr = PetscFree(*ja);CHKERRQ(ierr);
2963a40ed3dSBarry Smith   PetscFunctionReturn(0);
2973b2fbd54SBarry Smith }
2983b2fbd54SBarry Smith 
2997cee066cSHong Zhang /*
3007cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3017cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
302040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3037cee066cSHong Zhang */
3047cee066cSHong Zhang PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
3057cee066cSHong Zhang {
3067cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3077cee066cSHong Zhang   PetscErrorCode ierr;
3087cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
309071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3107cee066cSHong Zhang   PetscInt       *cspidx;
311071fcb05SBarry Smith   const PetscInt *jj;
3127cee066cSHong Zhang 
3137cee066cSHong Zhang   PetscFunctionBegin;
3147cee066cSHong Zhang   *nn = n;
3157cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
316625f6d37SHong Zhang 
317b9e7e5c1SBarry Smith   ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
318854ce69bSBarry Smith   ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
319b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
320b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr);
3217cee066cSHong Zhang   jj   = a->j;
3227cee066cSHong Zhang   for (i=0; i<nz; i++) {
3237cee066cSHong Zhang     collengths[jj[i]]++;
3247cee066cSHong Zhang   }
3257cee066cSHong Zhang   cia[0] = oshift;
3267cee066cSHong Zhang   for (i=0; i<n; i++) {
3277cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3287cee066cSHong Zhang   }
329580bdb30SBarry Smith   ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
3307cee066cSHong Zhang   jj   = a->j;
3317cee066cSHong Zhang   for (row=0; row<m; row++) {
3327cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3337cee066cSHong Zhang     for (i=0; i<mr; i++) {
3347cee066cSHong Zhang       col         = *jj++;
335071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
336071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
337071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3387cee066cSHong Zhang     }
3397cee066cSHong Zhang   }
3407cee066cSHong Zhang   ierr   = PetscFree(collengths);CHKERRQ(ierr);
341071fcb05SBarry Smith   *ia    = cia;
342071fcb05SBarry Smith   *ja    = cja;
3437cee066cSHong Zhang   *spidx = cspidx;
3447cee066cSHong Zhang   PetscFunctionReturn(0);
3457cee066cSHong Zhang }
3467cee066cSHong Zhang 
3477cee066cSHong 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)
3487cee066cSHong Zhang {
3497cee066cSHong Zhang   PetscErrorCode ierr;
3507cee066cSHong Zhang 
3517cee066cSHong Zhang   PetscFunctionBegin;
3525243ef75SHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
3537cee066cSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
3547cee066cSHong Zhang   PetscFunctionReturn(0);
3557cee066cSHong Zhang }
3567cee066cSHong Zhang 
35787d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
35887d4246cSBarry Smith {
35987d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
36087d4246cSBarry Smith   PetscInt       *ai = a->i;
36187d4246cSBarry Smith   PetscErrorCode ierr;
36287d4246cSBarry Smith 
36387d4246cSBarry Smith   PetscFunctionBegin;
364580bdb30SBarry Smith   ierr = PetscArraycpy(a->a+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr);
36587d4246cSBarry Smith   PetscFunctionReturn(0);
36687d4246cSBarry Smith }
36787d4246cSBarry Smith 
368bd04181cSBarry Smith /*
369bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
370bd04181cSBarry Smith 
371bd04181cSBarry Smith       -   a single row of values is set with each call
372bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
373bd04181cSBarry Smith       -   the values are always added to the matrix, not set
374bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
375bd04181cSBarry Smith 
3761f763a69SBarry Smith      This does NOT assume the global column indices are sorted
377bd04181cSBarry Smith 
3781f763a69SBarry Smith */
379bd04181cSBarry Smith 
380af0996ceSBarry Smith #include <petsc/private/isimpl.h>
381189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
382189e4007SBarry Smith {
383189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3841f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
3851f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
3861f763a69SBarry Smith   PetscInt       lastcol = -1;
387189e4007SBarry Smith   MatScalar      *ap,value,*aa = a->a;
388189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
389189e4007SBarry Smith 
390f38dd0b8SBarry Smith   row = ridx[im[0]];
3911f763a69SBarry Smith   rp   = aj + ai[row];
3921f763a69SBarry Smith   ap = aa + ai[row];
3931f763a69SBarry Smith   nrow = ailen[row];
394189e4007SBarry Smith   low  = 0;
395189e4007SBarry Smith   high = nrow;
396189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
397189e4007SBarry Smith     col = cidx[in[l]];
398f38dd0b8SBarry Smith     value = v[l];
399189e4007SBarry Smith 
400189e4007SBarry Smith     if (col <= lastcol) low = 0;
401189e4007SBarry Smith     else high = nrow;
402189e4007SBarry Smith     lastcol = col;
403189e4007SBarry Smith     while (high-low > 5) {
404189e4007SBarry Smith       t = (low+high)/2;
405189e4007SBarry Smith       if (rp[t] > col) high = t;
406189e4007SBarry Smith       else low = t;
407189e4007SBarry Smith     }
408189e4007SBarry Smith     for (i=low; i<high; i++) {
409189e4007SBarry Smith       if (rp[i] == col) {
4101f763a69SBarry Smith         ap[i] += value;
411189e4007SBarry Smith         low = i + 1;
4121f763a69SBarry Smith         break;
413189e4007SBarry Smith       }
414189e4007SBarry Smith     }
415189e4007SBarry Smith   }
416f38dd0b8SBarry Smith   return 0;
417189e4007SBarry Smith }
418189e4007SBarry Smith 
41997f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
42017ab2063SBarry Smith {
421416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
422e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
42397f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
4246849ba73SBarry Smith   PetscErrorCode ierr;
425e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
426d8cdefa3SHong Zhang   MatScalar      *ap=NULL,value=0.0,*aa = a->a;
427ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
428ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
42917ab2063SBarry Smith 
4303a40ed3dSBarry Smith   PetscFunctionBegin;
43117ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
432416022c9SBarry Smith     row = im[k];
4335ef9f2a5SBarry Smith     if (row < 0) continue;
4342515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
435e32f2f54SBarry 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);
4363b2fbd54SBarry Smith #endif
437720833daSHong Zhang     rp   = aj + ai[row];
438876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
43917ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
440416022c9SBarry Smith     low  = 0;
441c71e6ed7SBarry Smith     high = nrow;
44217ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4435ef9f2a5SBarry Smith       if (in[l] < 0) continue;
4442515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
445e32f2f54SBarry 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);
4463b2fbd54SBarry Smith #endif
447bfeeae90SHong Zhang       col = in[l];
448071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
449071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
45036db0b34SBarry Smith 
4512205254eSKarl Rupp       if (col <= lastcol) low = 0;
4522205254eSKarl Rupp       else high = nrow;
453e2ee6c50SBarry Smith       lastcol = col;
454416022c9SBarry Smith       while (high-low > 5) {
455416022c9SBarry Smith         t = (low+high)/2;
456416022c9SBarry Smith         if (rp[t] > col) high = t;
457416022c9SBarry Smith         else low = t;
45817ab2063SBarry Smith       }
459416022c9SBarry Smith       for (i=low; i<high; i++) {
46017ab2063SBarry Smith         if (rp[i] > col) break;
46117ab2063SBarry Smith         if (rp[i] == col) {
462876c6284SHong Zhang           if (!A->structure_only) {
4630c0d7e18SFande Kong             if (is == ADD_VALUES) {
4640c0d7e18SFande Kong               ap[i] += value;
4650c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4660c0d7e18SFande Kong             }
46717ab2063SBarry Smith             else ap[i] = value;
468720833daSHong Zhang           }
469e44c0bd4SBarry Smith           low = i + 1;
47017ab2063SBarry Smith           goto noinsert;
47117ab2063SBarry Smith         }
47217ab2063SBarry Smith       }
473dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
474c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
475e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
476720833daSHong Zhang       if (A->structure_only) {
477876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
478720833daSHong Zhang       } else {
479fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
480720833daSHong Zhang       }
481c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
482416022c9SBarry Smith       /* shift up all the later entries in this row */
483580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
48417ab2063SBarry Smith       rp[i] = col;
485580bdb30SBarry Smith       if (!A->structure_only){
486580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
487580bdb30SBarry Smith         ap[i] = value;
488580bdb30SBarry Smith       }
489416022c9SBarry Smith       low = i + 1;
490e56f5c9eSBarry Smith       A->nonzerostate++;
491e44c0bd4SBarry Smith noinsert:;
49217ab2063SBarry Smith     }
49317ab2063SBarry Smith     ailen[row] = nrow;
49417ab2063SBarry Smith   }
4953a40ed3dSBarry Smith   PetscFunctionReturn(0);
49617ab2063SBarry Smith }
49717ab2063SBarry Smith 
498071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
499071fcb05SBarry Smith {
500071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
501071fcb05SBarry Smith   PetscInt       *rp,k,row;
502071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
503071fcb05SBarry Smith   PetscErrorCode ierr;
504071fcb05SBarry Smith   PetscInt       *aj = a->j;
505071fcb05SBarry Smith   MatScalar      *aa = a->a,*ap;
506071fcb05SBarry Smith 
507071fcb05SBarry Smith   PetscFunctionBegin;
508071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
509071fcb05SBarry Smith     row  = im[k];
510071fcb05SBarry Smith     rp   = aj + ai[row];
511071fcb05SBarry Smith     ap   = aa + ai[row];
512071fcb05SBarry Smith     if (!A->was_assembled) {
513071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
514071fcb05SBarry Smith     }
515071fcb05SBarry Smith     if (!A->structure_only) {
516071fcb05SBarry Smith       if (v) {
517071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
518071fcb05SBarry Smith         v   += n;
519071fcb05SBarry Smith       } else {
520071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
521071fcb05SBarry Smith       }
522071fcb05SBarry Smith     }
523071fcb05SBarry Smith     ailen[row] = n;
524071fcb05SBarry Smith     a->nz      += n;
525071fcb05SBarry Smith   }
526071fcb05SBarry Smith   PetscFunctionReturn(0);
527071fcb05SBarry Smith }
528071fcb05SBarry Smith 
52981824310SBarry Smith 
530a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
5317eb43aa7SLois Curfman McInnes {
5327eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
53397f1f81fSBarry Smith   PetscInt   *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
53497f1f81fSBarry Smith   PetscInt   *ai = a->i,*ailen = a->ilen;
53554f21887SBarry Smith   MatScalar  *ap,*aa = a->a;
5367eb43aa7SLois Curfman McInnes 
5373a40ed3dSBarry Smith   PetscFunctionBegin;
5387eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
5397eb43aa7SLois Curfman McInnes     row = im[k];
540e32f2f54SBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
541e32f2f54SBarry 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);
542bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
5437eb43aa7SLois Curfman McInnes     nrow = ailen[row];
5447eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
545e32f2f54SBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
546e32f2f54SBarry 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);
547bfeeae90SHong Zhang       col  = in[l];
5487eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
5497eb43aa7SLois Curfman McInnes       while (high-low > 5) {
5507eb43aa7SLois Curfman McInnes         t = (low+high)/2;
5517eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
5527eb43aa7SLois Curfman McInnes         else low = t;
5537eb43aa7SLois Curfman McInnes       }
5547eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
5557eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
5567eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
557b49de8d1SLois Curfman McInnes           *v++ = ap[i];
5587eb43aa7SLois Curfman McInnes           goto finished;
5597eb43aa7SLois Curfman McInnes         }
5607eb43aa7SLois Curfman McInnes       }
56197e567efSBarry Smith       *v++ = 0.0;
5627eb43aa7SLois Curfman McInnes finished:;
5637eb43aa7SLois Curfman McInnes     }
5647eb43aa7SLois Curfman McInnes   }
5653a40ed3dSBarry Smith   PetscFunctionReturn(0);
5667eb43aa7SLois Curfman McInnes }
5677eb43aa7SLois Curfman McInnes 
56817ab2063SBarry Smith 
569dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer)
57017ab2063SBarry Smith {
571416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
5726849ba73SBarry Smith   PetscErrorCode ierr;
5736f69ff64SBarry Smith   PetscInt       i,*col_lens;
5746f69ff64SBarry Smith   int            fd;
575b37d52dbSMark F. Adams   FILE           *file;
57617ab2063SBarry Smith 
5773a40ed3dSBarry Smith   PetscFunctionBegin;
578b0a32e0cSBarry Smith   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
579854ce69bSBarry Smith   ierr = PetscMalloc1(4+A->rmap->n,&col_lens);CHKERRQ(ierr);
5802205254eSKarl Rupp 
5810700a824SBarry Smith   col_lens[0] = MAT_FILE_CLASSID;
582d0f46423SBarry Smith   col_lens[1] = A->rmap->n;
583d0f46423SBarry Smith   col_lens[2] = A->cmap->n;
584416022c9SBarry Smith   col_lens[3] = a->nz;
585416022c9SBarry Smith 
586416022c9SBarry Smith   /* store lengths of each row and write (including header) to file */
587d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
588416022c9SBarry Smith     col_lens[4+i] = a->i[i+1] - a->i[i];
58917ab2063SBarry Smith   }
590d0f46423SBarry Smith   ierr = PetscBinaryWrite(fd,col_lens,4+A->rmap->n,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
591606d414cSSatish Balay   ierr = PetscFree(col_lens);CHKERRQ(ierr);
592416022c9SBarry Smith 
593416022c9SBarry Smith   /* store column indices (zero start index) */
5946f69ff64SBarry Smith   ierr = PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
595416022c9SBarry Smith 
596416022c9SBarry Smith   /* store nonzero values */
5976f69ff64SBarry Smith   ierr = PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
598b37d52dbSMark F. Adams 
599b37d52dbSMark F. Adams   ierr = PetscViewerBinaryGetInfoPointer(viewer,&file);CHKERRQ(ierr);
600b37d52dbSMark F. Adams   if (file) {
60133d57670SJed Brown     fprintf(file,"-matload_block_size %d\n",(int)PetscAbs(A->rmap->bs));
602b37d52dbSMark F. Adams   }
6033a40ed3dSBarry Smith   PetscFunctionReturn(0);
60417ab2063SBarry Smith }
605416022c9SBarry Smith 
6067dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
6077dc0baabSHong Zhang {
6087dc0baabSHong Zhang   PetscErrorCode ierr;
6097dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
6107dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
6117dc0baabSHong Zhang 
6127dc0baabSHong Zhang   PetscFunctionBegin;
6137dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
6147dc0baabSHong Zhang   for (i=0; i<m; i++) {
6157dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
6167dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
6177dc0baabSHong Zhang       ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr);
6187dc0baabSHong Zhang     }
6197dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
6207dc0baabSHong Zhang   }
6217dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
6227dc0baabSHong Zhang   PetscFunctionReturn(0);
6237dc0baabSHong Zhang }
6247dc0baabSHong Zhang 
62509573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
626cd155464SBarry Smith 
627dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
628416022c9SBarry Smith {
629416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
630dfbe8321SBarry Smith   PetscErrorCode    ierr;
63160e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
632e060cb09SBarry Smith   const char        *name;
633f3ef73ceSBarry Smith   PetscViewerFormat format;
63417ab2063SBarry Smith 
6353a40ed3dSBarry Smith   PetscFunctionBegin;
6367dc0baabSHong Zhang   if (A->structure_only) {
6377dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
6387dc0baabSHong Zhang     PetscFunctionReturn(0);
6397dc0baabSHong Zhang   }
64043e49210SHong Zhang 
641b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
64271c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
64397f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
64460e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
645c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
646d00d2cf4SBarry Smith       nofinalvalue = 1;
647d00d2cf4SBarry Smith     }
648d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
649d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
65077431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
651fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
652fbfe6fa7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
653fbfe6fa7SJed Brown #else
65477431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
655fbfe6fa7SJed Brown #endif
656b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
65717ab2063SBarry Smith 
65817ab2063SBarry Smith     for (i=0; i<m; i++) {
65960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
660aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
661a9bf72d8SJed 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);
66217ab2063SBarry Smith #else
66360e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
66417ab2063SBarry Smith #endif
66517ab2063SBarry Smith       }
66617ab2063SBarry Smith     }
667d00d2cf4SBarry Smith     if (nofinalvalue) {
668c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
669c337ccceSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
670c337ccceSJed Brown #else
671d0f46423SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
672c337ccceSJed Brown #endif
673d00d2cf4SBarry Smith     }
674317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
675fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
676d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
67768369a75SKris Buschelman   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
678cd155464SBarry Smith     PetscFunctionReturn(0);
679fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
680d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
68144cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
68277431f27SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
68360e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
684aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
68536db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
68660e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
68736db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
68860e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
68936db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
69060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
6916831982aSBarry Smith         }
69244cd7ae7SLois Curfman McInnes #else
69360e0710aSBarry Smith         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
69444cd7ae7SLois Curfman McInnes #endif
69544cd7ae7SLois Curfman McInnes       }
696b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
69744cd7ae7SLois Curfman McInnes     }
698d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
699fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
70097f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
701d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
702854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
703496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
704496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
70560e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
706496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
707aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
70836db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
709496be53dSLois Curfman McInnes #else
710496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
711496be53dSLois Curfman McInnes #endif
712496be53dSLois Curfman McInnes         }
713496be53dSLois Curfman McInnes       }
714496be53dSLois Curfman McInnes     }
7152e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
71677431f27SBarry Smith     ierr    = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
7172e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
7182205254eSKarl Rupp       if (i+4<m) {
7192205254eSKarl 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);
7202205254eSKarl Rupp       } else if (i+3<m) {
7212205254eSKarl 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);
7222205254eSKarl Rupp       } else if (i+2<m) {
7232205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
7242205254eSKarl Rupp       } else if (i+1<m) {
7252205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
7262205254eSKarl Rupp       } else if (i<m) {
7272205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
7282205254eSKarl Rupp       } else {
7292205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);
7302205254eSKarl Rupp       }
731496be53dSLois Curfman McInnes     }
732b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
733606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
734496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
73560e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
73677431f27SBarry Smith         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
737496be53dSLois Curfman McInnes       }
738b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
739496be53dSLois Curfman McInnes     }
740b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
741496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
74260e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
743496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
744aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
74536db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
74660e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
7476831982aSBarry Smith           }
748496be53dSLois Curfman McInnes #else
74960e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
750496be53dSLois Curfman McInnes #endif
751496be53dSLois Curfman McInnes         }
752496be53dSLois Curfman McInnes       }
753b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
754496be53dSLois Curfman McInnes     }
755d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
756fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
75797f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
75887828ca2SBarry Smith     PetscScalar value;
75968f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
76068f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
76168f1ed48SBarry Smith 
76268f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
76368f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
76468f1ed48SBarry Smith         realonly = PETSC_FALSE;
76568f1ed48SBarry Smith         break;
76668f1ed48SBarry Smith       }
76768f1ed48SBarry Smith     }
76868f1ed48SBarry Smith #endif
76902594712SBarry Smith 
770d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
77102594712SBarry Smith     for (i=0; i<m; i++) {
77202594712SBarry Smith       jcnt = 0;
773d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
774e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
77502594712SBarry Smith           value = a->a[cnt++];
776e24b481bSBarry Smith           jcnt++;
77702594712SBarry Smith         } else {
77802594712SBarry Smith           value = 0.0;
77902594712SBarry Smith         }
780aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
78168f1ed48SBarry Smith         if (realonly) {
78260e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
78368f1ed48SBarry Smith         } else {
78460e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
78568f1ed48SBarry Smith         }
78602594712SBarry Smith #else
78760e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
78802594712SBarry Smith #endif
78902594712SBarry Smith       }
790b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
79102594712SBarry Smith     }
792d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
7933c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
794150b93efSMatthew G. Knepley     PetscInt fshift=1;
795d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
7963c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
79719303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
7983c215bfdSMatthew Knepley #else
79919303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
8003c215bfdSMatthew Knepley #endif
801d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
8023c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
80360e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
8043c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
805a9a0e077SKarl 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);
8063c215bfdSMatthew Knepley #else
807150b93efSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
8083c215bfdSMatthew Knepley #endif
8093c215bfdSMatthew Knepley       }
8103c215bfdSMatthew Knepley     }
811d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
8123a40ed3dSBarry Smith   } else {
813d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
814d5f3da31SBarry Smith     if (A->factortype) {
81516cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
81616cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
81716cd7e1dSShri Abhyankar         /* L part */
81860e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
81916cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
82016cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
82160e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
82216cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
8236712e2f1SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
82416cd7e1dSShri Abhyankar           } else {
82560e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
82616cd7e1dSShri Abhyankar           }
82716cd7e1dSShri Abhyankar #else
82860e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
82916cd7e1dSShri Abhyankar #endif
83016cd7e1dSShri Abhyankar         }
83116cd7e1dSShri Abhyankar         /* diagonal */
83216cd7e1dSShri Abhyankar         j = a->diag[i];
83316cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
83416cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
83560e0710aSBarry 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);
83616cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
8376712e2f1SBarry 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);
83816cd7e1dSShri Abhyankar         } else {
83960e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
84016cd7e1dSShri Abhyankar         }
84116cd7e1dSShri Abhyankar #else
84260e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
84316cd7e1dSShri Abhyankar #endif
84416cd7e1dSShri Abhyankar 
84516cd7e1dSShri Abhyankar         /* U part */
84660e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
84716cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
84816cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
84960e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
85016cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
85122ab088eSBarry 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 {
85360e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
85416cd7e1dSShri Abhyankar           }
85516cd7e1dSShri Abhyankar #else
85660e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
85716cd7e1dSShri Abhyankar #endif
85816cd7e1dSShri Abhyankar         }
85916cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
86016cd7e1dSShri Abhyankar       }
86116cd7e1dSShri Abhyankar     } else {
86217ab2063SBarry Smith       for (i=0; i<m; i++) {
86377431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
86460e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
865aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
86636db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
86760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
86836db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
86960e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
8703a40ed3dSBarry Smith           } else {
87160e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
87217ab2063SBarry Smith           }
87317ab2063SBarry Smith #else
87460e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
87517ab2063SBarry Smith #endif
87617ab2063SBarry Smith         }
877b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
87817ab2063SBarry Smith       }
87916cd7e1dSShri Abhyankar     }
880d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
88117ab2063SBarry Smith   }
882b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8833a40ed3dSBarry Smith   PetscFunctionReturn(0);
884416022c9SBarry Smith }
885416022c9SBarry Smith 
8869804daf3SBarry Smith #include <petscdraw.h>
887dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
888416022c9SBarry Smith {
889480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
890416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
891dfbe8321SBarry Smith   PetscErrorCode    ierr;
892383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
893383922c3SLisandro Dalcin   int               color;
894b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
895b0a32e0cSBarry Smith   PetscViewer       viewer;
896f3ef73ceSBarry Smith   PetscViewerFormat format;
897cddf8d76SBarry Smith 
8983a40ed3dSBarry Smith   PetscFunctionBegin;
899480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
900b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
901b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
902383922c3SLisandro Dalcin 
903416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
9040513a670SBarry Smith 
905fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
906383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
9070513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
908b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
909416022c9SBarry Smith     for (i=0; i<m; i++) {
910cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
911bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
912bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
91336db0b34SBarry Smith         if (PetscRealPart(a->a[j]) >=  0.) continue;
914b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
915cddf8d76SBarry Smith       }
916cddf8d76SBarry Smith     }
917b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
918cddf8d76SBarry Smith     for (i=0; i<m; i++) {
919cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
920bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
921bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
922cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
923b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
924cddf8d76SBarry Smith       }
925cddf8d76SBarry Smith     }
926b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
927cddf8d76SBarry Smith     for (i=0; i<m; i++) {
928cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
929bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
930bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
93136db0b34SBarry Smith         if (PetscRealPart(a->a[j]) <=  0.) continue;
932b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
933416022c9SBarry Smith       }
934416022c9SBarry Smith     }
935383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
9360513a670SBarry Smith   } else {
9370513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
9380513a670SBarry Smith     /* first determine max of all nonzero values */
939b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
940383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
941b0a32e0cSBarry Smith     PetscDraw popup;
9420513a670SBarry Smith 
9430513a670SBarry Smith     for (i=0; i<nz; i++) {
9440513a670SBarry Smith       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
9450513a670SBarry Smith     }
946383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
947b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
94845f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
949383922c3SLisandro Dalcin 
950383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
9510513a670SBarry Smith     for (i=0; i<m; i++) {
952383922c3SLisandro Dalcin       y_l = m - i - 1.0;
953383922c3SLisandro Dalcin       y_r = y_l + 1.0;
954bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
955383922c3SLisandro Dalcin         x_l = a->j[j];
956383922c3SLisandro Dalcin         x_r = x_l + 1.0;
957b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(a->a[count]),minv,maxv);
958b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
9590513a670SBarry Smith         count++;
9600513a670SBarry Smith       }
9610513a670SBarry Smith     }
962383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
9630513a670SBarry Smith   }
964480ef9eaSBarry Smith   PetscFunctionReturn(0);
965480ef9eaSBarry Smith }
966cddf8d76SBarry Smith 
9679804daf3SBarry Smith #include <petscdraw.h>
968dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
969480ef9eaSBarry Smith {
970dfbe8321SBarry Smith   PetscErrorCode ierr;
971b0a32e0cSBarry Smith   PetscDraw      draw;
97236db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
973ace3abfcSBarry Smith   PetscBool      isnull;
974480ef9eaSBarry Smith 
975480ef9eaSBarry Smith   PetscFunctionBegin;
976b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
977b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
978480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
979480ef9eaSBarry Smith 
980d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
981480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
982b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
983832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
984b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
9850298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
986832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
9873a40ed3dSBarry Smith   PetscFunctionReturn(0);
988416022c9SBarry Smith }
989416022c9SBarry Smith 
990dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
991416022c9SBarry Smith {
992dfbe8321SBarry Smith   PetscErrorCode ierr;
993ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
994416022c9SBarry Smith 
9953a40ed3dSBarry Smith   PetscFunctionBegin;
996251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
997251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
998251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
999c45a1595SBarry Smith   if (iascii) {
10003a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
10010f5bd95cSBarry Smith   } else if (isbinary) {
10023a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
10030f5bd95cSBarry Smith   } else if (isdraw) {
10043a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
100511aeaf0aSBarry Smith   }
10064108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
10073a40ed3dSBarry Smith   PetscFunctionReturn(0);
100817ab2063SBarry Smith }
100919bcc07fSBarry Smith 
1010dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
101117ab2063SBarry Smith {
1012416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
10136849ba73SBarry Smith   PetscErrorCode ierr;
1014580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1015d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
101654f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
10173447b6efSHong Zhang   PetscReal      ratio  = 0.6;
101817ab2063SBarry Smith 
10193a40ed3dSBarry Smith   PetscFunctionBegin;
10203a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1021071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1022071fcb05SBarry Smith   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) PetscFunctionReturn(0);
102317ab2063SBarry Smith 
102443ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
102517ab2063SBarry Smith   for (i=1; i<m; i++) {
1026416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
102717ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
102894a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
102917ab2063SBarry Smith     if (fshift) {
1030bfeeae90SHong Zhang       ip = aj + ai[i];
1031bfeeae90SHong Zhang       ap = aa + ai[i];
103217ab2063SBarry Smith       N  = ailen[i];
1033580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1034580bdb30SBarry Smith       if (!A->structure_only) {
1035580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
103617ab2063SBarry Smith       }
103717ab2063SBarry Smith     }
103817ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
103917ab2063SBarry Smith   }
104017ab2063SBarry Smith   if (m) {
104117ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
104217ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
104317ab2063SBarry Smith   }
10447b083b7cSBarry Smith 
104517ab2063SBarry Smith   /* reset ilen and imax for each row */
10467b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1047396832f4SHong Zhang   if (A->structure_only) {
1048071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1049071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1050396832f4SHong Zhang   } else { /* !A->structure_only */
105117ab2063SBarry Smith     for (i=0; i<m; i++) {
105217ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
10537b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
105417ab2063SBarry Smith     }
1055396832f4SHong Zhang   }
1056bfeeae90SHong Zhang   a->nz = ai[m];
105765e19b50SBarry 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);
105817ab2063SBarry Smith 
105909f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1060d0f46423SBarry 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);
1061ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1062ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
10632205254eSKarl Rupp 
10648e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1065dd5f02e7SSatish Balay   a->reallocs         = 0;
10666712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
106736db0b34SBarry Smith   a->rmax             = rmax;
10684e220ebcSLois Curfman McInnes 
1069396832f4SHong Zhang   if (!A->structure_only) {
107011e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1071396832f4SHong Zhang   }
10724108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
10733a40ed3dSBarry Smith   PetscFunctionReturn(0);
107417ab2063SBarry Smith }
107517ab2063SBarry Smith 
107699cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
107799cafbc1SBarry Smith {
107899cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
107999cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
108054f21887SBarry Smith   MatScalar      *aa = a->a;
1081acf2f550SJed Brown   PetscErrorCode ierr;
108299cafbc1SBarry Smith 
108399cafbc1SBarry Smith   PetscFunctionBegin;
108499cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
1085acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
108699cafbc1SBarry Smith   PetscFunctionReturn(0);
108799cafbc1SBarry Smith }
108899cafbc1SBarry Smith 
108999cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
109099cafbc1SBarry Smith {
109199cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
109299cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
109354f21887SBarry Smith   MatScalar      *aa = a->a;
1094acf2f550SJed Brown   PetscErrorCode ierr;
109599cafbc1SBarry Smith 
109699cafbc1SBarry Smith   PetscFunctionBegin;
109799cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
1098acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
109999cafbc1SBarry Smith   PetscFunctionReturn(0);
110099cafbc1SBarry Smith }
110199cafbc1SBarry Smith 
1102dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
110317ab2063SBarry Smith {
1104416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1105dfbe8321SBarry Smith   PetscErrorCode ierr;
11063a40ed3dSBarry Smith 
11073a40ed3dSBarry Smith   PetscFunctionBegin;
1108580bdb30SBarry Smith   ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
1109acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
11103a40ed3dSBarry Smith   PetscFunctionReturn(0);
111117ab2063SBarry Smith }
1112416022c9SBarry Smith 
1113dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
111417ab2063SBarry Smith {
1115416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1116dfbe8321SBarry Smith   PetscErrorCode ierr;
1117d5d45c9bSBarry Smith 
11183a40ed3dSBarry Smith   PetscFunctionBegin;
1119aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1120d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
112117ab2063SBarry Smith #endif
1122e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
11236bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
11246bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
112505b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1126d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1127071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1128071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1129846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
113071f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
113105b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
11326bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
113305b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
11346bf464f9SBarry Smith   ierr = ISColoringDestroy(&a->coloring);CHKERRQ(ierr);
1135cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
11360b7e3e3dSHong Zhang   ierr = PetscFree(a->matmult_abdense);CHKERRQ(ierr);
1137a30b2313SHong Zhang 
11384108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1139bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1140901853e0SKris Buschelman 
1141dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1142bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1143bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1144bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1145bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1146bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1147bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
1148af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1149af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1150af8000cdSHong Zhang #endif
115163c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
115263c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
11533dad0653Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMatMult_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
115463c07aadSStefano Zampini #endif
1155b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1156c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1157c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1158bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1159bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1160846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1161bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1162bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
116375d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_is_seqaij_C",NULL);CHKERRQ(ierr);
11643a40ed3dSBarry Smith   PetscFunctionReturn(0);
116517ab2063SBarry Smith }
116617ab2063SBarry Smith 
1167ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
116817ab2063SBarry Smith {
1169416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
11704846f1f5SKris Buschelman   PetscErrorCode ierr;
11713a40ed3dSBarry Smith 
11723a40ed3dSBarry Smith   PetscFunctionBegin;
1173a65d3064SKris Buschelman   switch (op) {
1174a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
11754e0d8c25SBarry Smith     a->roworiented = flg;
1176a65d3064SKris Buschelman     break;
1177a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1178a9817697SBarry Smith     a->keepnonzeropattern = flg;
1179a65d3064SKris Buschelman     break;
1180512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1181512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1182a65d3064SKris Buschelman     break;
1183a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
11844e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1185a65d3064SKris Buschelman     break;
1186a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
11874e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1188a65d3064SKris Buschelman     break;
118928b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
119028b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
119128b2fa4aSMatthew Knepley     break;
1192a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
11934e0d8c25SBarry Smith     a->ignorezeroentries = flg;
11940df259c2SBarry Smith     break;
11953d472b54SHong Zhang   case MAT_SPD:
1196b1646e73SJed Brown   case MAT_SYMMETRIC:
1197b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1198b1646e73SJed Brown   case MAT_HERMITIAN:
1199b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1200957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
12015021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
12025021d80fSJed Brown     break;
12034e0d8c25SBarry Smith   case MAT_NEW_DIAGONALS:
1204a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1205a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1206290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1207a65d3064SKris Buschelman     break;
1208b87ac2d8SJed Brown   case MAT_USE_INODES:
1209b87ac2d8SJed Brown     /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */
1210b87ac2d8SJed Brown     break;
1211c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1212c10200c1SHong Zhang     A->submat_singleis = flg;
1213c10200c1SHong Zhang     break;
1214071fcb05SBarry Smith   case MAT_SORTED_FULL:
1215071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1216071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1217071fcb05SBarry Smith     break;
1218a65d3064SKris Buschelman   default:
1219e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1220a65d3064SKris Buschelman   }
12214108e4d5SBarry Smith   ierr = MatSetOption_SeqAIJ_Inode(A,op,flg);CHKERRQ(ierr);
12223a40ed3dSBarry Smith   PetscFunctionReturn(0);
122317ab2063SBarry Smith }
122417ab2063SBarry Smith 
1225dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
122617ab2063SBarry Smith {
1227416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
12286849ba73SBarry Smith   PetscErrorCode ierr;
1229fdc842d1SBarry Smith   PetscInt       i,j,n,*ai=a->i,*aj=a->j;
1230fdc842d1SBarry Smith   PetscScalar    *aa=a->a,*x;
123117ab2063SBarry Smith 
12323a40ed3dSBarry Smith   PetscFunctionBegin;
1233d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1234e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
123535e7444dSHong Zhang 
1236d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1237d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1238fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
12392c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1240fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
124135e7444dSHong Zhang     PetscFunctionReturn(0);
124235e7444dSHong Zhang   }
124335e7444dSHong Zhang 
1244fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
124535e7444dSHong Zhang   for (i=0; i<n; i++) {
1246fdc842d1SBarry Smith     x[i] = 0.0;
124735e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
124835e7444dSHong Zhang       if (aj[j] == i) {
124935e7444dSHong Zhang         x[i] = aa[j];
125017ab2063SBarry Smith         break;
125117ab2063SBarry Smith       }
125217ab2063SBarry Smith     }
125317ab2063SBarry Smith   }
1254fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
12553a40ed3dSBarry Smith   PetscFunctionReturn(0);
125617ab2063SBarry Smith }
125717ab2063SBarry Smith 
1258c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1259dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
126017ab2063SBarry Smith {
1261416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1262d9ca1df4SBarry Smith   PetscScalar       *y;
1263d9ca1df4SBarry Smith   const PetscScalar *x;
1264dfbe8321SBarry Smith   PetscErrorCode    ierr;
1265d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
12665c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1267d9ca1df4SBarry Smith   const MatScalar   *v;
1268a77337e4SBarry Smith   PetscScalar       alpha;
1269d9ca1df4SBarry Smith   PetscInt          n,i,j;
1270d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
12713447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1272ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
12735c897100SBarry Smith #endif
127417ab2063SBarry Smith 
12753a40ed3dSBarry Smith   PetscFunctionBegin;
12762e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1277d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
12781ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
12795c897100SBarry Smith 
12805c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1281bfeeae90SHong Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
12825c897100SBarry Smith #else
12833447b6efSHong Zhang   if (usecprow) {
12843447b6efSHong Zhang     m    = cprow.nrows;
12853447b6efSHong Zhang     ii   = cprow.i;
12867b2bb3b9SHong Zhang     ridx = cprow.rindex;
12873447b6efSHong Zhang   } else {
12883447b6efSHong Zhang     ii = a->i;
12893447b6efSHong Zhang   }
129017ab2063SBarry Smith   for (i=0; i<m; i++) {
12913447b6efSHong Zhang     idx = a->j + ii[i];
12923447b6efSHong Zhang     v   = a->a + ii[i];
12933447b6efSHong Zhang     n   = ii[i+1] - ii[i];
12943447b6efSHong Zhang     if (usecprow) {
12957b2bb3b9SHong Zhang       alpha = x[ridx[i]];
12963447b6efSHong Zhang     } else {
129717ab2063SBarry Smith       alpha = x[i];
12983447b6efSHong Zhang     }
129904fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
130017ab2063SBarry Smith   }
13015c897100SBarry Smith #endif
1302dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1303d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
13041ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
13053a40ed3dSBarry Smith   PetscFunctionReturn(0);
130617ab2063SBarry Smith }
130717ab2063SBarry Smith 
1308dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
13095c897100SBarry Smith {
1310dfbe8321SBarry Smith   PetscErrorCode ierr;
13115c897100SBarry Smith 
13125c897100SBarry Smith   PetscFunctionBegin;
1313170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
13145c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
13155c897100SBarry Smith   PetscFunctionReturn(0);
13165c897100SBarry Smith }
13175c897100SBarry Smith 
1318c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
131978b84d54SShri Abhyankar 
1320dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
132117ab2063SBarry Smith {
1322416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1323d9fead3dSBarry Smith   PetscScalar       *y;
132454f21887SBarry Smith   const PetscScalar *x;
132554f21887SBarry Smith   const MatScalar   *aa;
1326dfbe8321SBarry Smith   PetscErrorCode    ierr;
1327003131ecSBarry Smith   PetscInt          m=A->rmap->n;
13280298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
13297b083b7cSBarry Smith   PetscInt          n,i;
1330362ced78SSatish Balay   PetscScalar       sum;
1331ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
133217ab2063SBarry Smith 
1333b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
133497952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1335fee21e36SBarry Smith #endif
1336fee21e36SBarry Smith 
13373a40ed3dSBarry Smith   PetscFunctionBegin;
13383649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
13391ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1340416022c9SBarry Smith   ii   = a->i;
13414eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1342580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
134397952fefSHong Zhang     m    = a->compressedrow.nrows;
134497952fefSHong Zhang     ii   = a->compressedrow.i;
134597952fefSHong Zhang     ridx = a->compressedrow.rindex;
134697952fefSHong Zhang     for (i=0; i<m; i++) {
134797952fefSHong Zhang       n           = ii[i+1] - ii[i];
134897952fefSHong Zhang       aj          = a->j + ii[i];
134997952fefSHong Zhang       aa          = a->a + ii[i];
135097952fefSHong Zhang       sum         = 0.0;
1351003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1352003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
135397952fefSHong Zhang       y[*ridx++] = sum;
135497952fefSHong Zhang     }
135597952fefSHong Zhang   } else { /* do not use compressed row format */
1356b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
13573d3eaba7SBarry Smith     aj   = a->j;
13583d3eaba7SBarry Smith     aa   = a->a;
1359b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1360b05257ddSBarry Smith #else
136117ab2063SBarry Smith     for (i=0; i<m; i++) {
1362003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1363003131ecSBarry Smith       aj          = a->j + ii[i];
1364003131ecSBarry Smith       aa          = a->a + ii[i];
136517ab2063SBarry Smith       sum         = 0.0;
1366003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
136717ab2063SBarry Smith       y[i] = sum;
136817ab2063SBarry Smith     }
13698d195f9aSBarry Smith #endif
1370b05257ddSBarry Smith   }
13717b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
13723649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
13731ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
13743a40ed3dSBarry Smith   PetscFunctionReturn(0);
137517ab2063SBarry Smith }
137617ab2063SBarry Smith 
1377b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1378b434eb95SMatthew G. Knepley {
1379b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1380b434eb95SMatthew G. Knepley   PetscScalar       *y;
1381b434eb95SMatthew G. Knepley   const PetscScalar *x;
1382b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1383b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1384b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1385b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1386b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1387b434eb95SMatthew G. Knepley   PetscScalar       sum;
1388b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1389b434eb95SMatthew G. Knepley 
1390b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1391b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1392b434eb95SMatthew G. Knepley #endif
1393b434eb95SMatthew G. Knepley 
1394b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1395b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1396b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1397b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1398b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1399b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1400b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1401b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1402b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1403b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1404b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1405b434eb95SMatthew G. Knepley       sum         = 0.0;
1406b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1407b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1408b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1409b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1410b434eb95SMatthew G. Knepley     }
1411b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
14123d3eaba7SBarry Smith     ii = a->i;
1413b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1414b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1415b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1416b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1417b434eb95SMatthew G. Knepley       sum         = 0.0;
1418b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1419b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1420b434eb95SMatthew G. Knepley       y[i] = sum;
1421b434eb95SMatthew G. Knepley     }
1422b434eb95SMatthew G. Knepley   }
1423b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1424b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1425b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1426b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1427b434eb95SMatthew G. Knepley }
1428b434eb95SMatthew G. Knepley 
1429b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1430b434eb95SMatthew G. Knepley {
1431b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1432b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1433b434eb95SMatthew G. Knepley   const PetscScalar *x;
1434b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1435b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1436b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1437b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1438b434eb95SMatthew G. Knepley   PetscScalar       sum;
1439b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1440b434eb95SMatthew G. Knepley 
1441b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1442b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1443d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1444b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1445b434eb95SMatthew G. Knepley     if (zz != yy) {
1446580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1447b434eb95SMatthew G. Knepley     }
1448b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1449b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1450b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1451b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1452b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1453b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1454b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1455b434eb95SMatthew G. Knepley       sum = y[*ridx];
1456b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1457b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1458b434eb95SMatthew G. Knepley     }
1459b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
14603d3eaba7SBarry Smith     ii = a->i;
1461b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1462b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1463b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1464b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1465b434eb95SMatthew G. Knepley       sum = y[i];
1466b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1467b434eb95SMatthew G. Knepley       z[i] = sum;
1468b434eb95SMatthew G. Knepley     }
1469b434eb95SMatthew G. Knepley   }
1470b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1471b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1472d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1473b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1474b434eb95SMatthew G. Knepley }
1475b434eb95SMatthew G. Knepley 
1476c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1477dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
147817ab2063SBarry Smith {
1479416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1480f15663dcSBarry Smith   PetscScalar       *y,*z;
1481f15663dcSBarry Smith   const PetscScalar *x;
148254f21887SBarry Smith   const MatScalar   *aa;
1483dfbe8321SBarry Smith   PetscErrorCode    ierr;
1484d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1485d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1486362ced78SSatish Balay   PetscScalar       sum;
1487ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
14889ea0dfa2SSatish Balay 
14893a40ed3dSBarry Smith   PetscFunctionBegin;
1490f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1491d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
14924eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
14934eb6d288SHong Zhang     if (zz != yy) {
1494580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
14954eb6d288SHong Zhang     }
149697952fefSHong Zhang     m    = a->compressedrow.nrows;
149797952fefSHong Zhang     ii   = a->compressedrow.i;
149897952fefSHong Zhang     ridx = a->compressedrow.rindex;
149997952fefSHong Zhang     for (i=0; i<m; i++) {
150097952fefSHong Zhang       n   = ii[i+1] - ii[i];
150197952fefSHong Zhang       aj  = a->j + ii[i];
150297952fefSHong Zhang       aa  = a->a + ii[i];
150397952fefSHong Zhang       sum = y[*ridx];
1504f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
150597952fefSHong Zhang       z[*ridx++] = sum;
150697952fefSHong Zhang     }
150797952fefSHong Zhang   } else { /* do not use compressed row format */
15083d3eaba7SBarry Smith     ii = a->i;
1509f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
15103d3eaba7SBarry Smith     aj = a->j;
15113d3eaba7SBarry Smith     aa = a->a;
1512f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1513f15663dcSBarry Smith #else
151417ab2063SBarry Smith     for (i=0; i<m; i++) {
1515f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1516f15663dcSBarry Smith       aj  = a->j + ii[i];
1517f15663dcSBarry Smith       aa  = a->a + ii[i];
151817ab2063SBarry Smith       sum = y[i];
1519f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
152017ab2063SBarry Smith       z[i] = sum;
152117ab2063SBarry Smith     }
152202ab625aSSatish Balay #endif
1523f15663dcSBarry Smith   }
1524dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1525f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1526d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
15273a40ed3dSBarry Smith   PetscFunctionReturn(0);
152817ab2063SBarry Smith }
152917ab2063SBarry Smith 
153017ab2063SBarry Smith /*
153117ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
153217ab2063SBarry Smith */
1533dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
153417ab2063SBarry Smith {
1535416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
15366849ba73SBarry Smith   PetscErrorCode ierr;
1537d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
153817ab2063SBarry Smith 
15393a40ed3dSBarry Smith   PetscFunctionBegin;
154009f38230SBarry Smith   if (!a->diag) {
1541785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
15423bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
154309f38230SBarry Smith   }
1544d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
154509f38230SBarry Smith     a->diag[i] = a->i[i+1];
1546bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1547bfeeae90SHong Zhang       if (a->j[j] == i) {
154809f38230SBarry Smith         a->diag[i] = j;
154917ab2063SBarry Smith         break;
155017ab2063SBarry Smith       }
155117ab2063SBarry Smith     }
155217ab2063SBarry Smith   }
15533a40ed3dSBarry Smith   PetscFunctionReturn(0);
155417ab2063SBarry Smith }
155517ab2063SBarry Smith 
155661ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
155761ecd0c6SBarry Smith {
155861ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
155961ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
156061ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
156161ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
156261ecd0c6SBarry Smith   PetscErrorCode    ierr;
156361ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
156461ecd0c6SBarry Smith 
156561ecd0c6SBarry Smith   PetscFunctionBegin;
156661ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
156761ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
156861ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
156961ecd0c6SBarry Smith     PetscFunctionReturn(0);
157061ecd0c6SBarry Smith   }
157161ecd0c6SBarry Smith 
157261ecd0c6SBarry Smith   if (a->diagonaldense) {
157361ecd0c6SBarry Smith     cnt = 0;
157461ecd0c6SBarry Smith   } else {
157561ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
157661ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
157761ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
157861ecd0c6SBarry Smith         cnt++;
157961ecd0c6SBarry Smith         mdiag[i] = 1;
158061ecd0c6SBarry Smith       }
158161ecd0c6SBarry Smith     }
158261ecd0c6SBarry Smith   }
158361ecd0c6SBarry Smith   if (!cnt) {
158461ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
158561ecd0c6SBarry Smith   } else {
1586b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1587b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
158861ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
158961ecd0c6SBarry Smith 
159061ecd0c6SBarry Smith     a->a = NULL;
159161ecd0c6SBarry Smith     a->j = NULL;
159261ecd0c6SBarry Smith     a->i = NULL;
159361ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
159461ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
159561ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1596447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
159761ecd0c6SBarry Smith     }
159861ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
159961ecd0c6SBarry Smith 
160061ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
160161ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
160261ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1603447d62f5SStefano Zampini       if (i < A->cmap->n) {
160461ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
160561ecd0c6SBarry Smith       }
1606447d62f5SStefano Zampini     }
160761ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
160861ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
160961ecd0c6SBarry Smith     if (singlemalloc) {
161061ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
161161ecd0c6SBarry Smith     } else {
161261ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
161361ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
161461ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
161561ecd0c6SBarry Smith     }
161661ecd0c6SBarry Smith   }
161761ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
161861ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
161961ecd0c6SBarry Smith   PetscFunctionReturn(0);
162061ecd0c6SBarry Smith }
162161ecd0c6SBarry Smith 
1622be5855fcSBarry Smith /*
1623be5855fcSBarry Smith      Checks for missing diagonals
1624be5855fcSBarry Smith */
1625ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1626be5855fcSBarry Smith {
1627be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
16287734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1629994fe344SLisandro Dalcin   PetscErrorCode ierr;
1630be5855fcSBarry Smith 
1631be5855fcSBarry Smith   PetscFunctionBegin;
163209f38230SBarry Smith   *missing = PETSC_FALSE;
16337734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
163409f38230SBarry Smith     *missing = PETSC_TRUE;
163509f38230SBarry Smith     if (d) *d = 0;
1636994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
163709f38230SBarry Smith   } else {
163801445905SHong Zhang     PetscInt n;
163901445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1640f1e2ffcdSBarry Smith     diag = a->diag;
164101445905SHong Zhang     for (i=0; i<n; i++) {
16427734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
164309f38230SBarry Smith         *missing = PETSC_TRUE;
164409f38230SBarry Smith         if (d) *d = i;
1645994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1646358d2f5dSShri Abhyankar         break;
164709f38230SBarry Smith       }
1648be5855fcSBarry Smith     }
1649be5855fcSBarry Smith   }
1650be5855fcSBarry Smith   PetscFunctionReturn(0);
1651be5855fcSBarry Smith }
1652be5855fcSBarry Smith 
16530da83c2eSBarry Smith #include <petscblaslapack.h>
16540da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
16550da83c2eSBarry Smith 
16560da83c2eSBarry Smith /*
16570da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
16580da83c2eSBarry Smith */
16590da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
16600da83c2eSBarry Smith {
16610da83c2eSBarry Smith   PetscErrorCode  ierr;
16620da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
16630da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
16640da83c2eSBarry Smith   const PetscReal shift = 0.0;
16650da83c2eSBarry Smith   PetscInt        ipvt[5];
16660da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
16670da83c2eSBarry Smith 
16680da83c2eSBarry Smith   PetscFunctionBegin;
16690da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
16700da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
16710da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
16720da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
16730da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
16740da83c2eSBarry Smith   }
16750da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
16760da83c2eSBarry Smith   if (bsizemax > 7) {
16770da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
16780da83c2eSBarry Smith   }
16790da83c2eSBarry Smith   ncnt = 0;
16800da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
16810da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
16820da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
16830da83c2eSBarry Smith     switch (bsizes[i]) {
16840da83c2eSBarry Smith     case 1:
16850da83c2eSBarry Smith       *diag = 1.0/(*diag);
16860da83c2eSBarry Smith       break;
16870da83c2eSBarry Smith     case 2:
16880da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
16890da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
16900da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
16910da83c2eSBarry Smith       break;
16920da83c2eSBarry Smith     case 3:
16930da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
16940da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
16950da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
16960da83c2eSBarry Smith       break;
16970da83c2eSBarry Smith     case 4:
16980da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
16990da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17000da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
17010da83c2eSBarry Smith       break;
17020da83c2eSBarry Smith     case 5:
17030da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17040da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17050da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
17060da83c2eSBarry Smith       break;
17070da83c2eSBarry Smith     case 6:
17080da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17090da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17100da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
17110da83c2eSBarry Smith       break;
17120da83c2eSBarry Smith     case 7:
17130da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17140da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17150da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
17160da83c2eSBarry Smith       break;
17170da83c2eSBarry Smith     default:
17180da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17190da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17200da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
17210da83c2eSBarry Smith     }
17220da83c2eSBarry Smith     ncnt   += bsizes[i];
17230da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
17240da83c2eSBarry Smith   }
17250da83c2eSBarry Smith   if (bsizemax > 7) {
17260da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
17270da83c2eSBarry Smith   }
17280da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
17290da83c2eSBarry Smith   PetscFunctionReturn(0);
17300da83c2eSBarry Smith }
17310da83c2eSBarry Smith 
1732422a814eSBarry Smith /*
1733422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1734422a814eSBarry Smith */
17357087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
173671f1c65dSBarry Smith {
173771f1c65dSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*) A->data;
173871f1c65dSBarry Smith   PetscErrorCode ierr;
1739d0f46423SBarry Smith   PetscInt       i,*diag,m = A->rmap->n;
174054f21887SBarry Smith   MatScalar      *v = a->a;
174154f21887SBarry Smith   PetscScalar    *idiag,*mdiag;
174271f1c65dSBarry Smith 
174371f1c65dSBarry Smith   PetscFunctionBegin;
174471f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
174571f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
174671f1c65dSBarry Smith   diag = a->diag;
174771f1c65dSBarry Smith   if (!a->idiag) {
1748dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
17493bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr);
175071f1c65dSBarry Smith     v    = a->a;
175171f1c65dSBarry Smith   }
175271f1c65dSBarry Smith   mdiag = a->mdiag;
175371f1c65dSBarry Smith   idiag = a->idiag;
175471f1c65dSBarry Smith 
1755422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
175671f1c65dSBarry Smith     for (i=0; i<m; i++) {
175771f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1758899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1759899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1760899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
17617b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17627b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
17637b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1764a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1765899639b0SHong Zhang       }
176671f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
176771f1c65dSBarry Smith     }
176871f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
176971f1c65dSBarry Smith   } else {
177071f1c65dSBarry Smith     for (i=0; i<m; i++) {
177171f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
177271f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
177371f1c65dSBarry Smith     }
1774dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
177571f1c65dSBarry Smith   }
177671f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
177771f1c65dSBarry Smith   PetscFunctionReturn(0);
177871f1c65dSBarry Smith }
177971f1c65dSBarry Smith 
1780c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
178141f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
178217ab2063SBarry Smith {
1783416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1784e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
17853d3eaba7SBarry Smith   const MatScalar   *v,*idiag=0,*mdiag;
178654f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1787dfbe8321SBarry Smith   PetscErrorCode    ierr;
17883d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
178997f1f81fSBarry Smith   const PetscInt    *idx,*diag;
179017ab2063SBarry Smith 
17913a40ed3dSBarry Smith   PetscFunctionBegin;
1792b965ef7fSBarry Smith   its = its*lits;
179391723122SBarry Smith 
179471f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
179571f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
179671f1c65dSBarry Smith   a->fshift = fshift;
179771f1c65dSBarry Smith   a->omega  = omega;
1798ed480e8bSBarry Smith 
179971f1c65dSBarry Smith   diag  = a->diag;
180071f1c65dSBarry Smith   t     = a->ssor_work;
1801ed480e8bSBarry Smith   idiag = a->idiag;
180271f1c65dSBarry Smith   mdiag = a->mdiag;
1803ed480e8bSBarry Smith 
18041ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
18053649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
1806ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
180717ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
180817ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1809ed480e8bSBarry Smith     bs = b;
181017ab2063SBarry Smith     for (i=0; i<m; i++) {
181171f1c65dSBarry Smith       d   = fshift + mdiag[i];
1812416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1813ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
1814ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
181517ab2063SBarry Smith       sum = b[i]*d/omega;
1816003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
181717ab2063SBarry Smith       x[i] = sum;
181817ab2063SBarry Smith     }
18191ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
18203649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1821efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
18223a40ed3dSBarry Smith     PetscFunctionReturn(0);
182317ab2063SBarry Smith   }
1824c783ea89SBarry Smith 
18252205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
18262205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
182717ab2063SBarry Smith     /* Let  A = L + U + D; where L is lower trianglar,
1828887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
182917ab2063SBarry Smith 
183017ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
183117ab2063SBarry Smith 
1832887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
183317ab2063SBarry Smith     */
183417ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
183517ab2063SBarry Smith 
183617ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
183717ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
1838416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1839ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
1840ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
184117ab2063SBarry Smith       sum = b[i];
1842e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
1843ed480e8bSBarry Smith       x[i] = sum*idiag[i];
184417ab2063SBarry Smith     }
184517ab2063SBarry Smith 
184617ab2063SBarry Smith     /*  t = b - (2*E - D)x */
1847416022c9SBarry Smith     v = a->a;
18482205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
184917ab2063SBarry Smith 
185017ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
1851ed480e8bSBarry Smith     ts   = t;
1852416022c9SBarry Smith     diag = a->diag;
185317ab2063SBarry Smith     for (i=0; i<m; i++) {
1854416022c9SBarry Smith       n   = diag[i] - a->i[i];
1855ed480e8bSBarry Smith       idx = a->j + a->i[i];
1856ed480e8bSBarry Smith       v   = a->a + a->i[i];
185717ab2063SBarry Smith       sum = t[i];
1858003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
1859ed480e8bSBarry Smith       t[i] = sum*idiag[i];
1860733d66baSBarry Smith       /*  x = x + t */
1861733d66baSBarry Smith       x[i] += t[i];
186217ab2063SBarry Smith     }
186317ab2063SBarry Smith 
1864dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
18651ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
18663649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
18673a40ed3dSBarry Smith     PetscFunctionReturn(0);
186817ab2063SBarry Smith   }
186917ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
187017ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
187117ab2063SBarry Smith       for (i=0; i<m; i++) {
1872416022c9SBarry Smith         n   = diag[i] - a->i[i];
1873ed480e8bSBarry Smith         idx = a->j + a->i[i];
1874ed480e8bSBarry Smith         v   = a->a + a->i[i];
187517ab2063SBarry Smith         sum = b[i];
1876e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
18775c99c7daSBarry Smith         t[i] = sum;
1878ed480e8bSBarry Smith         x[i] = sum*idiag[i];
187917ab2063SBarry Smith       }
18805c99c7daSBarry Smith       xb   = t;
1881efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
18823a40ed3dSBarry Smith     } else xb = b;
188317ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
188417ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
1885416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
1886ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
1887ed480e8bSBarry Smith         v   = a->a + diag[i] + 1;
188817ab2063SBarry Smith         sum = xb[i];
1889e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
18905c99c7daSBarry Smith         if (xb == b) {
1891ed480e8bSBarry Smith           x[i] = sum*idiag[i];
18925c99c7daSBarry Smith         } else {
1893b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
189417ab2063SBarry Smith         }
18955c99c7daSBarry Smith       }
1896b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
189717ab2063SBarry Smith     }
189817ab2063SBarry Smith     its--;
189917ab2063SBarry Smith   }
190017ab2063SBarry Smith   while (its--) {
190117ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
190217ab2063SBarry Smith       for (i=0; i<m; i++) {
1903b19a5dc2SMark Adams         /* lower */
1904b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
1905ed480e8bSBarry Smith         idx = a->j + a->i[i];
1906ed480e8bSBarry Smith         v   = a->a + a->i[i];
190717ab2063SBarry Smith         sum = b[i];
1908e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1909b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
1910b19a5dc2SMark Adams         /* upper */
1911b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
1912b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
1913b19a5dc2SMark Adams         v   = a->a + diag[i] + 1;
1914b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1915b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
191617ab2063SBarry Smith       }
1917b19a5dc2SMark Adams       xb   = t;
19189f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1919b19a5dc2SMark Adams     } else xb = b;
192017ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
192117ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
1922b19a5dc2SMark Adams         sum = xb[i];
1923b19a5dc2SMark Adams         if (xb == b) {
1924b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
1925416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
1926ed480e8bSBarry Smith           idx = a->j + a->i[i];
1927ed480e8bSBarry Smith           v   = a->a + a->i[i];
1928e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
1929ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1930b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
1931b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
1932b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
1933b19a5dc2SMark Adams           v   = a->a + diag[i] + 1;
1934b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
1935b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
193617ab2063SBarry Smith         }
1937b19a5dc2SMark Adams       }
1938b19a5dc2SMark Adams       if (xb == b) {
19399f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1940b19a5dc2SMark Adams       } else {
1941b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
1942b19a5dc2SMark Adams       }
194317ab2063SBarry Smith     }
194417ab2063SBarry Smith   }
19451ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
19463649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1947365a8a9eSBarry Smith   PetscFunctionReturn(0);
194817ab2063SBarry Smith }
194917ab2063SBarry Smith 
19502af78befSBarry Smith 
1951dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
195217ab2063SBarry Smith {
1953416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
19544e220ebcSLois Curfman McInnes 
19553a40ed3dSBarry Smith   PetscFunctionBegin;
19564e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
19574e220ebcSLois Curfman McInnes   info->nz_allocated = (double)a->maxnz;
19584e220ebcSLois Curfman McInnes   info->nz_used      = (double)a->nz;
19594e220ebcSLois Curfman McInnes   info->nz_unneeded  = (double)(a->maxnz - a->nz);
19604e220ebcSLois Curfman McInnes   info->assemblies   = (double)A->num_ass;
19618e58a170SBarry Smith   info->mallocs      = (double)A->info.mallocs;
19627adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
1963d5f3da31SBarry Smith   if (A->factortype) {
19644e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
19654e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
19664e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
19674e220ebcSLois Curfman McInnes   } else {
19684e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
19694e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
19704e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
19714e220ebcSLois Curfman McInnes   }
19723a40ed3dSBarry Smith   PetscFunctionReturn(0);
197317ab2063SBarry Smith }
197417ab2063SBarry Smith 
19752b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
197617ab2063SBarry Smith {
1977416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1978c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
19796849ba73SBarry Smith   PetscErrorCode    ierr;
198097b48c8fSBarry Smith   const PetscScalar *xx;
198197b48c8fSBarry Smith   PetscScalar       *bb;
1982c7da8527SEric Chamberland   PetscInt          d = 0;
198317ab2063SBarry Smith 
19843a40ed3dSBarry Smith   PetscFunctionBegin;
198597b48c8fSBarry Smith   if (x && b) {
198697b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
198797b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
198897b48c8fSBarry Smith     for (i=0; i<N; i++) {
198997b48c8fSBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1990447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
199197b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
199297b48c8fSBarry Smith     }
199397b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
199497b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
199597b48c8fSBarry Smith   }
199697b48c8fSBarry Smith 
1997a9817697SBarry Smith   if (a->keepnonzeropattern) {
1998f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
1999e32f2f54SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2000580bdb30SBarry Smith       ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2001f1e2ffcdSBarry Smith     }
2002f4df32b1SMatthew Knepley     if (diag != 0.0) {
2003c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2004c7da8527SEric Chamberland         d = rows[i];
2005447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2006c7da8527SEric 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);
2007c7da8527SEric Chamberland       }
2008f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2009447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2010f4df32b1SMatthew Knepley         a->a[a->diag[rows[i]]] = diag;
2011f1e2ffcdSBarry Smith       }
2012f1e2ffcdSBarry Smith     }
2013f1e2ffcdSBarry Smith   } else {
2014f4df32b1SMatthew Knepley     if (diag != 0.0) {
201517ab2063SBarry Smith       for (i=0; i<N; i++) {
2016e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
20177ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2018447d62f5SStefano Zampini 	  if (rows[i] >= A->cmap->n) {
2019447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2020447d62f5SStefano Zampini           } else {
2021416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
2022f4df32b1SMatthew Knepley             a->a[a->i[rows[i]]] = diag;
2023bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2024447d62f5SStefano Zampini           }
2025447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2026f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
202717ab2063SBarry Smith         }
202817ab2063SBarry Smith       }
20293a40ed3dSBarry Smith     } else {
203017ab2063SBarry Smith       for (i=0; i<N; i++) {
2031e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2032416022c9SBarry Smith         a->ilen[rows[i]] = 0;
203317ab2063SBarry Smith       }
203417ab2063SBarry Smith     }
2035e56f5c9eSBarry Smith     A->nonzerostate++;
2036f1e2ffcdSBarry Smith   }
20374099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20383a40ed3dSBarry Smith   PetscFunctionReturn(0);
203917ab2063SBarry Smith }
204017ab2063SBarry Smith 
20416e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
20426e169961SBarry Smith {
20436e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
20446e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
20456e169961SBarry Smith   PetscErrorCode    ierr;
20462b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
20476e169961SBarry Smith   const PetscScalar *xx;
20486e169961SBarry Smith   PetscScalar       *bb;
20496e169961SBarry Smith 
20506e169961SBarry Smith   PetscFunctionBegin;
20516e169961SBarry Smith   if (x && b) {
20526e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
20536e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
20542b40b63fSBarry Smith     vecs = PETSC_TRUE;
20556e169961SBarry Smith   }
20561795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
20576e169961SBarry Smith   for (i=0; i<N; i++) {
20586e169961SBarry Smith     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2059580bdb30SBarry Smith     ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
20602205254eSKarl Rupp 
20616e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
20626e169961SBarry Smith   }
20636e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
20646e169961SBarry Smith     if (!zeroed[i]) {
20656e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
20664cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
20672b40b63fSBarry Smith           if (vecs) bb[i] -= a->a[j]*xx[a->j[j]];
20686e169961SBarry Smith           a->a[j] = 0.0;
20696e169961SBarry Smith         }
20706e169961SBarry Smith       }
20714cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
20726e169961SBarry Smith   }
20736e169961SBarry Smith   if (x && b) {
20746e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
20756e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
20766e169961SBarry Smith   }
20776e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
20786e169961SBarry Smith   if (diag != 0.0) {
20796e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
20801d5a398dSstefano_zampini     if (missing) {
20811d5a398dSstefano_zampini       for (i=0; i<N; i++) {
20824cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
20834cf107fdSStefano 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]);
20841d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
20851d5a398dSstefano_zampini       }
20861d5a398dSstefano_zampini     } else {
20876e169961SBarry Smith       for (i=0; i<N; i++) {
20886e169961SBarry Smith         a->a[a->diag[rows[i]]] = diag;
20896e169961SBarry Smith       }
20906e169961SBarry Smith     }
20911d5a398dSstefano_zampini   }
20924099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20936e169961SBarry Smith   PetscFunctionReturn(0);
20946e169961SBarry Smith }
20956e169961SBarry Smith 
2096a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
209717ab2063SBarry Smith {
2098416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
209997f1f81fSBarry Smith   PetscInt   *itmp;
210017ab2063SBarry Smith 
21013a40ed3dSBarry Smith   PetscFunctionBegin;
2102e32f2f54SBarry Smith   if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row);
210317ab2063SBarry Smith 
2104416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
2105bfeeae90SHong Zhang   if (v) *v = a->a + a->i[row];
210617ab2063SBarry Smith   if (idx) {
2107bfeeae90SHong Zhang     itmp = a->j + a->i[row];
210826fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
210917ab2063SBarry Smith     else *idx = 0;
211017ab2063SBarry Smith   }
21113a40ed3dSBarry Smith   PetscFunctionReturn(0);
211217ab2063SBarry Smith }
211317ab2063SBarry Smith 
2114bfeeae90SHong Zhang /* remove this function? */
2115a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
211617ab2063SBarry Smith {
21173a40ed3dSBarry Smith   PetscFunctionBegin;
21183a40ed3dSBarry Smith   PetscFunctionReturn(0);
211917ab2063SBarry Smith }
212017ab2063SBarry Smith 
2121dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
212217ab2063SBarry Smith {
2123416022c9SBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
212454f21887SBarry Smith   MatScalar      *v  = a->a;
212536db0b34SBarry Smith   PetscReal      sum = 0.0;
21266849ba73SBarry Smith   PetscErrorCode ierr;
212797f1f81fSBarry Smith   PetscInt       i,j;
212817ab2063SBarry Smith 
21293a40ed3dSBarry Smith   PetscFunctionBegin;
213017ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2131570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2132570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
2133570b7f6dSBarry Smith     *nrm = BLASnrm2_(&nz,v,&one);
2134570b7f6dSBarry Smith #else
2135416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
213636db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
213717ab2063SBarry Smith     }
21388f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2139570b7f6dSBarry Smith #endif
214051f70360SJed Brown     ierr = PetscLogFlops(2*a->nz);CHKERRQ(ierr);
21413a40ed3dSBarry Smith   } else if (type == NORM_1) {
214236db0b34SBarry Smith     PetscReal *tmp;
214397f1f81fSBarry Smith     PetscInt  *jj = a->j;
21441795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2145064f8208SBarry Smith     *nrm = 0.0;
2146416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2147bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
214817ab2063SBarry Smith     }
2149d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2150064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
215117ab2063SBarry Smith     }
2152606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
215351f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
21543a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2155064f8208SBarry Smith     *nrm = 0.0;
2156d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
2157bfeeae90SHong Zhang       v   = a->a + a->i[j];
215817ab2063SBarry Smith       sum = 0.0;
2159416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
2160cddf8d76SBarry Smith         sum += PetscAbsScalar(*v); v++;
216117ab2063SBarry Smith       }
2162064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
216317ab2063SBarry Smith     }
216451f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2165f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
21663a40ed3dSBarry Smith   PetscFunctionReturn(0);
216717ab2063SBarry Smith }
216817ab2063SBarry Smith 
21694e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
21704e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
21714e938277SHong Zhang {
21724e938277SHong Zhang   PetscErrorCode ierr;
21734e938277SHong Zhang   PetscInt       i,j,anzj;
21744e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
21754e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
21764e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
21774e938277SHong Zhang 
21784e938277SHong Zhang   PetscFunctionBegin;
21794e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2180854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2181785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2182785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
21834e938277SHong Zhang 
21844e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
21854e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
218626fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
21874e938277SHong Zhang   /* Form ati for csr format of A^T. */
218826fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
21894e938277SHong Zhang 
21904e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2191580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
21924e938277SHong Zhang 
21934e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
21944e938277SHong Zhang   for (i=0;i<am;i++) {
21954e938277SHong Zhang     anzj = ai[i+1] - ai[i];
21964e938277SHong Zhang     for (j=0;j<anzj;j++) {
21974e938277SHong Zhang       atj[atfill[*aj]] = i;
21984e938277SHong Zhang       atfill[*aj++]   += 1;
21994e938277SHong Zhang     }
22004e938277SHong Zhang   }
22014e938277SHong Zhang 
22024e938277SHong Zhang   /* Clean up temporary space and complete requests. */
22034e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2204ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
220533d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2206*b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2207a2f3521dSMark F. Adams 
22084e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
22094e938277SHong Zhang   b->free_a  = PETSC_FALSE;
22104e938277SHong Zhang   b->free_ij = PETSC_TRUE;
22114e938277SHong Zhang   b->nonew   = 0;
22124e938277SHong Zhang   PetscFunctionReturn(0);
22134e938277SHong Zhang }
22144e938277SHong Zhang 
22157087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2216cd0d46ebSvictorle {
22173d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
221854f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
221954f21887SBarry Smith   MatScalar      *va,*vb;
22206849ba73SBarry Smith   PetscErrorCode ierr;
222197f1f81fSBarry Smith   PetscInt       ma,na,mb,nb, i;
2222cd0d46ebSvictorle 
2223cd0d46ebSvictorle   PetscFunctionBegin;
2224cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2225cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
22265485867bSBarry Smith   if (ma!=nb || na!=mb) {
22275485867bSBarry Smith     *f = PETSC_FALSE;
22285485867bSBarry Smith     PetscFunctionReturn(0);
22295485867bSBarry Smith   }
2230cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2231cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2232cd0d46ebSvictorle   va   = aij->a; vb = bij->a;
2233785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2234785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2235cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2236cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2237cd0d46ebSvictorle 
2238cd0d46ebSvictorle   *f = PETSC_TRUE;
2239cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2240cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
224197f1f81fSBarry Smith       PetscInt    idc,idr;
22425485867bSBarry Smith       PetscScalar vc,vr;
2243cd0d46ebSvictorle       /* column/row index/value */
22445485867bSBarry Smith       idc = adx[aptr[i]];
22455485867bSBarry Smith       idr = bdx[bptr[idc]];
22465485867bSBarry Smith       vc  = va[aptr[i]];
22475485867bSBarry Smith       vr  = vb[bptr[idc]];
22485485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
22495485867bSBarry Smith         *f = PETSC_FALSE;
22505485867bSBarry Smith         goto done;
2251cd0d46ebSvictorle       } else {
22525485867bSBarry Smith         aptr[i]++;
22535485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2254cd0d46ebSvictorle       }
2255cd0d46ebSvictorle     }
2256cd0d46ebSvictorle   }
2257cd0d46ebSvictorle done:
2258cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
22593aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
2260cd0d46ebSvictorle   PetscFunctionReturn(0);
2261cd0d46ebSvictorle }
2262cd0d46ebSvictorle 
22637087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
22641cbb95d3SBarry Smith {
22653d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
226654f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
226754f21887SBarry Smith   MatScalar      *va,*vb;
22681cbb95d3SBarry Smith   PetscErrorCode ierr;
22691cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
22701cbb95d3SBarry Smith 
22711cbb95d3SBarry Smith   PetscFunctionBegin;
22721cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
22731cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
22741cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
22751cbb95d3SBarry Smith     *f = PETSC_FALSE;
22761cbb95d3SBarry Smith     PetscFunctionReturn(0);
22771cbb95d3SBarry Smith   }
22781cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
22791cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
22801cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2281785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2282785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
22831cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
22841cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
22851cbb95d3SBarry Smith 
22861cbb95d3SBarry Smith   *f = PETSC_TRUE;
22871cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
22881cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
22891cbb95d3SBarry Smith       PetscInt    idc,idr;
22901cbb95d3SBarry Smith       PetscScalar vc,vr;
22911cbb95d3SBarry Smith       /* column/row index/value */
22921cbb95d3SBarry Smith       idc = adx[aptr[i]];
22931cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
22941cbb95d3SBarry Smith       vc  = va[aptr[i]];
22951cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
22961cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
22971cbb95d3SBarry Smith         *f = PETSC_FALSE;
22981cbb95d3SBarry Smith         goto done;
22991cbb95d3SBarry Smith       } else {
23001cbb95d3SBarry Smith         aptr[i]++;
23011cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
23021cbb95d3SBarry Smith       }
23031cbb95d3SBarry Smith     }
23041cbb95d3SBarry Smith   }
23051cbb95d3SBarry Smith done:
23061cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
23071cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
23081cbb95d3SBarry Smith   PetscFunctionReturn(0);
23091cbb95d3SBarry Smith }
23101cbb95d3SBarry Smith 
2311ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
23129e29f15eSvictorle {
2313dfbe8321SBarry Smith   PetscErrorCode ierr;
23146e111a19SKarl Rupp 
23159e29f15eSvictorle   PetscFunctionBegin;
23165485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
23179e29f15eSvictorle   PetscFunctionReturn(0);
23189e29f15eSvictorle }
23199e29f15eSvictorle 
2320ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
23211cbb95d3SBarry Smith {
23221cbb95d3SBarry Smith   PetscErrorCode ierr;
23236e111a19SKarl Rupp 
23241cbb95d3SBarry Smith   PetscFunctionBegin;
23251cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
23261cbb95d3SBarry Smith   PetscFunctionReturn(0);
23271cbb95d3SBarry Smith }
23281cbb95d3SBarry Smith 
2329dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
233017ab2063SBarry Smith {
2331416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2332fff8e43fSBarry Smith   const PetscScalar *l,*r;
2333fff8e43fSBarry Smith   PetscScalar       x;
233454f21887SBarry Smith   MatScalar         *v;
2335dfbe8321SBarry Smith   PetscErrorCode    ierr;
2336fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2337fff8e43fSBarry Smith   const PetscInt    *jj;
233817ab2063SBarry Smith 
23393a40ed3dSBarry Smith   PetscFunctionBegin;
234017ab2063SBarry Smith   if (ll) {
23413ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
23423ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2343e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
2344e32f2f54SBarry Smith     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2345fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
2346416022c9SBarry Smith     v    = a->a;
234717ab2063SBarry Smith     for (i=0; i<m; i++) {
234817ab2063SBarry Smith       x = l[i];
2349416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
23502205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
235117ab2063SBarry Smith     }
2352fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2353efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
235417ab2063SBarry Smith   }
235517ab2063SBarry Smith   if (rr) {
2356e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
2357e32f2f54SBarry Smith     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2358fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
2359416022c9SBarry Smith     v    = a->a; jj = a->j;
23602205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
2361fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2362efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
236317ab2063SBarry Smith   }
2364acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
23653a40ed3dSBarry Smith   PetscFunctionReturn(0);
236617ab2063SBarry Smith }
236717ab2063SBarry Smith 
23687dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
236917ab2063SBarry Smith {
2370db02288aSLois Curfman McInnes   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*c;
23716849ba73SBarry Smith   PetscErrorCode ierr;
2372d0f46423SBarry Smith   PetscInt       *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
237397f1f81fSBarry Smith   PetscInt       row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
23745d0c19d7SBarry Smith   const PetscInt *irow,*icol;
23755d0c19d7SBarry Smith   PetscInt       nrows,ncols;
237697f1f81fSBarry Smith   PetscInt       *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
237754f21887SBarry Smith   MatScalar      *a_new,*mat_a;
2378416022c9SBarry Smith   Mat            C;
2379cdc6f3adSToby Isaac   PetscBool      stride;
238017ab2063SBarry Smith 
23813a40ed3dSBarry Smith   PetscFunctionBegin;
238299141d43SSatish Balay 
238317ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2384b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2385b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
238617ab2063SBarry Smith 
2387251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2388ff718158SBarry Smith   if (stride) {
2389ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2390ff718158SBarry Smith   } else {
2391ff718158SBarry Smith     first = 0;
2392ff718158SBarry Smith     step  = 0;
2393ff718158SBarry Smith   }
2394fee21e36SBarry Smith   if (stride && step == 1) {
239502834360SBarry Smith     /* special case of contiguous rows */
2396dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
239702834360SBarry Smith     /* loop over new rows determining lens and starting points */
239802834360SBarry Smith     for (i=0; i<nrows; i++) {
2399bfeeae90SHong Zhang       kstart = ai[irow[i]];
2400a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2401a91a9bebSLisandro Dalcin       starts[i] = kstart;
240202834360SBarry Smith       for (k=kstart; k<kend; k++) {
2403bfeeae90SHong Zhang         if (aj[k] >= first) {
240402834360SBarry Smith           starts[i] = k;
240502834360SBarry Smith           break;
240602834360SBarry Smith         }
240702834360SBarry Smith       }
2408a2744918SBarry Smith       sum = 0;
240902834360SBarry Smith       while (k < kend) {
2410bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2411a2744918SBarry Smith         sum++;
241202834360SBarry Smith       }
2413a2744918SBarry Smith       lens[i] = sum;
241402834360SBarry Smith     }
241502834360SBarry Smith     /* create submatrix */
2416cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
241797f1f81fSBarry Smith       PetscInt n_cols,n_rows;
241808480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2419e32f2f54SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2420d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
242108480c60SBarry Smith       C    = *B;
24223a40ed3dSBarry Smith     } else {
24233bef6203SJed Brown       PetscInt rbs,cbs;
2424ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2425f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
24263bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
24273bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
24283bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
24297adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2430ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
243108480c60SBarry Smith     }
2432db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2433db02288aSLois Curfman McInnes 
243402834360SBarry Smith     /* loop over rows inserting into submatrix */
2435db02288aSLois Curfman McInnes     a_new = c->a;
2436db02288aSLois Curfman McInnes     j_new = c->j;
2437db02288aSLois Curfman McInnes     i_new = c->i;
2438bfeeae90SHong Zhang 
243902834360SBarry Smith     for (i=0; i<nrows; i++) {
2440a2744918SBarry Smith       ii    = starts[i];
2441a2744918SBarry Smith       lensi = lens[i];
2442a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2443a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
244402834360SBarry Smith       }
2445580bdb30SBarry Smith       ierr       = PetscArraycpy(a_new,a->a + starts[i],lensi);CHKERRQ(ierr);
2446a2744918SBarry Smith       a_new     += lensi;
2447a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2448a2744918SBarry Smith       c->ilen[i] = lensi;
244902834360SBarry Smith     }
24500e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
24513a40ed3dSBarry Smith   } else {
245202834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
24531795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2454854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
24554dcab191SBarry Smith     for (i=0; i<ncols; i++) {
24564dcab191SBarry Smith #if defined(PETSC_USE_DEBUG)
24574dcab191SBarry 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);
24584dcab191SBarry Smith #endif
24594dcab191SBarry Smith       smap[icol[i]] = i+1;
24604dcab191SBarry Smith     }
24614dcab191SBarry Smith 
246202834360SBarry Smith     /* determine lens of each row */
246302834360SBarry Smith     for (i=0; i<nrows; i++) {
2464bfeeae90SHong Zhang       kstart  = ai[irow[i]];
246502834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
246602834360SBarry Smith       lens[i] = 0;
246702834360SBarry Smith       for (k=kstart; k<kend; k++) {
2468bfeeae90SHong Zhang         if (smap[aj[k]]) {
246902834360SBarry Smith           lens[i]++;
247002834360SBarry Smith         }
247102834360SBarry Smith       }
247202834360SBarry Smith     }
247317ab2063SBarry Smith     /* Create and fill new matrix */
2474a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2475ace3abfcSBarry Smith       PetscBool equal;
24760f5bd95cSBarry Smith 
247799141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2478e32f2f54SBarry Smith       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2479580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
2480f23aa3ddSBarry Smith       if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2481580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
248208480c60SBarry Smith       C    = *B;
24833a40ed3dSBarry Smith     } else {
24843bef6203SJed Brown       PetscInt rbs,cbs;
2485ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2486f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
24873bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
24883bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
24893bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
24907adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2491ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
249208480c60SBarry Smith     }
249399141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
249417ab2063SBarry Smith     for (i=0; i<nrows; i++) {
249599141d43SSatish Balay       row      = irow[i];
2496bfeeae90SHong Zhang       kstart   = ai[row];
249799141d43SSatish Balay       kend     = kstart + a->ilen[row];
2498bfeeae90SHong Zhang       mat_i    = c->i[i];
249999141d43SSatish Balay       mat_j    = c->j + mat_i;
250099141d43SSatish Balay       mat_a    = c->a + mat_i;
250199141d43SSatish Balay       mat_ilen = c->ilen + i;
250217ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2503bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2504ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
250599141d43SSatish Balay           *mat_a++ = a->a[k];
250699141d43SSatish Balay           (*mat_ilen)++;
250799141d43SSatish Balay 
250817ab2063SBarry Smith         }
250917ab2063SBarry Smith       }
251017ab2063SBarry Smith     }
251102834360SBarry Smith     /* Free work space */
251202834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2513606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2514606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2515cdc6f3adSToby Isaac     /* sort */
2516cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2517cdc6f3adSToby Isaac       PetscInt ilen;
2518cdc6f3adSToby Isaac 
2519cdc6f3adSToby Isaac       mat_i = c->i[i];
2520cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2521cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2522cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2523390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2524cdc6f3adSToby Isaac     }
252502834360SBarry Smith   }
25266d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
25276d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
252817ab2063SBarry Smith 
252917ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2530416022c9SBarry Smith   *B   = C;
25313a40ed3dSBarry Smith   PetscFunctionReturn(0);
253217ab2063SBarry Smith }
253317ab2063SBarry Smith 
2534fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
253582d44351SHong Zhang {
253682d44351SHong Zhang   PetscErrorCode ierr;
253782d44351SHong Zhang   Mat            B;
253882d44351SHong Zhang 
253982d44351SHong Zhang   PetscFunctionBegin;
2540c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
254182d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
254282d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
254333d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
254482d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
254582d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
254682d44351SHong Zhang     *subMat = B;
2547c2d650bdSHong Zhang   } else {
2548c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2549c2d650bdSHong Zhang   }
255082d44351SHong Zhang   PetscFunctionReturn(0);
255182d44351SHong Zhang }
255282d44351SHong Zhang 
25539a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2554a871dcd8SBarry Smith {
255563b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2556dfbe8321SBarry Smith   PetscErrorCode ierr;
255763b91edcSBarry Smith   Mat            outA;
2558ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
255963b91edcSBarry Smith 
25603a40ed3dSBarry Smith   PetscFunctionBegin;
2561e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
25621df811f5SHong Zhang 
2563b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2564b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2565a871dcd8SBarry Smith 
256663b91edcSBarry Smith   outA             = inA;
2567d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2568f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2569f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
25702205254eSKarl Rupp 
2571c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
25726bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
25732205254eSKarl Rupp 
2574c3122656SLisandro Dalcin   a->row = row;
25752205254eSKarl Rupp 
2576c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
25776bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
25782205254eSKarl Rupp 
2579c3122656SLisandro Dalcin   a->col = col;
258063b91edcSBarry Smith 
258136db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
25826bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
25834c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
25843bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2585f0ec6fceSSatish Balay 
258694a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2587854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
25883bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
258994a9d846SBarry Smith   }
259063b91edcSBarry Smith 
2591f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2592137fb511SHong Zhang   if (row_identity && col_identity) {
2593ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2594137fb511SHong Zhang   } else {
2595719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2596137fb511SHong Zhang   }
25973a40ed3dSBarry Smith   PetscFunctionReturn(0);
2598a871dcd8SBarry Smith }
2599a871dcd8SBarry Smith 
2600f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2601f0b747eeSBarry Smith {
2602f0b747eeSBarry Smith   Mat_SeqAIJ     *a     = (Mat_SeqAIJ*)inA->data;
2603f4df32b1SMatthew Knepley   PetscScalar    oalpha = alpha;
2604efee365bSSatish Balay   PetscErrorCode ierr;
2605c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
26063a40ed3dSBarry Smith 
26073a40ed3dSBarry Smith   PetscFunctionBegin;
2608c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
26098b83055fSJed Brown   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&oalpha,a->a,&one));
2610efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2611acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
26123a40ed3dSBarry Smith   PetscFunctionReturn(0);
2613f0b747eeSBarry Smith }
2614f0b747eeSBarry Smith 
2615f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
261616b64355SHong Zhang {
261716b64355SHong Zhang   PetscErrorCode ierr;
261816b64355SHong Zhang   PetscInt       i;
261916b64355SHong Zhang 
262016b64355SHong Zhang   PetscFunctionBegin;
262116b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
262216b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
262316b64355SHong Zhang 
262416b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
262516b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
262616b64355SHong Zhang     }
262716b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
262816b64355SHong Zhang 
262916b64355SHong Zhang     if (submatj->rbuf1) {
263016b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
263116b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
263216b64355SHong Zhang     }
263316b64355SHong Zhang 
263416b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
263516b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
263616b64355SHong Zhang     }
263716b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
263816b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
263916b64355SHong Zhang   }
264016b64355SHong Zhang 
264116b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
264216b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
264316b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
264416b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
264516b64355SHong Zhang #else
264616b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
264716b64355SHong Zhang #endif
264816b64355SHong Zhang 
264916b64355SHong Zhang   if (!submatj->allcolumns) {
265016b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
265116b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
265216b64355SHong Zhang #else
265316b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
265416b64355SHong Zhang #endif
265516b64355SHong Zhang   }
265616b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
265716b64355SHong Zhang 
265816b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
265916b64355SHong Zhang   PetscFunctionReturn(0);
266016b64355SHong Zhang }
266116b64355SHong Zhang 
26620fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
266316b64355SHong Zhang {
266416b64355SHong Zhang   PetscErrorCode ierr;
266516b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
26665c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
266716b64355SHong Zhang 
266816b64355SHong Zhang   PetscFunctionBegin;
266934136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2670f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
267116b64355SHong Zhang   PetscFunctionReturn(0);
267216b64355SHong Zhang }
267316b64355SHong Zhang 
26742d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
26752d033e1fSHong Zhang {
26762d033e1fSHong Zhang   PetscErrorCode ierr;
26772d033e1fSHong Zhang   PetscInt       i;
26780fb991dcSHong Zhang   Mat            C;
26790fb991dcSHong Zhang   Mat_SeqAIJ     *c;
26800fb991dcSHong Zhang   Mat_SubSppt    *submatj;
26812d033e1fSHong Zhang 
26822d033e1fSHong Zhang   PetscFunctionBegin;
26832d033e1fSHong Zhang   for (i=0; i<n; i++) {
26840fb991dcSHong Zhang     C       = (*mat)[i];
26850fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
26860fb991dcSHong Zhang     submatj = c->submatis1;
26872d033e1fSHong Zhang     if (submatj) {
2688682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
268934136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2690f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
269134136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
26922d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
26932d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
26942d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2695682e4c99SStefano Zampini       }
26962d033e1fSHong Zhang     } else {
26972d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
26982d033e1fSHong Zhang     }
26992d033e1fSHong Zhang   }
270086e85357SHong Zhang 
270163a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
270263a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
270363a75b2aSHong Zhang 
27042d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
27052d033e1fSHong Zhang   PetscFunctionReturn(0);
27062d033e1fSHong Zhang }
27072d033e1fSHong Zhang 
27087dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2709cddf8d76SBarry Smith {
2710dfbe8321SBarry Smith   PetscErrorCode ierr;
271197f1f81fSBarry Smith   PetscInt       i;
2712cddf8d76SBarry Smith 
27133a40ed3dSBarry Smith   PetscFunctionBegin;
2714cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2715df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2716cddf8d76SBarry Smith   }
2717cddf8d76SBarry Smith 
2718cddf8d76SBarry Smith   for (i=0; i<n; i++) {
27197dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2720cddf8d76SBarry Smith   }
27213a40ed3dSBarry Smith   PetscFunctionReturn(0);
2722cddf8d76SBarry Smith }
2723cddf8d76SBarry Smith 
272497f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
27254dcbc457SBarry Smith {
2726e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
27276849ba73SBarry Smith   PetscErrorCode ierr;
27285d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
27295d0c19d7SBarry Smith   const PetscInt *idx;
273097f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2731f1af5d2fSBarry Smith   PetscBT        table;
2732bbd702dbSSatish Balay 
27333a40ed3dSBarry Smith   PetscFunctionBegin;
2734d0f46423SBarry Smith   m  = A->rmap->n;
2735e4d965acSSatish Balay   ai = a->i;
2736bfeeae90SHong Zhang   aj = a->j;
27378a047759SSatish Balay 
2738e32f2f54SBarry Smith   if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
273906763907SSatish Balay 
2740854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
274153b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
274206763907SSatish Balay 
2743e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2744b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2745e4d965acSSatish Balay     isz  = 0;
27466831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2747e4d965acSSatish Balay 
2748e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
27494dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2750b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
2751e4d965acSSatish Balay 
2752dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2753e4d965acSSatish Balay     for (j=0; j<n; ++j) {
27542205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
27554dcbc457SBarry Smith     }
275606763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
27576bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
2758e4d965acSSatish Balay 
275904a348a9SBarry Smith     k = 0;
276004a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
276104a348a9SBarry Smith       n = isz;
276206763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2763e4d965acSSatish Balay         row   = nidx[k];
2764e4d965acSSatish Balay         start = ai[row];
2765e4d965acSSatish Balay         end   = ai[row+1];
276604a348a9SBarry Smith         for (l = start; l<end; l++) {
2767efb16452SHong Zhang           val = aj[l];
27682205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
2769e4d965acSSatish Balay         }
2770e4d965acSSatish Balay       }
2771e4d965acSSatish Balay     }
277270b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
2773e4d965acSSatish Balay   }
277494bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
2775606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
27763a40ed3dSBarry Smith   PetscFunctionReturn(0);
27774dcbc457SBarry Smith }
277817ab2063SBarry Smith 
27790513a670SBarry Smith /* -------------------------------------------------------------- */
2780dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
27810513a670SBarry Smith {
27820513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
27836849ba73SBarry Smith   PetscErrorCode ierr;
27843b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
27855d0c19d7SBarry Smith   const PetscInt *row,*col;
27865d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
278756cd22aeSBarry Smith   IS             icolp,irowp;
27880298fd71SBarry Smith   PetscInt       *cwork = NULL;
27890298fd71SBarry Smith   PetscScalar    *vwork = NULL;
27900513a670SBarry Smith 
27913a40ed3dSBarry Smith   PetscFunctionBegin;
27924c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
279356cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
27944c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
279556cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
27960513a670SBarry Smith 
27970513a670SBarry Smith   /* determine lengths of permuted rows */
2798854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
27992205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
2800ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
2801f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
280233d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
28037adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2804ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
2805606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
28060513a670SBarry Smith 
2807785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
28080513a670SBarry Smith   for (i=0; i<m; i++) {
280932ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
28102205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
2811cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
281232ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
28130513a670SBarry Smith   }
2814606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
28152205254eSKarl Rupp 
28163c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
28172205254eSKarl Rupp 
28180513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28190513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
282056cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
282156cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
28226bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
28236bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
28243a40ed3dSBarry Smith   PetscFunctionReturn(0);
28250513a670SBarry Smith }
28260513a670SBarry Smith 
2827dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
2828cb5b572fSBarry Smith {
2829dfbe8321SBarry Smith   PetscErrorCode ierr;
2830cb5b572fSBarry Smith 
2831cb5b572fSBarry Smith   PetscFunctionBegin;
283233f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
283333f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
2834be6bf707SBarry Smith     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2835be6bf707SBarry Smith     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
2836be6bf707SBarry Smith 
2837700c5bfcSBarry Smith     if (a->i[A->rmap->n] != b->i[B->rmap->n]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
2838580bdb30SBarry Smith     ierr = PetscArraycpy(b->a,a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
2839cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
2840cb5b572fSBarry Smith   } else {
2841cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
2842cb5b572fSBarry Smith   }
2843cb5b572fSBarry Smith   PetscFunctionReturn(0);
2844cb5b572fSBarry Smith }
2845cb5b572fSBarry Smith 
28464994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
2847273d9f13SBarry Smith {
2848dfbe8321SBarry Smith   PetscErrorCode ierr;
2849273d9f13SBarry Smith 
2850273d9f13SBarry Smith   PetscFunctionBegin;
2851ab93d7beSBarry Smith   ierr =  MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);CHKERRQ(ierr);
2852273d9f13SBarry Smith   PetscFunctionReturn(0);
2853273d9f13SBarry Smith }
2854273d9f13SBarry Smith 
28558c778c55SBarry Smith PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
28566c0721eeSBarry Smith {
28576c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
28586e111a19SKarl Rupp 
28596c0721eeSBarry Smith   PetscFunctionBegin;
28606c0721eeSBarry Smith   *array = a->a;
28616c0721eeSBarry Smith   PetscFunctionReturn(0);
28626c0721eeSBarry Smith }
28636c0721eeSBarry Smith 
28648c778c55SBarry Smith PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
28656c0721eeSBarry Smith {
28666c0721eeSBarry Smith   PetscFunctionBegin;
28676c0721eeSBarry Smith   PetscFunctionReturn(0);
28686c0721eeSBarry Smith }
2869273d9f13SBarry Smith 
28708229c054SShri Abhyankar /*
28718229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
28728229c054SShri Abhyankar    have different nonzero structure.
28738229c054SShri Abhyankar */
2874b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
2875ec7775f6SShri Abhyankar {
2876b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
2877ec7775f6SShri Abhyankar 
2878ec7775f6SShri Abhyankar   PetscFunctionBegin;
2879ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
2880ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
2881b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
2882b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
2883b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
28848af7cee1SJed Brown     nnz[i] = 0;
28858af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
2886b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
2887b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
28888af7cee1SJed Brown       nnz[i]++;
28898af7cee1SJed Brown     }
28908af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
2891ec7775f6SShri Abhyankar   }
2892ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
2893ec7775f6SShri Abhyankar }
2894ec7775f6SShri Abhyankar 
2895b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
2896b264fe52SHong Zhang {
2897b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
2898b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
2899b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
2900b264fe52SHong Zhang   PetscErrorCode ierr;
2901b264fe52SHong Zhang 
2902b264fe52SHong Zhang   PetscFunctionBegin;
2903b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
2904b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
2905b264fe52SHong Zhang   PetscFunctionReturn(0);
2906b264fe52SHong Zhang }
2907b264fe52SHong Zhang 
2908f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
2909ac90fabeSBarry Smith {
2910dfbe8321SBarry Smith   PetscErrorCode ierr;
2911ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
2912c5df96a5SBarry Smith   PetscBLASInt   one=1,bnz;
2913ac90fabeSBarry Smith 
2914ac90fabeSBarry Smith   PetscFunctionBegin;
2915c5df96a5SBarry Smith   ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
2916ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
2917f4df32b1SMatthew Knepley     PetscScalar alpha = a;
29188b83055fSJed Brown     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one));
2919acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
2920a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
2921ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2922ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
2923ac90fabeSBarry Smith   } else {
29248229c054SShri Abhyankar     Mat      B;
29258229c054SShri Abhyankar     PetscInt *nnz;
2926785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
2927ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
2928bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
29294aa94f47SShri Abhyankar     ierr = MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);CHKERRQ(ierr);
293033d57670SJed Brown     ierr = MatSetBlockSizesFromMats(B,Y,Y);CHKERRQ(ierr);
2931176df525SBarry Smith     ierr = MatSetType(B,(MatType) ((PetscObject)Y)->type_name);CHKERRQ(ierr);
29328229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
2933ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
2934ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
293528be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
29368229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
2937ac90fabeSBarry Smith   }
2938ac90fabeSBarry Smith   PetscFunctionReturn(0);
2939ac90fabeSBarry Smith }
2940ac90fabeSBarry Smith 
29417087cfbeSBarry Smith PetscErrorCode  MatConjugate_SeqAIJ(Mat mat)
2942354c94deSBarry Smith {
2943354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
2944354c94deSBarry Smith   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)mat->data;
2945354c94deSBarry Smith   PetscInt    i,nz;
2946354c94deSBarry Smith   PetscScalar *a;
2947354c94deSBarry Smith 
2948354c94deSBarry Smith   PetscFunctionBegin;
2949354c94deSBarry Smith   nz = aij->nz;
2950354c94deSBarry Smith   a  = aij->a;
29512205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
2952354c94deSBarry Smith #else
2953354c94deSBarry Smith   PetscFunctionBegin;
2954354c94deSBarry Smith #endif
2955354c94deSBarry Smith   PetscFunctionReturn(0);
2956354c94deSBarry Smith }
2957354c94deSBarry Smith 
2958985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2959e34fafa9SBarry Smith {
2960e34fafa9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2961e34fafa9SBarry Smith   PetscErrorCode ierr;
2962d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2963e34fafa9SBarry Smith   PetscReal      atmp;
2964985db425SBarry Smith   PetscScalar    *x;
2965e34fafa9SBarry Smith   MatScalar      *aa;
2966e34fafa9SBarry Smith 
2967e34fafa9SBarry Smith   PetscFunctionBegin;
2968e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2969e34fafa9SBarry Smith   aa = a->a;
2970e34fafa9SBarry Smith   ai = a->i;
2971e34fafa9SBarry Smith   aj = a->j;
2972e34fafa9SBarry Smith 
2973985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2974e34fafa9SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2975e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
2976e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2977e34fafa9SBarry Smith   for (i=0; i<m; i++) {
2978e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
29799189402eSHong Zhang     x[i]  = 0.0;
2980e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
2981985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
2982985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
2983985db425SBarry Smith       aa++; aj++;
2984985db425SBarry Smith     }
2985985db425SBarry Smith   }
2986985db425SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2987985db425SBarry Smith   PetscFunctionReturn(0);
2988985db425SBarry Smith }
2989985db425SBarry Smith 
2990985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2991985db425SBarry Smith {
2992985db425SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2993985db425SBarry Smith   PetscErrorCode ierr;
2994d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2995985db425SBarry Smith   PetscScalar    *x;
2996985db425SBarry Smith   MatScalar      *aa;
2997985db425SBarry Smith 
2998985db425SBarry Smith   PetscFunctionBegin;
2999e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3000985db425SBarry Smith   aa = a->a;
3001985db425SBarry Smith   ai = a->i;
3002985db425SBarry Smith   aj = a->j;
3003985db425SBarry Smith 
3004985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3005985db425SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3006985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3007e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3008985db425SBarry Smith   for (i=0; i<m; i++) {
3009985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3010d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3011985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3012985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3013985db425SBarry Smith       x[i] = 0.0;
3014985db425SBarry Smith       if (idx) {
3015985db425SBarry Smith         idx[i] = 0; /* in case ncols is zero */
3016985db425SBarry Smith         for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */
3017985db425SBarry Smith           if (aj[j] > j) {
3018985db425SBarry Smith             idx[i] = j;
3019985db425SBarry Smith             break;
3020985db425SBarry Smith           }
3021985db425SBarry Smith         }
3022985db425SBarry Smith       }
3023985db425SBarry Smith     }
3024985db425SBarry Smith     for (j=0; j<ncols; j++) {
3025985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3026985db425SBarry Smith       aa++; aj++;
3027985db425SBarry Smith     }
3028985db425SBarry Smith   }
3029985db425SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3030985db425SBarry Smith   PetscFunctionReturn(0);
3031985db425SBarry Smith }
3032985db425SBarry Smith 
3033c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3034c87e5d42SMatthew Knepley {
3035c87e5d42SMatthew Knepley   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3036c87e5d42SMatthew Knepley   PetscErrorCode ierr;
3037c87e5d42SMatthew Knepley   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3038c87e5d42SMatthew Knepley   PetscReal      atmp;
3039c87e5d42SMatthew Knepley   PetscScalar    *x;
3040c87e5d42SMatthew Knepley   MatScalar      *aa;
3041c87e5d42SMatthew Knepley 
3042c87e5d42SMatthew Knepley   PetscFunctionBegin;
3043e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3044c87e5d42SMatthew Knepley   aa = a->a;
3045c87e5d42SMatthew Knepley   ai = a->i;
3046c87e5d42SMatthew Knepley   aj = a->j;
3047c87e5d42SMatthew Knepley 
3048c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3049c87e5d42SMatthew Knepley   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3050c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
305160e0710aSBarry 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);
3052c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3053c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3054289a08f5SMatthew Knepley     if (ncols) {
3055289a08f5SMatthew Knepley       /* Get first nonzero */
3056289a08f5SMatthew Knepley       for (j = 0; j < ncols; j++) {
3057289a08f5SMatthew Knepley         atmp = PetscAbsScalar(aa[j]);
30582205254eSKarl Rupp         if (atmp > 1.0e-12) {
30592205254eSKarl Rupp           x[i] = atmp;
30602205254eSKarl Rupp           if (idx) idx[i] = aj[j];
30612205254eSKarl Rupp           break;
30622205254eSKarl Rupp         }
3063289a08f5SMatthew Knepley       }
306412431cb0SMatthew G Knepley       if (j == ncols) {x[i] = PetscAbsScalar(*aa); if (idx) idx[i] = *aj;}
3065289a08f5SMatthew Knepley     } else {
3066289a08f5SMatthew Knepley       x[i] = 0.0; if (idx) idx[i] = 0;
3067289a08f5SMatthew Knepley     }
3068c87e5d42SMatthew Knepley     for (j = 0; j < ncols; j++) {
3069c87e5d42SMatthew Knepley       atmp = PetscAbsScalar(*aa);
3070289a08f5SMatthew Knepley       if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3071c87e5d42SMatthew Knepley       aa++; aj++;
3072c87e5d42SMatthew Knepley     }
3073c87e5d42SMatthew Knepley   }
3074c87e5d42SMatthew Knepley   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3075c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3076c87e5d42SMatthew Knepley }
3077c87e5d42SMatthew Knepley 
3078985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3079985db425SBarry Smith {
3080985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3081985db425SBarry Smith   PetscErrorCode  ierr;
3082d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3083d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3084985db425SBarry Smith   PetscScalar     *x;
3085d9ca1df4SBarry Smith   const MatScalar *aa;
3086985db425SBarry Smith 
3087985db425SBarry Smith   PetscFunctionBegin;
3088e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3089985db425SBarry Smith   aa = a->a;
3090985db425SBarry Smith   ai = a->i;
3091985db425SBarry Smith   aj = a->j;
3092985db425SBarry Smith 
3093985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3094985db425SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3095985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3096e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3097985db425SBarry Smith   for (i=0; i<m; i++) {
3098985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3099d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3100985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3101985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3102985db425SBarry Smith       x[i] = 0.0;
3103985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3104985db425SBarry Smith         idx[i] = 0; /* in case ncols is zero */
3105985db425SBarry Smith         for (j=0; j<ncols; j++) {
3106985db425SBarry Smith           if (aj[j] > j) {
3107985db425SBarry Smith             idx[i] = j;
3108985db425SBarry Smith             break;
3109985db425SBarry Smith           }
3110985db425SBarry Smith         }
3111985db425SBarry Smith       }
3112985db425SBarry Smith     }
3113985db425SBarry Smith     for (j=0; j<ncols; j++) {
3114985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3115985db425SBarry Smith       aa++; aj++;
3116e34fafa9SBarry Smith     }
3117e34fafa9SBarry Smith   }
3118e34fafa9SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3119e34fafa9SBarry Smith   PetscFunctionReturn(0);
3120e34fafa9SBarry Smith }
3121bbead8a2SBarry Smith 
3122713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3123bbead8a2SBarry Smith {
3124bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3125bbead8a2SBarry Smith   PetscErrorCode  ierr;
312633d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3127bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
31280da83c2eSBarry Smith   const PetscReal shift = 0.0;
31291a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3130bbead8a2SBarry Smith 
3131bbead8a2SBarry Smith   PetscFunctionBegin;
3132a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
31334a0d0026SBarry Smith   if (a->ibdiagvalid) {
31344a0d0026SBarry Smith     if (values) *values = a->ibdiag;
31354a0d0026SBarry Smith     PetscFunctionReturn(0);
31364a0d0026SBarry Smith   }
3137bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3138bbead8a2SBarry Smith   if (!a->ibdiag) {
3139785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
31403bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3141bbead8a2SBarry Smith   }
3142bbead8a2SBarry Smith   diag = a->ibdiag;
3143bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3144bbead8a2SBarry Smith   /* factor and invert each block */
3145bbead8a2SBarry Smith   switch (bs) {
3146bbead8a2SBarry Smith   case 1:
3147bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3148bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3149ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3150ec1892c8SHong Zhang         if (allowzeropivot) {
31517b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
31527b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
31537b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
31547b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
31557b6c816cSBarry 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);
3156ec1892c8SHong Zhang       }
3157bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3158bbead8a2SBarry Smith     }
3159bbead8a2SBarry Smith     break;
3160bbead8a2SBarry Smith   case 2:
3161bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3162bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3163bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3164a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
31657b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
316696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3167bbead8a2SBarry Smith       diag += 4;
3168bbead8a2SBarry Smith     }
3169bbead8a2SBarry Smith     break;
3170bbead8a2SBarry Smith   case 3:
3171bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3172bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3173bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3174a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
31757b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
317696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3177bbead8a2SBarry Smith       diag += 9;
3178bbead8a2SBarry Smith     }
3179bbead8a2SBarry Smith     break;
3180bbead8a2SBarry Smith   case 4:
3181bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3182bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3183bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3184a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
31857b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
318696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3187bbead8a2SBarry Smith       diag += 16;
3188bbead8a2SBarry Smith     }
3189bbead8a2SBarry Smith     break;
3190bbead8a2SBarry Smith   case 5:
3191bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3192bbead8a2SBarry 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;
3193bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3194a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
31957b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
319696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3197bbead8a2SBarry Smith       diag += 25;
3198bbead8a2SBarry Smith     }
3199bbead8a2SBarry Smith     break;
3200bbead8a2SBarry Smith   case 6:
3201bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3202bbead8a2SBarry 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;
3203bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3204a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32057b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
320696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3207bbead8a2SBarry Smith       diag += 36;
3208bbead8a2SBarry Smith     }
3209bbead8a2SBarry Smith     break;
3210bbead8a2SBarry Smith   case 7:
3211bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3212bbead8a2SBarry 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;
3213bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3214a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32157b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
321696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3217bbead8a2SBarry Smith       diag += 49;
3218bbead8a2SBarry Smith     }
3219bbead8a2SBarry Smith     break;
3220bbead8a2SBarry Smith   default:
3221dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3222bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3223bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3224bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3225bbead8a2SBarry Smith       }
3226bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
32275f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32287b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
322996b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3230bbead8a2SBarry Smith       diag += bs2;
3231bbead8a2SBarry Smith     }
3232bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3233bbead8a2SBarry Smith   }
3234bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3235bbead8a2SBarry Smith   PetscFunctionReturn(0);
3236bbead8a2SBarry Smith }
3237bbead8a2SBarry Smith 
323873a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
323973a71a0fSBarry Smith {
324073a71a0fSBarry Smith   PetscErrorCode ierr;
324173a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
324273a71a0fSBarry Smith   PetscScalar    a;
324373a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
324473a71a0fSBarry Smith 
324573a71a0fSBarry Smith   PetscFunctionBegin;
324673a71a0fSBarry Smith   if (!x->assembled) {
324773a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
324873a71a0fSBarry Smith     for (i=0; i<m; i++) {
324973a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
325073a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
325173a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
325273a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
325373a71a0fSBarry Smith       }
325473a71a0fSBarry Smith     }
3255e2ce353bSJunchao Zhang   } else {
3256e2ce353bSJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);}
3257e2ce353bSJunchao Zhang   }
325873a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
325973a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
326073a71a0fSBarry Smith   PetscFunctionReturn(0);
326173a71a0fSBarry Smith }
326273a71a0fSBarry Smith 
3263679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3264679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3265679944adSJunchao Zhang {
3266679944adSJunchao Zhang   PetscErrorCode ierr;
3267679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3268679944adSJunchao Zhang   PetscScalar    a;
3269679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3270679944adSJunchao Zhang 
3271679944adSJunchao Zhang   PetscFunctionBegin;
3272679944adSJunchao Zhang   nskip = high - low;
3273679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3274679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3275679944adSJunchao Zhang   for (i=0; i<m; i++) {
3276679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3277679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3278679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3279679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3280679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3281679944adSJunchao Zhang     }
3282e2ce353bSJunchao Zhang   }
3283679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3284679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3285679944adSJunchao Zhang   PetscFunctionReturn(0);
3286679944adSJunchao Zhang }
3287679944adSJunchao Zhang 
3288679944adSJunchao Zhang 
3289682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
32900a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3291cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3292cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3293cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
329497304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
32957c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
32967c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3297db4efbfdSBarry Smith                                         0,
3298db4efbfdSBarry Smith                                         0,
3299db4efbfdSBarry Smith                                         0,
3300db4efbfdSBarry Smith                                 /* 10*/ 0,
3301cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3302cb5b572fSBarry Smith                                         0,
330341f059aeSBarry Smith                                         MatSOR_SeqAIJ,
330491e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
330597304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3306cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3307cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3308cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3309cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
331097304618SKris Buschelman                                 /* 20*/ 0,
3311cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3312cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3313cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3314d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3315db4efbfdSBarry Smith                                         0,
3316db4efbfdSBarry Smith                                         0,
3317db4efbfdSBarry Smith                                         0,
3318db4efbfdSBarry Smith                                         0,
33194994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3320db4efbfdSBarry Smith                                         0,
3321db4efbfdSBarry Smith                                         0,
33228c778c55SBarry Smith                                         0,
33238c778c55SBarry Smith                                         0,
3324d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3325cb5b572fSBarry Smith                                         0,
3326cb5b572fSBarry Smith                                         0,
3327cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3328cb5b572fSBarry Smith                                         0,
3329d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
33307dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3331cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3332cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3333cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3334d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3335cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
33367d68702bSBarry Smith                                         MatShift_SeqAIJ,
333779299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
33386e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
333973a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
33403b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
33413b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
33423b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3343a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
334493dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3345b9617806SBarry Smith                                         0,
33460513a670SBarry Smith                                         0,
3347cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3348cda55fadSBarry Smith                                         0,
3349d519adbfSMatthew Knepley                                 /* 59*/ 0,
3350b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3351b9b97703SBarry Smith                                         MatView_SeqAIJ,
3352357abbc8SBarry Smith                                         0,
3353321b30b9SSatish Balay                                         MatMatMatMult_SeqAIJ_SeqAIJ_SeqAIJ,
3354321b30b9SSatish Balay                                 /* 64*/ MatMatMatMultSymbolic_SeqAIJ_SeqAIJ_SeqAIJ,
3355321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3356ee4f033dSBarry Smith                                         0,
3357ee4f033dSBarry Smith                                         0,
3358ee4f033dSBarry Smith                                         0,
3359d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3360c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3361ee4f033dSBarry Smith                                         0,
3362dcf5cc72SBarry Smith                                         0,
33632c93a97aSBarry Smith                                         0,
33642c93a97aSBarry Smith                                 /* 74*/ 0,
33653acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
336697304618SKris Buschelman                                         0,
336797304618SKris Buschelman                                         0,
336897304618SKris Buschelman                                         0,
33696ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
337097304618SKris Buschelman                                         0,
337197304618SKris Buschelman                                         0,
337297304618SKris Buschelman                                         0,
3373bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3374d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
33751cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
33766284ec50SHong Zhang                                         0,
33776284ec50SHong Zhang                                         0,
3378bc011b1eSHong Zhang                                         0,
3379d519adbfSMatthew Knepley                                 /* 89*/ MatMatMult_SeqAIJ_SeqAIJ,
338026be0446SHong Zhang                                         MatMatMultSymbolic_SeqAIJ_SeqAIJ,
338126be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
338265e8a0caSHong Zhang                                         MatPtAP_SeqAIJ_SeqAIJ,
33838fa4b5a6SHong Zhang                                         MatPtAPSymbolic_SeqAIJ_SeqAIJ_SparseAxpy,
33848fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
33856fc122caSHong Zhang                                         MatMatTransposeMult_SeqAIJ_SeqAIJ,
33866fc122caSHong Zhang                                         MatMatTransposeMultSymbolic_SeqAIJ_SeqAIJ,
33876fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
33882121bac1SHong Zhang                                         0,
33892121bac1SHong Zhang                                 /* 99*/ 0,
3390609c6c4dSKris Buschelman                                         0,
3391609c6c4dSKris Buschelman                                         0,
339287d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
339387d4246cSBarry Smith                                         0,
3394d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
339599cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3396f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3397f5edf698SHong Zhang                                         0,
33982bebee5dSHong Zhang                                         0,
3399cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3400985db425SBarry Smith                                         0,
34012af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
34022af78befSBarry Smith                                         0,
3403599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3404d519adbfSMatthew Knepley                                 /*114*/ 0,
3405599ef60dSHong Zhang                                         0,
34063c2a7987SHong Zhang                                         0,
3407fe97e370SBarry Smith                                         0,
3408fbdbba38SShri Abhyankar                                         0,
3409fbdbba38SShri Abhyankar                                 /*119*/ 0,
3410fbdbba38SShri Abhyankar                                         0,
3411fbdbba38SShri Abhyankar                                         0,
341282d44351SHong Zhang                                         0,
3413b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
34140716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3415bbead8a2SBarry Smith                                         MatGetColumnNorms_SeqAIJ,
341637868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
34170da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
341837868618SMatthew G Knepley                                         0,
34195df89d91SHong Zhang                                 /*129*/ 0,
342075648e8dSHong Zhang                                         MatTransposeMatMult_SeqAIJ_SeqAIJ,
342175648e8dSHong Zhang                                         MatTransposeMatMultSymbolic_SeqAIJ_SeqAIJ,
342275648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3423b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3424b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
34252b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
34262b8ad9a3SHong Zhang                                         MatRARt_SeqAIJ_SeqAIJ,
34272b8ad9a3SHong Zhang                                         MatRARtSymbolic_SeqAIJ_SeqAIJ,
34283964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
34293964eb88SJed Brown                                  /*139*/0,
3430f9426fe0SMark Adams                                         0,
34311919a2e2SJed Brown                                         0,
34323a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
34339c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
34342d033e1fSHong Zhang                                  /*144*/MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
34352d033e1fSHong Zhang                                         MatDestroySubMatrices_SeqAIJ
34369e29f15eSvictorle };
343717ab2063SBarry Smith 
34387087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3439bef8e0ddSBarry Smith {
3440bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
344197f1f81fSBarry Smith   PetscInt   i,nz,n;
3442bef8e0ddSBarry Smith 
3443bef8e0ddSBarry Smith   PetscFunctionBegin;
3444bef8e0ddSBarry Smith   nz = aij->maxnz;
3445d0f46423SBarry Smith   n  = mat->rmap->n;
3446bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3447bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3448bef8e0ddSBarry Smith   }
3449bef8e0ddSBarry Smith   aij->nz = nz;
3450bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3451bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3452bef8e0ddSBarry Smith   }
3453bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3454bef8e0ddSBarry Smith }
3455bef8e0ddSBarry Smith 
3456a3bb6f32SFande Kong /*
3457e8b528d9SFande Kong  * When a sparse matrix has many zero columns, we should compact them out to save the space
3458a3bb6f32SFande Kong  * This happens in MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3459a3bb6f32SFande Kong  * */
3460a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3461a3bb6f32SFande Kong {
3462a3bb6f32SFande Kong   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
3463a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3464a3bb6f32SFande Kong   PetscTablePosition tpos;
3465a3bb6f32SFande Kong   PetscInt           gid,lid,i,j,ncols,ec;
3466a3bb6f32SFande Kong   PetscInt           *garray;
3467a3bb6f32SFande Kong   PetscErrorCode  ierr;
3468a3bb6f32SFande Kong 
3469a3bb6f32SFande Kong   PetscFunctionBegin;
3470a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3471a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3472a3bb6f32SFande Kong   /* use a table */
3473a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3474a3bb6f32SFande Kong   ec = 0;
3475a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3476a3bb6f32SFande Kong     ncols = aij->i[i+1] - aij->i[i];
3477a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3478a3bb6f32SFande Kong       PetscInt data,gid1 = aij->j[aij->i[i] + j] + 1;
3479a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3480a3bb6f32SFande Kong       if (!data) {
3481a3bb6f32SFande Kong         /* one based table */
3482a3bb6f32SFande Kong         ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3483a3bb6f32SFande Kong       }
3484a3bb6f32SFande Kong     }
3485a3bb6f32SFande Kong   }
3486a3bb6f32SFande Kong   /* form array of columns we need */
3487a3bb6f32SFande Kong   ierr = PetscMalloc1(ec+1,&garray);CHKERRQ(ierr);
3488a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3489a3bb6f32SFande Kong   while (tpos) {
3490a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3491a3bb6f32SFande Kong     gid--;
3492a3bb6f32SFande Kong     lid--;
3493a3bb6f32SFande Kong     garray[lid] = gid;
3494a3bb6f32SFande Kong   }
3495a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3496a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3497a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3498a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3499a3bb6f32SFande Kong   }
3500a3bb6f32SFande Kong   /* compact out the extra columns in B */
3501a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3502a3bb6f32SFande Kong 	ncols = aij->i[i+1] - aij->i[i];
3503a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3504a3bb6f32SFande Kong       PetscInt gid1 = aij->j[aij->i[i] + j] + 1;
3505a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3506a3bb6f32SFande Kong       lid--;
3507a3bb6f32SFande Kong       aij->j[aij->i[i] + j] = lid;
3508a3bb6f32SFande Kong     }
3509a3bb6f32SFande Kong   }
3510a3bb6f32SFande Kong   mat->cmap->n = mat->cmap->N = ec;
3511a3bb6f32SFande Kong   mat->cmap->bs = 1;
3512a3bb6f32SFande Kong 
3513a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
3514a3bb6f32SFande Kong   ierr = PetscLayoutSetUp((mat->cmap));CHKERRQ(ierr);
3515a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3516a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3517a3bb6f32SFande Kong   PetscFunctionReturn(0);
3518a3bb6f32SFande Kong }
3519a3bb6f32SFande Kong 
3520bef8e0ddSBarry Smith /*@
3521bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3522bef8e0ddSBarry Smith        in the matrix.
3523bef8e0ddSBarry Smith 
3524bef8e0ddSBarry Smith   Input Parameters:
3525bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3526bef8e0ddSBarry Smith -  indices - the column indices
3527bef8e0ddSBarry Smith 
352815091d37SBarry Smith   Level: advanced
352915091d37SBarry Smith 
3530bef8e0ddSBarry Smith   Notes:
3531bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3532bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3533bef8e0ddSBarry Smith   of the MatSetValues() operation.
3534bef8e0ddSBarry Smith 
3535bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3536d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3537bef8e0ddSBarry Smith 
3538bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3539bef8e0ddSBarry Smith 
3540b9617806SBarry Smith     The indices should start with zero, not one.
3541b9617806SBarry Smith 
3542bef8e0ddSBarry Smith @*/
35437087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3544bef8e0ddSBarry Smith {
35454ac538c5SBarry Smith   PetscErrorCode ierr;
3546bef8e0ddSBarry Smith 
3547bef8e0ddSBarry Smith   PetscFunctionBegin;
35480700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
35494482741eSBarry Smith   PetscValidPointer(indices,2);
35504ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3551bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3552bef8e0ddSBarry Smith }
3553bef8e0ddSBarry Smith 
3554be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3555be6bf707SBarry Smith 
35567087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3557be6bf707SBarry Smith {
3558be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
35596849ba73SBarry Smith   PetscErrorCode ierr;
3560d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3561be6bf707SBarry Smith 
3562be6bf707SBarry Smith   PetscFunctionBegin;
3563169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3564be6bf707SBarry Smith 
3565be6bf707SBarry Smith   /* allocate space for values if not already there */
3566be6bf707SBarry Smith   if (!aij->saved_values) {
3567854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
35683bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3569be6bf707SBarry Smith   }
3570be6bf707SBarry Smith 
3571be6bf707SBarry Smith   /* copy values over */
3572580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3573be6bf707SBarry Smith   PetscFunctionReturn(0);
3574be6bf707SBarry Smith }
3575be6bf707SBarry Smith 
3576be6bf707SBarry Smith /*@
3577be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3578be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3579be6bf707SBarry Smith        nonlinear portion.
3580be6bf707SBarry Smith 
3581be6bf707SBarry Smith    Collect on Mat
3582be6bf707SBarry Smith 
3583be6bf707SBarry Smith   Input Parameters:
35840e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3585be6bf707SBarry Smith 
358615091d37SBarry Smith   Level: advanced
358715091d37SBarry Smith 
3588be6bf707SBarry Smith   Common Usage, with SNESSolve():
3589be6bf707SBarry Smith $    Create Jacobian matrix
3590be6bf707SBarry Smith $    Set linear terms into matrix
3591be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3592be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3593be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3594512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3595be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3596be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3597be6bf707SBarry Smith $    In your Jacobian routine
3598be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3599be6bf707SBarry Smith $      Set nonlinear terms in matrix
3600be6bf707SBarry Smith 
3601be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3602be6bf707SBarry Smith $    // build linear portion of Jacobian
3603512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3604be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3605be6bf707SBarry Smith $    loop over nonlinear iterations
3606be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3607be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3608be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3609be6bf707SBarry Smith $       Solve linear system with Jacobian
3610be6bf707SBarry Smith $    endloop
3611be6bf707SBarry Smith 
3612be6bf707SBarry Smith   Notes:
3613be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3614512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3615be6bf707SBarry Smith     calling this routine.
3616be6bf707SBarry Smith 
36170c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
36180c468ba9SBarry Smith     and does not allocated additional space.
36190c468ba9SBarry Smith 
3620be6bf707SBarry Smith .seealso: MatRetrieveValues()
3621be6bf707SBarry Smith 
3622be6bf707SBarry Smith @*/
36237087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3624be6bf707SBarry Smith {
36254ac538c5SBarry Smith   PetscErrorCode ierr;
3626be6bf707SBarry Smith 
3627be6bf707SBarry Smith   PetscFunctionBegin;
36280700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3629e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3630e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
36314ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3632be6bf707SBarry Smith   PetscFunctionReturn(0);
3633be6bf707SBarry Smith }
3634be6bf707SBarry Smith 
36357087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3636be6bf707SBarry Smith {
3637be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
36386849ba73SBarry Smith   PetscErrorCode ierr;
3639d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3640be6bf707SBarry Smith 
3641be6bf707SBarry Smith   PetscFunctionBegin;
3642169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3643f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3644be6bf707SBarry Smith   /* copy values over */
3645580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3646be6bf707SBarry Smith   PetscFunctionReturn(0);
3647be6bf707SBarry Smith }
3648be6bf707SBarry Smith 
3649be6bf707SBarry Smith /*@
3650be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3651be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3652be6bf707SBarry Smith        nonlinear portion.
3653be6bf707SBarry Smith 
3654be6bf707SBarry Smith    Collect on Mat
3655be6bf707SBarry Smith 
3656be6bf707SBarry Smith   Input Parameters:
3657386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3658be6bf707SBarry Smith 
365915091d37SBarry Smith   Level: advanced
366015091d37SBarry Smith 
3661be6bf707SBarry Smith .seealso: MatStoreValues()
3662be6bf707SBarry Smith 
3663be6bf707SBarry Smith @*/
36647087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3665be6bf707SBarry Smith {
36664ac538c5SBarry Smith   PetscErrorCode ierr;
3667be6bf707SBarry Smith 
3668be6bf707SBarry Smith   PetscFunctionBegin;
36690700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3670e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3671e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
36724ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3673be6bf707SBarry Smith   PetscFunctionReturn(0);
3674be6bf707SBarry Smith }
3675be6bf707SBarry Smith 
3676f83d6046SBarry Smith 
3677be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
367817ab2063SBarry Smith /*@C
3679682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
36800d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
36816e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
368251c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
36832bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
368417ab2063SBarry Smith 
3685d083f849SBarry Smith    Collective
3686db81eaa0SLois Curfman McInnes 
368717ab2063SBarry Smith    Input Parameters:
3688db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
368917ab2063SBarry Smith .  m - number of rows
369017ab2063SBarry Smith .  n - number of columns
369117ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
369251c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
36930298fd71SBarry Smith          (possibly different for each row) or NULL
369417ab2063SBarry Smith 
369517ab2063SBarry Smith    Output Parameter:
3696416022c9SBarry Smith .  A - the matrix
369717ab2063SBarry Smith 
3698175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3699f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3700175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3701175b88e8SBarry Smith 
3702b259b22eSLois Curfman McInnes    Notes:
370349a6f317SBarry Smith    If nnz is given then nz is ignored
370449a6f317SBarry Smith 
370517ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
370617ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
37070002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
370844cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
370917ab2063SBarry Smith 
371017ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
37110298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
37123d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
37136da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
371417ab2063SBarry Smith 
3715682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
37164fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3717682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
37186c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
37196c7ebb05SLois Curfman McInnes 
37206c7ebb05SLois Curfman McInnes    Options Database Keys:
3721698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
37229db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
372317ab2063SBarry Smith 
3724027ccd11SLois Curfman McInnes    Level: intermediate
3725027ccd11SLois Curfman McInnes 
372669b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
372736db0b34SBarry Smith 
372817ab2063SBarry Smith @*/
37297087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
373017ab2063SBarry Smith {
3731dfbe8321SBarry Smith   PetscErrorCode ierr;
37326945ee14SBarry Smith 
37333a40ed3dSBarry Smith   PetscFunctionBegin;
3734f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3735117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3736c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
3737d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
3738273d9f13SBarry Smith   PetscFunctionReturn(0);
3739273d9f13SBarry Smith }
3740273d9f13SBarry Smith 
3741273d9f13SBarry Smith /*@C
3742273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3743273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
3744273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
3745273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
3746273d9f13SBarry Smith 
3747d083f849SBarry Smith    Collective
3748273d9f13SBarry Smith 
3749273d9f13SBarry Smith    Input Parameters:
37501c4f3114SJed Brown +  B - The matrix
3751273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
3752273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
37530298fd71SBarry Smith          (possibly different for each row) or NULL
3754273d9f13SBarry Smith 
3755273d9f13SBarry Smith    Notes:
375649a6f317SBarry Smith      If nnz is given then nz is ignored
375749a6f317SBarry Smith 
3758273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
3759273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
3760273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
3761273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
3762273d9f13SBarry Smith 
3763273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
37640298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
3765273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
3766273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
3767273d9f13SBarry Smith 
3768aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
3769aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3770aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
3771aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
3772aa95bbe8SBarry Smith 
3773a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
3774a96a251dSBarry Smith    entries or columns indices
3775a96a251dSBarry Smith 
3776273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
3777273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
3778273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
3779273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
3780273d9f13SBarry Smith 
3781273d9f13SBarry Smith    Options Database Keys:
3782698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
378347b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3784273d9f13SBarry Smith 
3785273d9f13SBarry Smith    Level: intermediate
3786273d9f13SBarry Smith 
378769b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo()
3788273d9f13SBarry Smith 
3789273d9f13SBarry Smith @*/
37907087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
3791273d9f13SBarry Smith {
37924ac538c5SBarry Smith   PetscErrorCode ierr;
3793a23d5eceSKris Buschelman 
3794a23d5eceSKris Buschelman   PetscFunctionBegin;
37956ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
37966ba663aaSJed Brown   PetscValidType(B,1);
37974ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
3798a23d5eceSKris Buschelman   PetscFunctionReturn(0);
3799a23d5eceSKris Buschelman }
3800a23d5eceSKris Buschelman 
38017087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
3802a23d5eceSKris Buschelman {
3803273d9f13SBarry Smith   Mat_SeqAIJ     *b;
38042576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
38056849ba73SBarry Smith   PetscErrorCode ierr;
380697f1f81fSBarry Smith   PetscInt       i;
3807273d9f13SBarry Smith 
3808273d9f13SBarry Smith   PetscFunctionBegin;
38092576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
3810a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
3811c461c341SBarry Smith     skipallocation = PETSC_TRUE;
3812c461c341SBarry Smith     nz             = 0;
3813c461c341SBarry Smith   }
381426283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
381526283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
3816899cda47SBarry Smith 
3817435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
381860e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
3819071fcb05SBarry Smith #if defined(PETSC_USE_DEBUG)
3820b73539f3SBarry Smith   if (nnz) {
3821d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
382260e0710aSBarry 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]);
382360e0710aSBarry 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);
3824b73539f3SBarry Smith     }
3825b73539f3SBarry Smith   }
3826071fcb05SBarry Smith #endif
3827b73539f3SBarry Smith 
3828273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
38292205254eSKarl Rupp 
3830273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
3831273d9f13SBarry Smith 
3832ab93d7beSBarry Smith   if (!skipallocation) {
38332ee49352SLisandro Dalcin     if (!b->imax) {
3834071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
3835071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3836071fcb05SBarry Smith     }
3837071fcb05SBarry Smith     if (!b->ilen) {
3838071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
3839071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
3840071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3841071fcb05SBarry Smith     } else {
3842071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
38432ee49352SLisandro Dalcin     }
3844846b4da1SFande Kong     if (!b->ipre) {
3845846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
3846846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3847846b4da1SFande Kong     }
3848273d9f13SBarry Smith     if (!nnz) {
3849435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
3850c62bd62aSJed Brown       else if (nz < 0) nz = 1;
38515d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
3852d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
3853d0f46423SBarry Smith       nz = nz*B->rmap->n;
3854273d9f13SBarry Smith     } else {
3855273d9f13SBarry Smith       nz = 0;
3856d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
3857273d9f13SBarry Smith     }
3858ab93d7beSBarry Smith 
3859273d9f13SBarry Smith     /* allocate the matrix space */
386053dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
38612ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
3862396832f4SHong Zhang     if (B->structure_only) {
38635848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
38645848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
3865396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
3866396832f4SHong Zhang     } else {
3867dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
38683bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
3869396832f4SHong Zhang     }
3870bfeeae90SHong Zhang     b->i[0] = 0;
3871d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
38725da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
38735da197adSKris Buschelman     }
3874396832f4SHong Zhang     if (B->structure_only) {
3875396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
3876396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
3877396832f4SHong Zhang     } else {
3878273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
3879e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
3880396832f4SHong Zhang     }
3881e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
3882c461c341SBarry Smith   } else {
3883e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
3884e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
3885c461c341SBarry Smith   }
3886273d9f13SBarry Smith 
3887846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
3888846b4da1SFande Kong     /* reserve user-requested sparsity */
3889580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
3890846b4da1SFande Kong   }
3891846b4da1SFande Kong 
3892846b4da1SFande Kong 
3893273d9f13SBarry Smith   b->nz               = 0;
3894273d9f13SBarry Smith   b->maxnz            = nz;
3895273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
38962205254eSKarl Rupp   if (realalloc) {
38972205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
38982205254eSKarl Rupp   }
3899cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
3900cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
3901273d9f13SBarry Smith   PetscFunctionReturn(0);
3902273d9f13SBarry Smith }
3903273d9f13SBarry Smith 
3904846b4da1SFande Kong 
3905846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
3906846b4da1SFande Kong {
3907846b4da1SFande Kong   Mat_SeqAIJ     *a;
3908a5bbaf83SFande Kong   PetscInt       i;
3909846b4da1SFande Kong   PetscErrorCode ierr;
3910846b4da1SFande Kong 
3911846b4da1SFande Kong   PetscFunctionBegin;
3912846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
391314d0e64fSAlex Lindsay 
391414d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
391514d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
391614d0e64fSAlex Lindsay 
3917846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
39182c814fdeSFande Kong   /* if no saved info, we error out */
3919fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
39202c814fdeSFande Kong 
3921fb4dc15dSAlex 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");
39222c814fdeSFande Kong 
3923580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
3924580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
3925846b4da1SFande Kong   a->i[0] = 0;
3926846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
3927846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
3928846b4da1SFande Kong   }
3929846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
3930846b4da1SFande Kong   a->nz               = 0;
3931846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
3932846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
3933846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
3934846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
3935846b4da1SFande Kong   PetscFunctionReturn(0);
3936846b4da1SFande Kong }
3937846b4da1SFande Kong 
393858d36128SBarry Smith /*@
3939a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
3940a1661176SMatthew Knepley 
3941a1661176SMatthew Knepley    Input Parameters:
3942a1661176SMatthew Knepley +  B - the matrix
3943a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
3944a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
3945a1661176SMatthew Knepley -  v - optional values in the matrix
3946a1661176SMatthew Knepley 
3947a1661176SMatthew Knepley    Level: developer
3948a1661176SMatthew Knepley 
394958d36128SBarry Smith    The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
395058d36128SBarry Smith 
3951c1c1d628SHong Zhang .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ
3952a1661176SMatthew Knepley @*/
3953a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
3954a1661176SMatthew Knepley {
3955a1661176SMatthew Knepley   PetscErrorCode ierr;
3956a1661176SMatthew Knepley 
3957a1661176SMatthew Knepley   PetscFunctionBegin;
39580700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
39596ba663aaSJed Brown   PetscValidType(B,1);
39604ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
3961a1661176SMatthew Knepley   PetscFunctionReturn(0);
3962a1661176SMatthew Knepley }
3963a1661176SMatthew Knepley 
39647087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
3965a1661176SMatthew Knepley {
3966a1661176SMatthew Knepley   PetscInt       i;
3967a1661176SMatthew Knepley   PetscInt       m,n;
3968a1661176SMatthew Knepley   PetscInt       nz;
3969a1661176SMatthew Knepley   PetscInt       *nnz, nz_max = 0;
3970a1661176SMatthew Knepley   PetscErrorCode ierr;
3971a1661176SMatthew Knepley 
3972a1661176SMatthew Knepley   PetscFunctionBegin;
397365e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
3974779a8d59SSatish Balay 
3975779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
3976779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
3977779a8d59SSatish Balay 
3978779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
3979854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
3980a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
3981b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
3982a1661176SMatthew Knepley     nz_max = PetscMax(nz_max, nz);
398365e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
3984a1661176SMatthew Knepley     nnz[i] = nz;
3985a1661176SMatthew Knepley   }
3986a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
3987a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
3988a1661176SMatthew Knepley 
3989a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
3990071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
3991a1661176SMatthew Knepley   }
3992a1661176SMatthew Knepley 
3993a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3994a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3995a1661176SMatthew Knepley 
39967827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
3997a1661176SMatthew Knepley   PetscFunctionReturn(0);
3998a1661176SMatthew Knepley }
3999a1661176SMatthew Knepley 
4000c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4001af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4002170fe5c8SBarry Smith 
4003170fe5c8SBarry Smith /*
4004170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4005170fe5c8SBarry Smith 
4006170fe5c8SBarry Smith                n                       p                          p
4007170fe5c8SBarry Smith         (              )       (              )         (                  )
4008170fe5c8SBarry Smith       m (      A       )  *  n (       B      )   =   m (         C        )
4009170fe5c8SBarry Smith         (              )       (              )         (                  )
4010170fe5c8SBarry Smith 
4011170fe5c8SBarry Smith */
4012170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4013170fe5c8SBarry Smith {
4014170fe5c8SBarry Smith   PetscErrorCode    ierr;
4015170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4016170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4017170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
40181de00fd4SBarry Smith   PetscInt          i,n,m,q,p;
4019170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4020170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4021170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
4022170fe5c8SBarry Smith 
4023170fe5c8SBarry Smith   PetscFunctionBegin;
4024d0f46423SBarry Smith   m    = A->rmap->n;
4025d0f46423SBarry Smith   n    = A->cmap->n;
4026d0f46423SBarry Smith   p    = B->cmap->n;
4027170fe5c8SBarry Smith   a    = sub_a->v;
4028170fe5c8SBarry Smith   b    = sub_b->a;
4029170fe5c8SBarry Smith   c    = sub_c->v;
4030580bdb30SBarry Smith   ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
4031170fe5c8SBarry Smith 
4032170fe5c8SBarry Smith   ii  = sub_b->i;
4033170fe5c8SBarry Smith   idx = sub_b->j;
4034170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4035170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4036170fe5c8SBarry Smith     while (q-->0) {
4037170fe5c8SBarry Smith       c_q = c + m*(*idx);
4038170fe5c8SBarry Smith       a_q = a + m*i;
4039854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4040170fe5c8SBarry Smith       idx++;
4041170fe5c8SBarry Smith       b++;
4042170fe5c8SBarry Smith     }
4043170fe5c8SBarry Smith   }
4044170fe5c8SBarry Smith   PetscFunctionReturn(0);
4045170fe5c8SBarry Smith }
4046170fe5c8SBarry Smith 
4047170fe5c8SBarry Smith PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C)
4048170fe5c8SBarry Smith {
4049170fe5c8SBarry Smith   PetscErrorCode ierr;
4050d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
4051170fe5c8SBarry Smith   Mat            Cmat;
4052170fe5c8SBarry Smith 
4053170fe5c8SBarry Smith   PetscFunctionBegin;
405460e0710aSBarry 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);
4055ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),&Cmat);CHKERRQ(ierr);
4056170fe5c8SBarry Smith   ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr);
405733d57670SJed Brown   ierr = MatSetBlockSizesFromMats(Cmat,A,B);CHKERRQ(ierr);
4058170fe5c8SBarry Smith   ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr);
40590298fd71SBarry Smith   ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr);
4060d73949e8SHong Zhang 
4061d73949e8SHong Zhang   Cmat->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
40622205254eSKarl Rupp 
4063170fe5c8SBarry Smith   *C = Cmat;
4064170fe5c8SBarry Smith   PetscFunctionReturn(0);
4065170fe5c8SBarry Smith }
4066170fe5c8SBarry Smith 
4067170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
4068150d2497SBarry Smith PETSC_INTERN PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
4069170fe5c8SBarry Smith {
4070170fe5c8SBarry Smith   PetscErrorCode ierr;
4071170fe5c8SBarry Smith 
4072170fe5c8SBarry Smith   PetscFunctionBegin;
4073170fe5c8SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
40743ff4c91cSHong Zhang     ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
4075170fe5c8SBarry Smith     ierr = MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);CHKERRQ(ierr);
40763ff4c91cSHong Zhang     ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
4077170fe5c8SBarry Smith   }
40783ff4c91cSHong Zhang   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
4079170fe5c8SBarry Smith   ierr = MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);CHKERRQ(ierr);
40803ff4c91cSHong Zhang   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
4081170fe5c8SBarry Smith   PetscFunctionReturn(0);
4082170fe5c8SBarry Smith }
4083170fe5c8SBarry Smith 
4084170fe5c8SBarry Smith 
40850bad9183SKris Buschelman /*MC
4086fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
40870bad9183SKris Buschelman    based on compressed sparse row format.
40880bad9183SKris Buschelman 
40890bad9183SKris Buschelman    Options Database Keys:
40900bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
40910bad9183SKris Buschelman 
40920bad9183SKris Buschelman   Level: beginner
40930bad9183SKris Buschelman 
4094f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
40950bad9183SKris Buschelman M*/
40960bad9183SKris Buschelman 
4097ccd284c7SBarry Smith /*MC
4098ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4099ccd284c7SBarry Smith 
4100ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4101ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
4102ccd284c7SBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation is supported
4103ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4104ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4105ccd284c7SBarry Smith 
4106ccd284c7SBarry Smith    Options Database Keys:
4107ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4108ccd284c7SBarry Smith 
410995452b02SPatrick Sanan   Developer Notes:
4110ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4111ccd284c7SBarry Smith    enough exist.
4112ccd284c7SBarry Smith 
4113ccd284c7SBarry Smith   Level: beginner
4114ccd284c7SBarry Smith 
4115ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4116ccd284c7SBarry Smith M*/
4117ccd284c7SBarry Smith 
4118ccd284c7SBarry Smith /*MC
4119ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4120ccd284c7SBarry Smith 
4121ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4122ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4123ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4124ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4125ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4126ccd284c7SBarry Smith 
4127ccd284c7SBarry Smith    Options Database Keys:
4128ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4129ccd284c7SBarry Smith 
4130ccd284c7SBarry Smith   Level: beginner
4131ccd284c7SBarry Smith 
4132ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4133ccd284c7SBarry Smith M*/
4134ccd284c7SBarry Smith 
41357906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
41367906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
41377906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
41387906f579SHong Zhang #endif
41397906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
41407906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
41417906f579SHong Zhang PETSC_INTERN PetscErrorCode MatMatMatMult_Transpose_AIJ_AIJ(Mat,Mat,Mat,MatReuse,PetscReal,Mat*);
41427906f579SHong Zhang #endif
41437906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat,MatType,MatReuse,Mat*);
41447906f579SHong Zhang 
4145d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4146c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
414775d48cdbSStefano Zampini PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat,Mat,MatReuse,PetscReal,Mat*);
41487906f579SHong Zhang 
41498c778c55SBarry Smith /*@C
41508397e458SBarry Smith    MatSeqAIJGetArray - gives access to the array where the data for a MATSEQAIJ matrix is stored
41518c778c55SBarry Smith 
41528c778c55SBarry Smith    Not Collective
41538c778c55SBarry Smith 
41548c778c55SBarry Smith    Input Parameter:
4155579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
41568c778c55SBarry Smith 
41578c778c55SBarry Smith    Output Parameter:
41588c778c55SBarry Smith .   array - pointer to the data
41598c778c55SBarry Smith 
41608c778c55SBarry Smith    Level: intermediate
41618c778c55SBarry Smith 
4162774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
41638c778c55SBarry Smith @*/
41648c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
41658c778c55SBarry Smith {
41668c778c55SBarry Smith   PetscErrorCode ierr;
41678c778c55SBarry Smith 
41688c778c55SBarry Smith   PetscFunctionBegin;
41698c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
41708c778c55SBarry Smith   PetscFunctionReturn(0);
41718c778c55SBarry Smith }
41728c778c55SBarry Smith 
417321e72a00SBarry Smith /*@C
417421e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
417521e72a00SBarry Smith 
417621e72a00SBarry Smith    Not Collective
417721e72a00SBarry Smith 
417821e72a00SBarry Smith    Input Parameter:
4179579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
418021e72a00SBarry Smith 
418121e72a00SBarry Smith    Output Parameter:
418221e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
418321e72a00SBarry Smith 
418421e72a00SBarry Smith    Level: intermediate
418521e72a00SBarry Smith 
418621e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
418721e72a00SBarry Smith @*/
418821e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
418921e72a00SBarry Smith {
419021e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
419121e72a00SBarry Smith 
419221e72a00SBarry Smith   PetscFunctionBegin;
419321e72a00SBarry Smith   *nz = aij->rmax;
419421e72a00SBarry Smith   PetscFunctionReturn(0);
419521e72a00SBarry Smith }
419621e72a00SBarry Smith 
41978c778c55SBarry Smith /*@C
4198579dbff0SBarry Smith    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
41998c778c55SBarry Smith 
42008c778c55SBarry Smith    Not Collective
42018c778c55SBarry Smith 
42028c778c55SBarry Smith    Input Parameters:
4203a2b725a8SWilliam Gropp +  mat - a MATSEQAIJ matrix
4204a2b725a8SWilliam Gropp -  array - pointer to the data
42058c778c55SBarry Smith 
42068c778c55SBarry Smith    Level: intermediate
42078c778c55SBarry Smith 
4208774cf152SJed Brown .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
42098c778c55SBarry Smith @*/
42108c778c55SBarry Smith PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
42118c778c55SBarry Smith {
42128c778c55SBarry Smith   PetscErrorCode ierr;
42138c778c55SBarry Smith 
42148c778c55SBarry Smith   PetscFunctionBegin;
42158c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
42168c778c55SBarry Smith   PetscFunctionReturn(0);
42178c778c55SBarry Smith }
42188c778c55SBarry Smith 
421934b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
422002fe1965SBarry Smith PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat);
422102fe1965SBarry Smith #endif
422202fe1965SBarry Smith 
42238cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4224273d9f13SBarry Smith {
4225273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4226dfbe8321SBarry Smith   PetscErrorCode ierr;
422738baddfdSBarry Smith   PetscMPIInt    size;
4228273d9f13SBarry Smith 
4229273d9f13SBarry Smith   PetscFunctionBegin;
4230ce94432eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr);
4231e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4232273d9f13SBarry Smith 
4233b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
42342205254eSKarl Rupp 
4235b0a32e0cSBarry Smith   B->data = (void*)b;
42362205254eSKarl Rupp 
4237549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4238071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
42392205254eSKarl Rupp 
4240416022c9SBarry Smith   b->row                = 0;
4241416022c9SBarry Smith   b->col                = 0;
424282bf6240SBarry Smith   b->icol               = 0;
4243b810aeb4SBarry Smith   b->reallocs           = 0;
424436db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4245f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4246416022c9SBarry Smith   b->nonew              = 0;
4247416022c9SBarry Smith   b->diag               = 0;
4248416022c9SBarry Smith   b->solve_work         = 0;
42492a1b7f2aSHong Zhang   B->spptr              = 0;
4250be6bf707SBarry Smith   b->saved_values       = 0;
4251d7f994e1SBarry Smith   b->idiag              = 0;
425271f1c65dSBarry Smith   b->mdiag              = 0;
425371f1c65dSBarry Smith   b->ssor_work          = 0;
425471f1c65dSBarry Smith   b->omega              = 1.0;
425571f1c65dSBarry Smith   b->fshift             = 0.0;
425671f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4257bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4258a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
425917ab2063SBarry Smith 
426035d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4261bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr);
4262bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr);
42638c778c55SBarry Smith 
4264b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4265bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4266bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4267b3866ffcSBarry Smith #endif
426817f1a0eaSHong Zhang 
4269bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4270bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4271bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4272bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4273bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4274bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
42754dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
42769779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
42774a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4278191b95cbSRichard Tran Mills #endif
427934b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
428002fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
428102fe1965SBarry Smith #endif
4282bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4283af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4284af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4285af8000cdSHong Zhang #endif
428663c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
428763c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
42883dad0653Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMatMult_transpose_seqaij_seqaij_C",MatMatMatMult_Transpose_AIJ_AIJ);CHKERRQ(ierr);
428963c07aadSStefano Zampini #endif
4290b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4291d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4292c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4293bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4294bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4295bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4296846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4297bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4298bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
4299bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqdense_seqaij_C",MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr);
4300bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C",MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr);
4301bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C",MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr);
430275d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_is_seqaij_C",MatPtAP_IS_XAIJ);CHKERRQ(ierr);
43034108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
430417667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
43054099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
43063a40ed3dSBarry Smith   PetscFunctionReturn(0);
430717ab2063SBarry Smith }
430817ab2063SBarry Smith 
4309b24902e0SBarry Smith /*
4310b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4311b24902e0SBarry Smith */
4312ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
431317ab2063SBarry Smith {
4314416022c9SBarry Smith   Mat_SeqAIJ     *c,*a = (Mat_SeqAIJ*)A->data;
43156849ba73SBarry Smith   PetscErrorCode ierr;
4316071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
431717ab2063SBarry Smith 
43183a40ed3dSBarry Smith   PetscFunctionBegin;
4319273d9f13SBarry Smith   c = (Mat_SeqAIJ*)C->data;
4320273d9f13SBarry Smith 
4321d5f3da31SBarry Smith   C->factortype = A->factortype;
4322416022c9SBarry Smith   c->row        = 0;
4323416022c9SBarry Smith   c->col        = 0;
432482bf6240SBarry Smith   c->icol       = 0;
43256ad4291fSHong Zhang   c->reallocs   = 0;
432617ab2063SBarry Smith 
43276ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
432817ab2063SBarry Smith 
4329aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4330aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4331eec197d1SBarry Smith 
4332071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4333071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4334071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4335071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
43363bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
433717ab2063SBarry Smith 
433817ab2063SBarry Smith   /* allocate the matrix space */
4339f77e22a1SHong Zhang   if (mallocmatspace) {
4340dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
43413bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
43422205254eSKarl Rupp 
4343f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
43442205254eSKarl Rupp 
4345580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
434617ab2063SBarry Smith     if (m > 0) {
4347580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4348be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
4349580bdb30SBarry Smith         ierr = PetscArraycpy(c->a,a->a,a->i[m]);CHKERRQ(ierr);
4350be6bf707SBarry Smith       } else {
4351580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
435217ab2063SBarry Smith       }
435308480c60SBarry Smith     }
4354f77e22a1SHong Zhang   }
435517ab2063SBarry Smith 
43566ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4357416022c9SBarry Smith   c->roworiented       = a->roworiented;
4358416022c9SBarry Smith   c->nonew             = a->nonew;
4359416022c9SBarry Smith   if (a->diag) {
4360854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4361071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
43623bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4363071fcb05SBarry Smith   } else c->diag = NULL;
43642205254eSKarl Rupp 
43656ad4291fSHong Zhang   c->solve_work         = 0;
43666ad4291fSHong Zhang   c->saved_values       = 0;
43676ad4291fSHong Zhang   c->idiag              = 0;
436871f1c65dSBarry Smith   c->ssor_work          = 0;
4369a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4370e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4371e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
43726ad4291fSHong Zhang 
4373893ad86cSHong Zhang   c->rmax         = a->rmax;
4374416022c9SBarry Smith   c->nz           = a->nz;
43758ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4376273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4377754ec7b1SSatish Balay 
43786ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
43796ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4380cd6b891eSBarry Smith   if (a->compressedrow.use) {
43816ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4382dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4383580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4384580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
438527ea64f8SHong Zhang   } else {
438627ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
43870298fd71SBarry Smith     c->compressedrow.i      = NULL;
43880298fd71SBarry Smith     c->compressedrow.rindex = NULL;
43896ad4291fSHong Zhang   }
4390ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4391e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
43924846f1f5SKris Buschelman 
43932205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4394140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
43953a40ed3dSBarry Smith   PetscFunctionReturn(0);
439617ab2063SBarry Smith }
439717ab2063SBarry Smith 
4398b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4399b24902e0SBarry Smith {
4400b24902e0SBarry Smith   PetscErrorCode ierr;
4401b24902e0SBarry Smith 
4402b24902e0SBarry Smith   PetscFunctionBegin;
4403ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
44044b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4405cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
440633d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4407cfd3f464SBarry Smith   }
4408a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4409f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4410b24902e0SBarry Smith   PetscFunctionReturn(0);
4411b24902e0SBarry Smith }
4412b24902e0SBarry Smith 
4413112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4414fbdbba38SShri Abhyankar {
441552f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
441652f91c60SVaclav Hapla   PetscErrorCode ierr;
441752f91c60SVaclav Hapla 
441852f91c60SVaclav Hapla   PetscFunctionBegin;
441952f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
442052f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4421c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4422c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
442352f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
442452f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
442552f91c60SVaclav Hapla   if (isbinary) {
442652f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
442752f91c60SVaclav Hapla   } else if (ishdf5) {
442852f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
442952f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
443052f91c60SVaclav Hapla #else
443152f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
443252f91c60SVaclav Hapla #endif
443352f91c60SVaclav Hapla   } else {
443452f91c60SVaclav 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);
443552f91c60SVaclav Hapla   }
443652f91c60SVaclav Hapla   PetscFunctionReturn(0);
443752f91c60SVaclav Hapla }
443852f91c60SVaclav Hapla 
443952f91c60SVaclav Hapla PetscErrorCode MatLoad_SeqAIJ_Binary(Mat newMat, PetscViewer viewer)
444052f91c60SVaclav Hapla {
4441fbdbba38SShri Abhyankar   Mat_SeqAIJ     *a;
4442fbdbba38SShri Abhyankar   PetscErrorCode ierr;
4443fbdbba38SShri Abhyankar   PetscInt       i,sum,nz,header[4],*rowlengths = 0,M,N,rows,cols;
4444fbdbba38SShri Abhyankar   int            fd;
4445fbdbba38SShri Abhyankar   PetscMPIInt    size;
4446fbdbba38SShri Abhyankar   MPI_Comm       comm;
44473059b6faSBarry Smith   PetscInt       bs = newMat->rmap->bs;
4448fbdbba38SShri Abhyankar 
4449fbdbba38SShri Abhyankar   PetscFunctionBegin;
4450fbdbba38SShri Abhyankar   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
4451fbdbba38SShri Abhyankar   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
4452fbdbba38SShri Abhyankar   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor");
4453bbead8a2SBarry Smith 
44540298fd71SBarry Smith   ierr = PetscOptionsBegin(comm,NULL,"Options for loading SEQAIJ matrix","Mat");CHKERRQ(ierr);
44550298fd71SBarry Smith   ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,NULL);CHKERRQ(ierr);
4456bbead8a2SBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
44573059b6faSBarry Smith   if (bs < 0) bs = 1;
44583059b6faSBarry Smith   ierr = MatSetBlockSize(newMat,bs);CHKERRQ(ierr);
4459bbead8a2SBarry Smith 
4460fbdbba38SShri Abhyankar   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
44619860990eSLisandro Dalcin   ierr = PetscBinaryRead(fd,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
4462fbdbba38SShri Abhyankar   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
4463fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
4464fbdbba38SShri Abhyankar 
4465bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
4466fbdbba38SShri Abhyankar 
4467fbdbba38SShri Abhyankar   /* read in row lengths */
4468785e854fSJed Brown   ierr = PetscMalloc1(M,&rowlengths);CHKERRQ(ierr);
44699860990eSLisandro Dalcin   ierr = PetscBinaryRead(fd,rowlengths,M,NULL,PETSC_INT);CHKERRQ(ierr);
4470fbdbba38SShri Abhyankar 
4471fbdbba38SShri Abhyankar   /* check if sum of rowlengths is same as nz */
4472fbdbba38SShri Abhyankar   for (i=0,sum=0; i< M; i++) sum +=rowlengths[i];
447360e0710aSBarry Smith   if (sum != nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Inconsistant matrix data in file. no-nonzeros = %dD, sum-row-lengths = %D\n",nz,sum);
4474fbdbba38SShri Abhyankar 
4475fbdbba38SShri Abhyankar   /* set global size if not set already*/
4476f501eaabSShri Abhyankar   if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) {
4477fbdbba38SShri Abhyankar     ierr = MatSetSizes(newMat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
4478aabbc4fbSShri Abhyankar   } else {
44799d36ed5fSBarry Smith     /* if sizes and type are already set, check if the matrix  global sizes are correct */
4480fbdbba38SShri Abhyankar     ierr = MatGetSize(newMat,&rows,&cols);CHKERRQ(ierr);
44814c5b953cSHong Zhang     if (rows < 0 && cols < 0) { /* user might provide local size instead of global size */
44824c5b953cSHong Zhang       ierr = MatGetLocalSize(newMat,&rows,&cols);CHKERRQ(ierr);
44834c5b953cSHong Zhang     }
448460e0710aSBarry 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);
4485aabbc4fbSShri Abhyankar   }
4486fbdbba38SShri Abhyankar   ierr = MatSeqAIJSetPreallocation_SeqAIJ(newMat,0,rowlengths);CHKERRQ(ierr);
4487fbdbba38SShri Abhyankar   a    = (Mat_SeqAIJ*)newMat->data;
4488fbdbba38SShri Abhyankar 
44899860990eSLisandro Dalcin   ierr = PetscBinaryRead(fd,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
4490fbdbba38SShri Abhyankar 
4491fbdbba38SShri Abhyankar   /* read in nonzero values */
44929860990eSLisandro Dalcin   ierr = PetscBinaryRead(fd,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4493fbdbba38SShri Abhyankar 
4494fbdbba38SShri Abhyankar   /* set matrix "i" values */
4495fbdbba38SShri Abhyankar   a->i[0] = 0;
4496fbdbba38SShri Abhyankar   for (i=1; i<= M; i++) {
4497fbdbba38SShri Abhyankar     a->i[i]      = a->i[i-1] + rowlengths[i-1];
4498fbdbba38SShri Abhyankar     a->ilen[i-1] = rowlengths[i-1];
4499fbdbba38SShri Abhyankar   }
4500fbdbba38SShri Abhyankar   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
4501fbdbba38SShri Abhyankar 
4502fbdbba38SShri Abhyankar   ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4503fbdbba38SShri Abhyankar   ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4504fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4505fbdbba38SShri Abhyankar }
4506fbdbba38SShri Abhyankar 
4507ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
45087264ac53SSatish Balay {
45097264ac53SSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4510dfbe8321SBarry Smith   PetscErrorCode ierr;
4511eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4512eeffb40dSHong Zhang   PetscInt k;
4513eeffb40dSHong Zhang #endif
45147264ac53SSatish Balay 
45153a40ed3dSBarry Smith   PetscFunctionBegin;
4516bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4517d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4518ca44d042SBarry Smith     *flg = PETSC_FALSE;
4519ca44d042SBarry Smith     PetscFunctionReturn(0);
4520bcd2baecSBarry Smith   }
45217264ac53SSatish Balay 
45227264ac53SSatish Balay   /* if the a->i are the same */
4523580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4524abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
45257264ac53SSatish Balay 
45267264ac53SSatish Balay   /* if a->j are the same */
4527580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
4528abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
4529bcd2baecSBarry Smith 
4530bcd2baecSBarry Smith   /* if a->a are the same */
4531eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4532eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
4533eeffb40dSHong Zhang     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) {
4534eeffb40dSHong Zhang       *flg = PETSC_FALSE;
45353a40ed3dSBarry Smith       PetscFunctionReturn(0);
4536eeffb40dSHong Zhang     }
4537eeffb40dSHong Zhang   }
4538eeffb40dSHong Zhang #else
4539580bdb30SBarry Smith   ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr);
4540eeffb40dSHong Zhang #endif
4541eeffb40dSHong Zhang   PetscFunctionReturn(0);
45427264ac53SSatish Balay }
454336db0b34SBarry Smith 
454405869f15SSatish Balay /*@
454536db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
454636db0b34SBarry Smith               provided by the user.
454736db0b34SBarry Smith 
4548d083f849SBarry Smith       Collective
454936db0b34SBarry Smith 
455036db0b34SBarry Smith    Input Parameters:
455136db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
455236db0b34SBarry Smith .   m - number of rows
455336db0b34SBarry Smith .   n - number of columns
4554483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
455536db0b34SBarry Smith .   j - column indices
455636db0b34SBarry Smith -   a - matrix values
455736db0b34SBarry Smith 
455836db0b34SBarry Smith    Output Parameter:
455936db0b34SBarry Smith .   mat - the matrix
456036db0b34SBarry Smith 
456136db0b34SBarry Smith    Level: intermediate
456236db0b34SBarry Smith 
456336db0b34SBarry Smith    Notes:
45640551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
4565292fb18eSBarry Smith     once the matrix is destroyed and not before
456636db0b34SBarry Smith 
456736db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
456836db0b34SBarry Smith 
4569bfeeae90SHong Zhang        The i and j indices are 0 based
457036db0b34SBarry Smith 
4571a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
4572a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
45738eef79e4SBarry Smith     as shown
4574a4552177SSatish Balay 
45758eef79e4SBarry Smith $        1 0 0
45768eef79e4SBarry Smith $        2 0 3
45778eef79e4SBarry Smith $        4 5 6
45788eef79e4SBarry Smith $
45798eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
45808eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
45818eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
4582a4552177SSatish Balay 
45839985e31cSBarry Smith 
458469b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
458536db0b34SBarry Smith 
458636db0b34SBarry Smith @*/
4587c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
458836db0b34SBarry Smith {
4589dfbe8321SBarry Smith   PetscErrorCode ierr;
4590cbcfb4deSHong Zhang   PetscInt       ii;
459136db0b34SBarry Smith   Mat_SeqAIJ     *aij;
4592cbcfb4deSHong Zhang #if defined(PETSC_USE_DEBUG)
4593cbcfb4deSHong Zhang   PetscInt jj;
4594cbcfb4deSHong Zhang #endif
459536db0b34SBarry Smith 
459636db0b34SBarry Smith   PetscFunctionBegin;
459741096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4598f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
4599f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
4600a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
4601ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
4602ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr);
4603ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
4604071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
4605071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
4606ab93d7beSBarry Smith 
460736db0b34SBarry Smith   aij->i            = i;
460836db0b34SBarry Smith   aij->j            = j;
460936db0b34SBarry Smith   aij->a            = a;
461036db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
461136db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4612e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
4613e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
461436db0b34SBarry Smith 
461536db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
461636db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
46172515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
461860e0710aSBarry 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]);
46199985e31cSBarry Smith     for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4620a061629eSStefano 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);
4621a061629eSStefano 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);
46229985e31cSBarry Smith     }
462336db0b34SBarry Smith #endif
462436db0b34SBarry Smith   }
46252515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
462636db0b34SBarry Smith   for (ii=0; ii<aij->i[m]; ii++) {
462760e0710aSBarry Smith     if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
462860e0710aSBarry 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]);
462936db0b34SBarry Smith   }
463036db0b34SBarry Smith #endif
463136db0b34SBarry Smith 
4632b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4633b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
463436db0b34SBarry Smith   PetscFunctionReturn(0);
463536db0b34SBarry Smith }
463680ef6e79SMatthew G Knepley /*@C
4637d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
46388a0b0e6bSVictor Minden               provided by the user.
46398a0b0e6bSVictor Minden 
4640d083f849SBarry Smith       Collective
46418a0b0e6bSVictor Minden 
46428a0b0e6bSVictor Minden    Input Parameters:
46438a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
46448a0b0e6bSVictor Minden .   m   - number of rows
46458a0b0e6bSVictor Minden .   n   - number of columns
46468a0b0e6bSVictor Minden .   i   - row indices
46478a0b0e6bSVictor Minden .   j   - column indices
46481230e6d1SVictor Minden .   a   - matrix values
46491230e6d1SVictor Minden .   nz  - number of nonzeros
46501230e6d1SVictor Minden -   idx - 0 or 1 based
46518a0b0e6bSVictor Minden 
46528a0b0e6bSVictor Minden    Output Parameter:
46538a0b0e6bSVictor Minden .   mat - the matrix
46548a0b0e6bSVictor Minden 
46558a0b0e6bSVictor Minden    Level: intermediate
46568a0b0e6bSVictor Minden 
46578a0b0e6bSVictor Minden    Notes:
46588a0b0e6bSVictor Minden        The i and j indices are 0 based
46598a0b0e6bSVictor Minden 
46608a0b0e6bSVictor Minden        The format which is used for the sparse matrix input, is equivalent to a
46618a0b0e6bSVictor Minden     row-major ordering.. i.e for the following matrix, the input data expected is
46628a0b0e6bSVictor Minden     as shown:
46638a0b0e6bSVictor Minden 
46648a0b0e6bSVictor Minden         1 0 0
46658a0b0e6bSVictor Minden         2 0 3
46668a0b0e6bSVictor Minden         4 5 6
46678a0b0e6bSVictor Minden 
46688a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
46698a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
46708a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
46718a0b0e6bSVictor Minden 
46728a0b0e6bSVictor Minden 
467369b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
46748a0b0e6bSVictor Minden 
46758a0b0e6bSVictor Minden @*/
4676c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
46778a0b0e6bSVictor Minden {
46788a0b0e6bSVictor Minden   PetscErrorCode ierr;
4679d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
46808a0b0e6bSVictor Minden 
46818a0b0e6bSVictor Minden 
46828a0b0e6bSVictor Minden   PetscFunctionBegin;
46831795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
46841230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
4685c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
46861230e6d1SVictor Minden   }
46878a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
46888a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
46898a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
46901230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
46911230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
46921230e6d1SVictor Minden     if (idx) {
46931230e6d1SVictor Minden       row = i[ii] - 1;
46941230e6d1SVictor Minden       col = j[ii] - 1;
46951230e6d1SVictor Minden     } else {
46961230e6d1SVictor Minden       row = i[ii];
46971230e6d1SVictor Minden       col = j[ii];
46988a0b0e6bSVictor Minden     }
46991230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
47008a0b0e6bSVictor Minden   }
47018a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
47028a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4703d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
47048a0b0e6bSVictor Minden   PetscFunctionReturn(0);
47058a0b0e6bSVictor Minden }
470636db0b34SBarry Smith 
4707acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
4708acf2f550SJed Brown {
4709acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
4710acf2f550SJed Brown   PetscErrorCode ierr;
4711acf2f550SJed Brown 
4712acf2f550SJed Brown   PetscFunctionBegin;
4713acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
4714acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
47152205254eSKarl Rupp 
4716acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
4717acf2f550SJed Brown   PetscFunctionReturn(0);
4718acf2f550SJed Brown }
4719acf2f550SJed Brown 
47209c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
47219c8f2541SHong Zhang {
47229c8f2541SHong Zhang   PetscErrorCode ierr;
47238761c3d6SHong Zhang   PetscMPIInt    size;
47249c8f2541SHong Zhang 
47259c8f2541SHong Zhang   PetscFunctionBegin;
47268761c3d6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
47277bbdc51dSHong Zhang   if (size == 1) {
47287bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
47297bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
47307bbdc51dSHong Zhang     } else {
47318761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
47327bbdc51dSHong Zhang     }
47338761c3d6SHong Zhang   } else {
47349c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
47358761c3d6SHong Zhang   }
47369c8f2541SHong Zhang   PetscFunctionReturn(0);
47379c8f2541SHong Zhang }
47389c8f2541SHong Zhang 
473981824310SBarry Smith /*
474053dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
474153dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
474253dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
474353dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
474453dd7562SDmitry Karpeev  */
474553dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
474653dd7562SDmitry Karpeev {
474753dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
474853dd7562SDmitry Karpeev   PetscErrorCode ierr;
474953dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
475053dd7562SDmitry Karpeev   PetscBool      seqaij;
475153dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
475253dd7562SDmitry Karpeev   PetscScalar    v;
475353dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
475453dd7562SDmitry Karpeev 
475553dd7562SDmitry Karpeev   PetscFunctionBegin;
475653dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
475753dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
47584099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
475953dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
476053dd7562SDmitry Karpeev   if (rowemb) {
476153dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
476253dd7562SDmitry 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);
476353dd7562SDmitry Karpeev   } else {
47646c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
476553dd7562SDmitry Karpeev   }
476653dd7562SDmitry Karpeev   if (colemb) {
476753dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
476853dd7562SDmitry 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);
476953dd7562SDmitry Karpeev   } else {
477053dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
477153dd7562SDmitry Karpeev   }
477253dd7562SDmitry Karpeev 
477353dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
477453dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
477553dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
477653dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
477753dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
477853dd7562SDmitry Karpeev     }
477953dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
478053dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
478153dd7562SDmitry Karpeev   }
478253dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
478353dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
478453dd7562SDmitry Karpeev   }
478553dd7562SDmitry Karpeev   count = 0;
478653dd7562SDmitry Karpeev   rowindices = NULL;
478753dd7562SDmitry Karpeev   colindices = NULL;
478853dd7562SDmitry Karpeev   if (rowemb) {
478953dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
479053dd7562SDmitry Karpeev   }
479153dd7562SDmitry Karpeev   if (colemb) {
479253dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
479353dd7562SDmitry Karpeev   }
479453dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
479553dd7562SDmitry Karpeev     PetscInt row;
479653dd7562SDmitry Karpeev     row = i;
479753dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
479853dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
479953dd7562SDmitry Karpeev       PetscInt col;
480053dd7562SDmitry Karpeev       col  = Baij->j[count];
480153dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
480253dd7562SDmitry Karpeev       v    = Baij->a[count];
480353dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
480453dd7562SDmitry Karpeev       ++count;
480553dd7562SDmitry Karpeev     }
480653dd7562SDmitry Karpeev   }
480753dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
480853dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
480953dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
481053dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
481153dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
481253dd7562SDmitry Karpeev   PetscFunctionReturn(0);
481353dd7562SDmitry Karpeev }
481453dd7562SDmitry Karpeev 
48154099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
48164099cc6bSBarry Smith 
48174099cc6bSBarry Smith /*@C
48184099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
48194099cc6bSBarry Smith 
48204099cc6bSBarry Smith    Collective on Mat
48214099cc6bSBarry Smith 
48224099cc6bSBarry Smith    Input Parameters:
48234099cc6bSBarry Smith +  mat      - the matrix object
48244099cc6bSBarry Smith -  matype   - matrix type
48254099cc6bSBarry Smith 
48264099cc6bSBarry Smith    Options Database Key:
48274099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
48284099cc6bSBarry Smith 
48294099cc6bSBarry Smith 
48304099cc6bSBarry Smith   Level: intermediate
48314099cc6bSBarry Smith 
48324099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
48334099cc6bSBarry Smith @*/
48344099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
48354099cc6bSBarry Smith {
4836fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
48374099cc6bSBarry Smith   PetscBool      sametype;
48384099cc6bSBarry Smith 
48394099cc6bSBarry Smith   PetscFunctionBegin;
48404099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
48414099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
48424099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
48434099cc6bSBarry Smith 
48444099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
48454099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
48464099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
48474099cc6bSBarry Smith   PetscFunctionReturn(0);
48484099cc6bSBarry Smith }
48494099cc6bSBarry Smith 
48504099cc6bSBarry Smith 
48514099cc6bSBarry Smith /*@C
48524099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
48534099cc6bSBarry Smith 
48544099cc6bSBarry Smith    Not Collective
48554099cc6bSBarry Smith 
48564099cc6bSBarry Smith    Input Parameters:
48574099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
48584099cc6bSBarry Smith -  function - routine to convert to subtype
48594099cc6bSBarry Smith 
48604099cc6bSBarry Smith    Notes:
48614099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
48624099cc6bSBarry Smith 
48634099cc6bSBarry Smith 
48644099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
48654099cc6bSBarry Smith $     -mat_seqaij_type my_mat
48664099cc6bSBarry Smith 
48674099cc6bSBarry Smith    Level: advanced
48684099cc6bSBarry Smith 
48694099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
48704099cc6bSBarry Smith 
48714099cc6bSBarry Smith 
48724099cc6bSBarry Smith   Level: advanced
48734099cc6bSBarry Smith @*/
4874388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
48754099cc6bSBarry Smith {
48764099cc6bSBarry Smith   PetscErrorCode ierr;
48774099cc6bSBarry Smith 
48784099cc6bSBarry Smith   PetscFunctionBegin;
48799cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
48804099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
48814099cc6bSBarry Smith   PetscFunctionReturn(0);
48824099cc6bSBarry Smith }
48834099cc6bSBarry Smith 
48844099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
48854099cc6bSBarry Smith 
48864099cc6bSBarry Smith /*@C
48874099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
48884099cc6bSBarry Smith 
48894099cc6bSBarry Smith   Not Collective
48904099cc6bSBarry Smith 
48914099cc6bSBarry Smith   Level: advanced
48924099cc6bSBarry Smith 
48934099cc6bSBarry Smith   Developers Note: CUSP and CUSPARSE do not yet support the  MatConvert_SeqAIJ..() paradigm and thus cannot be registered here
48944099cc6bSBarry Smith 
48954099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
48964099cc6bSBarry Smith @*/
48974099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
48984099cc6bSBarry Smith {
48994099cc6bSBarry Smith   PetscErrorCode ierr;
49004099cc6bSBarry Smith 
49014099cc6bSBarry Smith   PetscFunctionBegin;
49024099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
49034099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
49044099cc6bSBarry Smith 
49054099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
49064099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
49074dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
49089779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
49096b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4910485f9817SRichard Tran Mills #endif
49114099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
49124099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
49134099cc6bSBarry Smith #endif
49144099cc6bSBarry Smith   PetscFunctionReturn(0);
49154099cc6bSBarry Smith }
491653dd7562SDmitry Karpeev 
491753dd7562SDmitry Karpeev /*
491881824310SBarry Smith     Special version for direct calls from Fortran
491981824310SBarry Smith */
4920af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
492181824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
492281824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
492381824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
492481824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
492581824310SBarry Smith #endif
492681824310SBarry Smith 
492781824310SBarry Smith /* Change these macros so can be used in void function */
492881824310SBarry Smith #undef CHKERRQ
4929ce94432eSBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr)
493081824310SBarry Smith #undef SETERRQ2
4931e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
49324994cf47SJed Brown #undef SETERRQ3
49334994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
493481824310SBarry Smith 
49358cc058d9SJed Brown PETSC_EXTERN void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
493681824310SBarry Smith {
493781824310SBarry Smith   Mat            A  = *AA;
493881824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
493981824310SBarry Smith   InsertMode     is = *isis;
494081824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
494181824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
494281824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
494381824310SBarry Smith   PetscErrorCode ierr;
494481824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
494554f21887SBarry Smith   MatScalar      *ap,value,*aa;
4946ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
4947ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
494881824310SBarry Smith 
494981824310SBarry Smith   PetscFunctionBegin;
49504994cf47SJed Brown   MatCheckPreallocated(A,1);
495181824310SBarry Smith   imax  = a->imax;
495281824310SBarry Smith   ai    = a->i;
495381824310SBarry Smith   ailen = a->ilen;
495481824310SBarry Smith   aj    = a->j;
495581824310SBarry Smith   aa    = a->a;
495681824310SBarry Smith 
495781824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
495881824310SBarry Smith     row = im[k];
495981824310SBarry Smith     if (row < 0) continue;
496081824310SBarry Smith #if defined(PETSC_USE_DEBUG)
4961ce94432eSBarry Smith     if (row >= A->rmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
496281824310SBarry Smith #endif
496381824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
496481824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
496581824310SBarry Smith     low  = 0;
496681824310SBarry Smith     high = nrow;
496781824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
496881824310SBarry Smith       if (in[l] < 0) continue;
496981824310SBarry Smith #if defined(PETSC_USE_DEBUG)
4970ce94432eSBarry Smith       if (in[l] >= A->cmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
497181824310SBarry Smith #endif
497281824310SBarry Smith       col = in[l];
49732205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
49742205254eSKarl Rupp       else value = v[k + l*m];
49752205254eSKarl Rupp 
497681824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
497781824310SBarry Smith 
49782205254eSKarl Rupp       if (col <= lastcol) low = 0;
49792205254eSKarl Rupp       else high = nrow;
498081824310SBarry Smith       lastcol = col;
498181824310SBarry Smith       while (high-low > 5) {
498281824310SBarry Smith         t = (low+high)/2;
498381824310SBarry Smith         if (rp[t] > col) high = t;
498481824310SBarry Smith         else             low  = t;
498581824310SBarry Smith       }
498681824310SBarry Smith       for (i=low; i<high; i++) {
498781824310SBarry Smith         if (rp[i] > col) break;
498881824310SBarry Smith         if (rp[i] == col) {
498981824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
499081824310SBarry Smith           else                  ap[i] = value;
499181824310SBarry Smith           goto noinsert;
499281824310SBarry Smith         }
499381824310SBarry Smith       }
499481824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
499581824310SBarry Smith       if (nonew == 1) goto noinsert;
4996ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
4997fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
499881824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
499981824310SBarry Smith       /* shift up all the later entries in this row */
500081824310SBarry Smith       for (ii=N; ii>=i; ii--) {
500181824310SBarry Smith         rp[ii+1] = rp[ii];
500281824310SBarry Smith         ap[ii+1] = ap[ii];
500381824310SBarry Smith       }
500481824310SBarry Smith       rp[i] = col;
500581824310SBarry Smith       ap[i] = value;
5006e56f5c9eSBarry Smith       A->nonzerostate++;
500781824310SBarry Smith noinsert:;
500881824310SBarry Smith       low = i + 1;
500981824310SBarry Smith     }
501081824310SBarry Smith     ailen[row] = nrow;
501181824310SBarry Smith   }
501281824310SBarry Smith   PetscFunctionReturnVoid();
501381824310SBarry Smith }
5014