xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 026e39d04bcf2a445c0a9332c845c324154b2e8f)
16d84be18SBarry Smith 
26945ee14SBarry Smith 
317ab2063SBarry Smith #ifndef lint
4*026e39d0SSatish Balay static char vcid[] = "$Id: aij.c,v 1.199 1996/12/02 20:20:36 balay Exp balay $";
517ab2063SBarry Smith #endif
617ab2063SBarry Smith 
7d5d45c9bSBarry Smith /*
85a838052SSatish Balay B    Defines the basic matrix operations for the AIJ (compressed row)
9d5d45c9bSBarry Smith   matrix storage format.
10d5d45c9bSBarry Smith */
1170f55243SBarry Smith #include "src/mat/impls/aij/seq/aij.h"
12f5eb4b81SSatish Balay #include "src/vec/vecimpl.h"
13f5eb4b81SSatish Balay #include "src/inline/spops.h"
14e4d965acSSatish Balay #include "petsc.h"
15f5eb4b81SSatish Balay #include "src/inline/bitarray.h"
1617ab2063SBarry Smith 
17a2ce50c7SBarry Smith /*
18a2ce50c7SBarry Smith     Basic AIJ format ILU based on drop tolerance
19a2ce50c7SBarry Smith */
20*026e39d0SSatish Balay #undef __FUNCTION__
21*026e39d0SSatish Balay #define __FUNCTION__ "MatILUDTFactor_SeqAIJ"
22a2ce50c7SBarry Smith int MatILUDTFactor_SeqAIJ(Mat A,double dt,int maxnz,IS row,IS col,Mat *fact)
23a2ce50c7SBarry Smith {
24a2ce50c7SBarry Smith   /* Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; */
25a2ce50c7SBarry Smith   int        ierr = 1;
26a2ce50c7SBarry Smith 
27a2ce50c7SBarry Smith   SETERRQ(ierr,"MatILUDTFactor_SeqAIJ:Not implemented");
28a2ce50c7SBarry Smith }
29a2ce50c7SBarry Smith 
30bcd2baecSBarry Smith extern int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**);
3117ab2063SBarry Smith 
32*026e39d0SSatish Balay #undef __FUNCTION__
33*026e39d0SSatish Balay #define __FUNCTION__ "MatGetRowIJ_SeqAIJ"
3431625ec5SSatish Balay static int MatGetRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *m,int **ia,int **ja,
356945ee14SBarry Smith                            PetscTruth *done)
3617ab2063SBarry Smith {
37416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
386945ee14SBarry Smith   int        ierr,i,ishift;
3917ab2063SBarry Smith 
4031625ec5SSatish Balay   *m     = A->m;
416945ee14SBarry Smith   if (!ia) return 0;
426945ee14SBarry Smith   ishift = a->indexshift;
436945ee14SBarry Smith   if (symmetric) {
4431625ec5SSatish Balay     ierr = MatToSymmetricIJ_SeqAIJ(a->m,a->i,a->j,ishift,oshift,ia,ja); CHKERRQ(ierr);
456945ee14SBarry Smith   } else if (oshift == 0 && ishift == -1) {
4631625ec5SSatish Balay     int nz = a->i[a->m];
473b2fbd54SBarry Smith     /* malloc space and  subtract 1 from i and j indices */
4831625ec5SSatish Balay     *ia = (int *) PetscMalloc( (a->m+1)*sizeof(int) ); CHKPTRQ(*ia);
493b2fbd54SBarry Smith     *ja = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(*ja);
503b2fbd54SBarry Smith     for ( i=0; i<nz; i++ ) (*ja)[i] = a->j[i] - 1;
5131625ec5SSatish Balay     for ( i=0; i<a->m+1; i++ ) (*ia)[i] = a->i[i] - 1;
526945ee14SBarry Smith   } else if (oshift == 1 && ishift == 0) {
5331625ec5SSatish Balay     int nz = a->i[a->m] + 1;
543b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
5531625ec5SSatish Balay     *ia = (int *) PetscMalloc( (a->m+1)*sizeof(int) ); CHKPTRQ(*ia);
563b2fbd54SBarry Smith     *ja = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(*ja);
573b2fbd54SBarry Smith     for ( i=0; i<nz; i++ ) (*ja)[i] = a->j[i] + 1;
5831625ec5SSatish Balay     for ( i=0; i<a->m+1; i++ ) (*ia)[i] = a->i[i] + 1;
596945ee14SBarry Smith   } else {
606945ee14SBarry Smith     *ia = a->i; *ja = a->j;
61a2ce50c7SBarry Smith   }
62a2ce50c7SBarry Smith 
63a2744918SBarry Smith   return 0;
64a2744918SBarry Smith }
65a2744918SBarry Smith 
66*026e39d0SSatish Balay #undef __FUNCTION__
67*026e39d0SSatish Balay #define __FUNCTION__ "MatRestoreRowIJ_SeqAIJ"
683b2fbd54SBarry Smith static int MatRestoreRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia,int **ja,
696945ee14SBarry Smith                                PetscTruth *done)
706945ee14SBarry Smith {
716945ee14SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
723b2fbd54SBarry Smith   int        ishift = a->indexshift;
736945ee14SBarry Smith 
746945ee14SBarry Smith   if (!ia) return 0;
753b2fbd54SBarry Smith   if (symmetric || (oshift == 0 && ishift == -1) || (oshift == 1 && ishift == 0)) {
766945ee14SBarry Smith     PetscFree(*ia);
776945ee14SBarry Smith     PetscFree(*ja);
78bcd2baecSBarry Smith   }
7917ab2063SBarry Smith   return 0;
8017ab2063SBarry Smith }
8117ab2063SBarry Smith 
82*026e39d0SSatish Balay #undef __FUNCTION__
83*026e39d0SSatish Balay #define __FUNCTION__ "MatGetColumnIJ_SeqAIJ"
8443a90d84SBarry Smith int MatGetColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja,
853b2fbd54SBarry Smith                            PetscTruth *done)
863b2fbd54SBarry Smith {
873b2fbd54SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
88a93ec695SBarry Smith   int        ierr,i,ishift = a->indexshift,*collengths,*cia,*cja,n = A->n,m = A->m;
89a93ec695SBarry Smith   int        nz = a->i[m]+ishift,row,*jj,mr,col;
903b2fbd54SBarry Smith 
913b2fbd54SBarry Smith   *nn     = A->n;
923b2fbd54SBarry Smith   if (!ia) return 0;
933b2fbd54SBarry Smith   if (symmetric) {
94179192dfSSatish Balay     ierr = MatToSymmetricIJ_SeqAIJ(a->m,a->i,a->j,ishift,oshift,ia,ja); CHKERRQ(ierr);
953b2fbd54SBarry Smith   } else {
9661d2ded1SBarry Smith     collengths = (int *) PetscMalloc( (n+1)*sizeof(int) ); CHKPTRQ(collengths);
973b2fbd54SBarry Smith     PetscMemzero(collengths,n*sizeof(int));
983b2fbd54SBarry Smith     cia        = (int *) PetscMalloc( (n+1)*sizeof(int) ); CHKPTRQ(cia);
99a93ec695SBarry Smith     cja        = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(cja);
1003b2fbd54SBarry Smith     jj = a->j;
1013b2fbd54SBarry Smith     for ( i=0; i<nz; i++ ) {
1023b2fbd54SBarry Smith       collengths[jj[i] + ishift]++;
1033b2fbd54SBarry Smith     }
1043b2fbd54SBarry Smith     cia[0] = oshift;
1053b2fbd54SBarry Smith     for ( i=0; i<n; i++) {
1063b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
1073b2fbd54SBarry Smith     }
1083b2fbd54SBarry Smith     PetscMemzero(collengths,n*sizeof(int));
1093b2fbd54SBarry Smith     jj = a->j;
110a93ec695SBarry Smith     for ( row=0; row<m; row++ ) {
111a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
112a93ec695SBarry Smith       for ( i=0; i<mr; i++ ) {
1133b2fbd54SBarry Smith         col = *jj++ + ishift;
1143b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
1153b2fbd54SBarry Smith       }
1163b2fbd54SBarry Smith     }
1173b2fbd54SBarry Smith     PetscFree(collengths);
1183b2fbd54SBarry Smith     *ia = cia; *ja = cja;
1193b2fbd54SBarry Smith   }
1203b2fbd54SBarry Smith 
1213b2fbd54SBarry Smith   return 0;
1223b2fbd54SBarry Smith }
1233b2fbd54SBarry Smith 
124*026e39d0SSatish Balay #undef __FUNCTION__
125*026e39d0SSatish Balay #define __FUNCTION__ "MatRestoreColumnIJ_SeqAIJ"
12643a90d84SBarry Smith int MatRestoreColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia,
1273b2fbd54SBarry Smith                                      int **ja,PetscTruth *done)
1283b2fbd54SBarry Smith {
1293b2fbd54SBarry Smith   if (!ia) return 0;
1303b2fbd54SBarry Smith 
1313b2fbd54SBarry Smith   PetscFree(*ia);
1323b2fbd54SBarry Smith   PetscFree(*ja);
1333b2fbd54SBarry Smith 
1343b2fbd54SBarry Smith   return 0;
1353b2fbd54SBarry Smith }
1363b2fbd54SBarry Smith 
137227d817aSBarry Smith #define CHUNKSIZE   15
13817ab2063SBarry Smith 
139*026e39d0SSatish Balay #undef __FUNCTION__
140*026e39d0SSatish Balay #define __FUNCTION__ "MatSetValues_SeqAIJ"
14161d2ded1SBarry Smith int MatSetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is)
14217ab2063SBarry Smith {
143416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
144416022c9SBarry Smith   int        *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax, N, sorted = a->sorted;
1454b0e389bSBarry Smith   int        *imax = a->imax, *ai = a->i, *ailen = a->ilen,roworiented = a->roworiented;
146d5d45c9bSBarry Smith   int        *aj = a->j, nonew = a->nonew,shift = a->indexshift;
147416022c9SBarry Smith   Scalar     *ap,value, *aa = a->a;
14817ab2063SBarry Smith 
14917ab2063SBarry Smith   for ( k=0; k<m; k++ ) { /* loop over added rows */
150416022c9SBarry Smith     row  = im[k];
1513b2fbd54SBarry Smith #if defined(PETSC_BOPT_g)
15217ab2063SBarry Smith     if (row < 0) SETERRQ(1,"MatSetValues_SeqAIJ:Negative row");
153416022c9SBarry Smith     if (row >= a->m) SETERRQ(1,"MatSetValues_SeqAIJ:Row too large");
1543b2fbd54SBarry Smith #endif
15517ab2063SBarry Smith     rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
15617ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
157416022c9SBarry Smith     low = 0;
15817ab2063SBarry Smith     for ( l=0; l<n; l++ ) { /* loop over added columns */
1593b2fbd54SBarry Smith #if defined(PETSC_BOPT_g)
160416022c9SBarry Smith       if (in[l] < 0) SETERRQ(1,"MatSetValues_SeqAIJ:Negative column");
161416022c9SBarry Smith       if (in[l] >= a->n) SETERRQ(1,"MatSetValues_SeqAIJ:Column too large");
1623b2fbd54SBarry Smith #endif
1634b0e389bSBarry Smith       col = in[l] - shift;
1644b0e389bSBarry Smith       if (roworiented) {
1654b0e389bSBarry Smith         value = *v++;
1664b0e389bSBarry Smith       }
1674b0e389bSBarry Smith       else {
1684b0e389bSBarry Smith         value = v[k + l*m];
1694b0e389bSBarry Smith       }
170416022c9SBarry Smith       if (!sorted) low = 0; high = nrow;
171416022c9SBarry Smith       while (high-low > 5) {
172416022c9SBarry Smith         t = (low+high)/2;
173416022c9SBarry Smith         if (rp[t] > col) high = t;
174416022c9SBarry Smith         else             low  = t;
17517ab2063SBarry Smith       }
176416022c9SBarry Smith       for ( i=low; i<high; i++ ) {
17717ab2063SBarry Smith         if (rp[i] > col) break;
17817ab2063SBarry Smith         if (rp[i] == col) {
179416022c9SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
18017ab2063SBarry Smith           else                  ap[i] = value;
18117ab2063SBarry Smith           goto noinsert;
18217ab2063SBarry Smith         }
18317ab2063SBarry Smith       }
18417ab2063SBarry Smith       if (nonew) goto noinsert;
18517ab2063SBarry Smith       if (nrow >= rmax) {
18617ab2063SBarry Smith         /* there is no extra room in row, therefore enlarge */
187416022c9SBarry Smith         int    new_nz = ai[a->m] + CHUNKSIZE,len,*new_i,*new_j;
18817ab2063SBarry Smith         Scalar *new_a;
18917ab2063SBarry Smith 
19017ab2063SBarry Smith         /* malloc new storage space */
191416022c9SBarry Smith         len     = new_nz*(sizeof(int)+sizeof(Scalar))+(a->m+1)*sizeof(int);
1920452661fSBarry Smith         new_a   = (Scalar *) PetscMalloc( len ); CHKPTRQ(new_a);
19317ab2063SBarry Smith         new_j   = (int *) (new_a + new_nz);
19417ab2063SBarry Smith         new_i   = new_j + new_nz;
19517ab2063SBarry Smith 
19617ab2063SBarry Smith         /* copy over old data into new slots */
19717ab2063SBarry Smith         for ( ii=0; ii<row+1; ii++ ) {new_i[ii] = ai[ii];}
198416022c9SBarry Smith         for ( ii=row+1; ii<a->m+1; ii++ ) {new_i[ii] = ai[ii]+CHUNKSIZE;}
199416022c9SBarry Smith         PetscMemcpy(new_j,aj,(ai[row]+nrow+shift)*sizeof(int));
200416022c9SBarry Smith         len = (new_nz - CHUNKSIZE - ai[row] - nrow - shift);
201416022c9SBarry Smith         PetscMemcpy(new_j+ai[row]+shift+nrow+CHUNKSIZE,aj+ai[row]+shift+nrow,
20217ab2063SBarry Smith                                                            len*sizeof(int));
203416022c9SBarry Smith         PetscMemcpy(new_a,aa,(ai[row]+nrow+shift)*sizeof(Scalar));
204416022c9SBarry Smith         PetscMemcpy(new_a+ai[row]+shift+nrow+CHUNKSIZE,aa+ai[row]+shift+nrow,
20517ab2063SBarry Smith                                                            len*sizeof(Scalar));
20617ab2063SBarry Smith         /* free up old matrix storage */
2070452661fSBarry Smith         PetscFree(a->a);
2080452661fSBarry Smith         if (!a->singlemalloc) {PetscFree(a->i);PetscFree(a->j);}
209416022c9SBarry Smith         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
210416022c9SBarry Smith         a->singlemalloc = 1;
21117ab2063SBarry Smith 
21217ab2063SBarry Smith         rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
213416022c9SBarry Smith         rmax = imax[row] = imax[row] + CHUNKSIZE;
214416022c9SBarry Smith         PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + sizeof(Scalar)));
215416022c9SBarry Smith         a->maxnz += CHUNKSIZE;
216b810aeb4SBarry Smith         a->reallocs++;
21717ab2063SBarry Smith       }
218416022c9SBarry Smith       N = nrow++ - 1; a->nz++;
219416022c9SBarry Smith       /* shift up all the later entries in this row */
220416022c9SBarry Smith       for ( ii=N; ii>=i; ii-- ) {
22117ab2063SBarry Smith         rp[ii+1] = rp[ii];
22217ab2063SBarry Smith         ap[ii+1] = ap[ii];
22317ab2063SBarry Smith       }
22417ab2063SBarry Smith       rp[i] = col;
22517ab2063SBarry Smith       ap[i] = value;
22617ab2063SBarry Smith       noinsert:;
227416022c9SBarry Smith       low = i + 1;
22817ab2063SBarry Smith     }
22917ab2063SBarry Smith     ailen[row] = nrow;
23017ab2063SBarry Smith   }
23117ab2063SBarry Smith   return 0;
23217ab2063SBarry Smith }
23317ab2063SBarry Smith 
234*026e39d0SSatish Balay #undef __FUNCTION__
235*026e39d0SSatish Balay #define __FUNCTION__ "MatGetValues_SeqAIJ"
2367eb43aa7SLois Curfman McInnes static int MatGetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v)
2377eb43aa7SLois Curfman McInnes {
2387eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
239b49de8d1SLois Curfman McInnes   int        *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
2407eb43aa7SLois Curfman McInnes   int        *ai = a->i, *ailen = a->ilen, shift = a->indexshift;
2417eb43aa7SLois Curfman McInnes   Scalar     *ap, *aa = a->a, zero = 0.0;
2427eb43aa7SLois Curfman McInnes 
2437eb43aa7SLois Curfman McInnes   for ( k=0; k<m; k++ ) { /* loop over rows */
2447eb43aa7SLois Curfman McInnes     row  = im[k];
2457eb43aa7SLois Curfman McInnes     if (row < 0) SETERRQ(1,"MatGetValues_SeqAIJ:Negative row");
2467eb43aa7SLois Curfman McInnes     if (row >= a->m) SETERRQ(1,"MatGetValues_SeqAIJ:Row too large");
2477eb43aa7SLois Curfman McInnes     rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
2487eb43aa7SLois Curfman McInnes     nrow = ailen[row];
2497eb43aa7SLois Curfman McInnes     for ( l=0; l<n; l++ ) { /* loop over columns */
2507eb43aa7SLois Curfman McInnes       if (in[l] < 0) SETERRQ(1,"MatGetValues_SeqAIJ:Negative column");
2517eb43aa7SLois Curfman McInnes       if (in[l] >= a->n) SETERRQ(1,"MatGetValues_SeqAIJ:Column too large");
2527eb43aa7SLois Curfman McInnes       col = in[l] - shift;
2537eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
2547eb43aa7SLois Curfman McInnes       while (high-low > 5) {
2557eb43aa7SLois Curfman McInnes         t = (low+high)/2;
2567eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
2577eb43aa7SLois Curfman McInnes         else             low  = t;
2587eb43aa7SLois Curfman McInnes       }
2597eb43aa7SLois Curfman McInnes       for ( i=low; i<high; i++ ) {
2607eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
2617eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
262b49de8d1SLois Curfman McInnes           *v++ = ap[i];
2637eb43aa7SLois Curfman McInnes           goto finished;
2647eb43aa7SLois Curfman McInnes         }
2657eb43aa7SLois Curfman McInnes       }
266b49de8d1SLois Curfman McInnes       *v++ = zero;
2677eb43aa7SLois Curfman McInnes       finished:;
2687eb43aa7SLois Curfman McInnes     }
2697eb43aa7SLois Curfman McInnes   }
2707eb43aa7SLois Curfman McInnes   return 0;
2717eb43aa7SLois Curfman McInnes }
2727eb43aa7SLois Curfman McInnes 
27317ab2063SBarry Smith #include "draw.h"
27417ab2063SBarry Smith #include "pinclude/pviewer.h"
27577c4ece6SBarry Smith #include "sys.h"
27617ab2063SBarry Smith 
277*026e39d0SSatish Balay #undef __FUNCTION__
278*026e39d0SSatish Balay #define __FUNCTION__ "MatView_SeqAIJ_Binary"
279416022c9SBarry Smith static int MatView_SeqAIJ_Binary(Mat A,Viewer viewer)
28017ab2063SBarry Smith {
281416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
282416022c9SBarry Smith   int        i, fd, *col_lens, ierr;
28317ab2063SBarry Smith 
28490ace30eSBarry Smith   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
2850452661fSBarry Smith   col_lens = (int *) PetscMalloc( (4+a->m)*sizeof(int) ); CHKPTRQ(col_lens);
286416022c9SBarry Smith   col_lens[0] = MAT_COOKIE;
287416022c9SBarry Smith   col_lens[1] = a->m;
288416022c9SBarry Smith   col_lens[2] = a->n;
289416022c9SBarry Smith   col_lens[3] = a->nz;
290416022c9SBarry Smith 
291416022c9SBarry Smith   /* store lengths of each row and write (including header) to file */
292416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
293416022c9SBarry Smith     col_lens[4+i] = a->i[i+1] - a->i[i];
29417ab2063SBarry Smith   }
29577c4ece6SBarry Smith   ierr = PetscBinaryWrite(fd,col_lens,4+a->m,BINARY_INT,1); CHKERRQ(ierr);
2960452661fSBarry Smith   PetscFree(col_lens);
297416022c9SBarry Smith 
298416022c9SBarry Smith   /* store column indices (zero start index) */
299416022c9SBarry Smith   if (a->indexshift) {
300416022c9SBarry Smith     for ( i=0; i<a->nz; i++ ) a->j[i]--;
30117ab2063SBarry Smith   }
30277c4ece6SBarry Smith   ierr = PetscBinaryWrite(fd,a->j,a->nz,BINARY_INT,0); CHKERRQ(ierr);
303416022c9SBarry Smith   if (a->indexshift) {
304416022c9SBarry Smith     for ( i=0; i<a->nz; i++ ) a->j[i]++;
30517ab2063SBarry Smith   }
306416022c9SBarry Smith 
307416022c9SBarry Smith   /* store nonzero values */
30877c4ece6SBarry Smith   ierr = PetscBinaryWrite(fd,a->a,a->nz,BINARY_SCALAR,0); CHKERRQ(ierr);
30917ab2063SBarry Smith   return 0;
31017ab2063SBarry Smith }
311416022c9SBarry Smith 
312*026e39d0SSatish Balay #undef __FUNCTION__
313*026e39d0SSatish Balay #define __FUNCTION__ "MatView_SeqAIJ_ASCII"
314416022c9SBarry Smith static int MatView_SeqAIJ_ASCII(Mat A,Viewer viewer)
315416022c9SBarry Smith {
316416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ *) A->data;
317496e697eSBarry Smith   int         ierr, i,j, m = a->m, shift = a->indexshift, format, flg1,flg2;
31817ab2063SBarry Smith   FILE        *fd;
31917ab2063SBarry Smith   char        *outputname;
32017ab2063SBarry Smith 
32190ace30eSBarry Smith   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
322416022c9SBarry Smith   ierr = ViewerFileGetOutputname_Private(viewer,&outputname); CHKERRQ(ierr);
32390ace30eSBarry Smith   ierr = ViewerGetFormat(viewer,&format);
324a93ec695SBarry Smith   if (format == VIEWER_FORMAT_ASCII_INFO) {
32595e01e2fSLois Curfman McInnes     return 0;
32695e01e2fSLois Curfman McInnes   }
327a93ec695SBarry Smith   else if (format == VIEWER_FORMAT_ASCII_INFO_LONG) {
328496e697eSBarry Smith     ierr = OptionsHasName(PETSC_NULL,"-mat_aij_no_inode",&flg1); CHKERRQ(ierr);
329496e697eSBarry Smith     ierr = OptionsHasName(PETSC_NULL,"-mat_no_unroll",&flg2); CHKERRQ(ierr);
330496e697eSBarry Smith     if (flg1 || flg2) fprintf(fd,"  not using I-node routines\n");
33195e01e2fSLois Curfman McInnes     else     fprintf(fd,"  using I-node routines: found %d nodes, limit used is %d\n",
33295e01e2fSLois Curfman McInnes         a->inode.node_count,a->inode.limit);
33317ab2063SBarry Smith   }
334a93ec695SBarry Smith   else if (format == VIEWER_FORMAT_ASCII_MATLAB) {
335416022c9SBarry Smith     fprintf(fd,"%% Size = %d %d \n",m,a->n);
3364e220ebcSLois Curfman McInnes     fprintf(fd,"%% Nonzeros = %d \n",a->nz);
3374e220ebcSLois Curfman McInnes     fprintf(fd,"zzz = zeros(%d,3);\n",a->nz);
33817ab2063SBarry Smith     fprintf(fd,"zzz = [\n");
33917ab2063SBarry Smith 
34017ab2063SBarry Smith     for (i=0; i<m; i++) {
341416022c9SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
34217ab2063SBarry Smith #if defined(PETSC_COMPLEX)
3436945ee14SBarry Smith         fprintf(fd,"%d %d  %18.16e + %18.16e i \n",i+1,a->j[j]+!shift,real(a->a[j]),
344416022c9SBarry Smith                    imag(a->a[j]));
34517ab2063SBarry Smith #else
3467a743949SBarry Smith         fprintf(fd,"%d %d  %18.16e\n", i+1, a->j[j]+!shift, a->a[j]);
34717ab2063SBarry Smith #endif
34817ab2063SBarry Smith       }
34917ab2063SBarry Smith     }
35017ab2063SBarry Smith     fprintf(fd,"];\n %s = spconvert(zzz);\n",outputname);
35117ab2063SBarry Smith   }
352a93ec695SBarry Smith   else if (format == VIEWER_FORMAT_ASCII_COMMON) {
35344cd7ae7SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
35444cd7ae7SLois Curfman McInnes       fprintf(fd,"row %d:",i);
35544cd7ae7SLois Curfman McInnes       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
35644cd7ae7SLois Curfman McInnes #if defined(PETSC_COMPLEX)
35744cd7ae7SLois Curfman McInnes         if (imag(a->a[j]) != 0.0 && real(a->a[j]) != 0.0)
35844cd7ae7SLois Curfman McInnes           fprintf(fd," %d %g + %g i",a->j[j]+shift,real(a->a[j]),imag(a->a[j]));
35944cd7ae7SLois Curfman McInnes         else if (real(a->a[j]) != 0.0)
36044cd7ae7SLois Curfman McInnes           fprintf(fd," %d %g ",a->j[j]+shift,real(a->a[j]));
36144cd7ae7SLois Curfman McInnes #else
36244cd7ae7SLois Curfman McInnes         if (a->a[j] != 0.0) fprintf(fd," %d %g ",a->j[j]+shift,a->a[j]);
36344cd7ae7SLois Curfman McInnes #endif
36444cd7ae7SLois Curfman McInnes       }
36544cd7ae7SLois Curfman McInnes       fprintf(fd,"\n");
36644cd7ae7SLois Curfman McInnes     }
36744cd7ae7SLois Curfman McInnes   }
36817ab2063SBarry Smith   else {
36917ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
37017ab2063SBarry Smith       fprintf(fd,"row %d:",i);
371416022c9SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
37217ab2063SBarry Smith #if defined(PETSC_COMPLEX)
373416022c9SBarry Smith         if (imag(a->a[j]) != 0.0) {
374416022c9SBarry Smith           fprintf(fd," %d %g + %g i",a->j[j]+shift,real(a->a[j]),imag(a->a[j]));
37517ab2063SBarry Smith         }
37617ab2063SBarry Smith         else {
377416022c9SBarry Smith           fprintf(fd," %d %g ",a->j[j]+shift,real(a->a[j]));
37817ab2063SBarry Smith         }
37917ab2063SBarry Smith #else
380416022c9SBarry Smith         fprintf(fd," %d %g ",a->j[j]+shift,a->a[j]);
38117ab2063SBarry Smith #endif
38217ab2063SBarry Smith       }
38317ab2063SBarry Smith       fprintf(fd,"\n");
38417ab2063SBarry Smith     }
38517ab2063SBarry Smith   }
38617ab2063SBarry Smith   fflush(fd);
387416022c9SBarry Smith   return 0;
388416022c9SBarry Smith }
389416022c9SBarry Smith 
390*026e39d0SSatish Balay #undef __FUNCTION__
391*026e39d0SSatish Balay #define __FUNCTION__ "MatView_SeqAIJ_Draw"
392416022c9SBarry Smith static int MatView_SeqAIJ_Draw(Mat A,Viewer viewer)
393416022c9SBarry Smith {
394416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ *) A->data;
395cddf8d76SBarry Smith   int         ierr, i,j, m = a->m, shift = a->indexshift,pause,color;
396cddf8d76SBarry Smith   double      xl,yl,xr,yr,w,h,xc,yc,scale = 1.0,x_l,x_r,y_l,y_r;
397bcd2baecSBarry Smith   Draw        draw;
398cddf8d76SBarry Smith   DrawButton  button;
39919bcc07fSBarry Smith   PetscTruth  isnull;
400cddf8d76SBarry Smith 
401bcd2baecSBarry Smith   ViewerDrawGetDraw(viewer,&draw);
40219bcc07fSBarry Smith   ierr = DrawIsNull(draw,&isnull); CHKERRQ(ierr); if (isnull) return 0;
40319bcc07fSBarry Smith 
404416022c9SBarry Smith   xr  = a->n; yr = a->m; h = yr/10.0; w = xr/10.0;
405416022c9SBarry Smith   xr += w;    yr += h;  xl = -w;     yl = -h;
406416022c9SBarry Smith   ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
407416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
408cddf8d76SBarry Smith   color = DRAW_BLUE;
409416022c9SBarry Smith   for ( i=0; i<m; i++ ) {
410cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
411416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
412cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
413cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
414cddf8d76SBarry Smith       if (real(a->a[j]) >=  0.) continue;
415cddf8d76SBarry Smith #else
416cddf8d76SBarry Smith       if (a->a[j] >=  0.) continue;
417cddf8d76SBarry Smith #endif
418cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
419cddf8d76SBarry Smith     }
420cddf8d76SBarry Smith   }
421cddf8d76SBarry Smith   color = DRAW_CYAN;
422cddf8d76SBarry Smith   for ( i=0; i<m; i++ ) {
423cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
424cddf8d76SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
425cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
426cddf8d76SBarry Smith       if (a->a[j] !=  0.) continue;
427cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
428cddf8d76SBarry Smith     }
429cddf8d76SBarry Smith   }
430cddf8d76SBarry Smith   color = DRAW_RED;
431cddf8d76SBarry Smith   for ( i=0; i<m; i++ ) {
432cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
433cddf8d76SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
434cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
435cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
436cddf8d76SBarry Smith       if (real(a->a[j]) <=  0.) continue;
437cddf8d76SBarry Smith #else
438cddf8d76SBarry Smith       if (a->a[j] <=  0.) continue;
439cddf8d76SBarry Smith #endif
440cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
441416022c9SBarry Smith     }
442416022c9SBarry Smith   }
443416022c9SBarry Smith   DrawFlush(draw);
444cddf8d76SBarry Smith   DrawGetPause(draw,&pause);
445cddf8d76SBarry Smith   if (pause >= 0) { PetscSleep(pause); return 0;}
446cddf8d76SBarry Smith 
447cddf8d76SBarry Smith   /* allow the matrix to zoom or shrink */
4486945ee14SBarry Smith   ierr = DrawCheckResizedWindow(draw);
449cddf8d76SBarry Smith   ierr = DrawGetMouseButton(draw,&button,&xc,&yc,0,0);
450cddf8d76SBarry Smith   while (button != BUTTON_RIGHT) {
451cddf8d76SBarry Smith     DrawClear(draw);
452cddf8d76SBarry Smith     if (button == BUTTON_LEFT) scale = .5;
453cddf8d76SBarry Smith     else if (button == BUTTON_CENTER) scale = 2.;
454cddf8d76SBarry Smith     xl = scale*(xl + w - xc) + xc - w*scale;
455cddf8d76SBarry Smith     xr = scale*(xr - w - xc) + xc + w*scale;
456cddf8d76SBarry Smith     yl = scale*(yl + h - yc) + yc - h*scale;
457cddf8d76SBarry Smith     yr = scale*(yr - h - yc) + yc + h*scale;
458cddf8d76SBarry Smith     w *= scale; h *= scale;
459cddf8d76SBarry Smith     ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
460cddf8d76SBarry Smith     color = DRAW_BLUE;
461cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
462cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
463cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
464cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
465cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
466cddf8d76SBarry Smith         if (real(a->a[j]) >=  0.) continue;
467cddf8d76SBarry Smith #else
468cddf8d76SBarry Smith         if (a->a[j] >=  0.) continue;
469cddf8d76SBarry Smith #endif
470cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
471cddf8d76SBarry Smith       }
472cddf8d76SBarry Smith     }
473cddf8d76SBarry Smith     color = DRAW_CYAN;
474cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
475cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
476cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
477cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
478cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
479cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
480cddf8d76SBarry Smith       }
481cddf8d76SBarry Smith     }
482cddf8d76SBarry Smith     color = DRAW_RED;
483cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
484cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
485cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
486cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
487cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
488cddf8d76SBarry Smith         if (real(a->a[j]) <=  0.) continue;
489cddf8d76SBarry Smith #else
490cddf8d76SBarry Smith         if (a->a[j] <=  0.) continue;
491cddf8d76SBarry Smith #endif
492cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
493cddf8d76SBarry Smith       }
494cddf8d76SBarry Smith     }
4956945ee14SBarry Smith     ierr = DrawCheckResizedWindow(draw);
496cddf8d76SBarry Smith     ierr = DrawGetMouseButton(draw,&button,&xc,&yc,0,0);
497cddf8d76SBarry Smith   }
498416022c9SBarry Smith   return 0;
499416022c9SBarry Smith }
500416022c9SBarry Smith 
501*026e39d0SSatish Balay #undef __FUNCTION__
502*026e39d0SSatish Balay #define __FUNCTION__ "MatView_SeqAIJ"
503416022c9SBarry Smith static int MatView_SeqAIJ(PetscObject obj,Viewer viewer)
504416022c9SBarry Smith {
505416022c9SBarry Smith   Mat         A = (Mat) obj;
506416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ*) A->data;
507bcd2baecSBarry Smith   ViewerType  vtype;
508bcd2baecSBarry Smith   int         ierr;
509416022c9SBarry Smith 
510bcd2baecSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
511bcd2baecSBarry Smith   if (vtype == MATLAB_VIEWER) {
512416022c9SBarry Smith     return ViewerMatlabPutSparse_Private(viewer,a->m,a->n,a->nz,a->a,a->i,a->j);
513416022c9SBarry Smith   }
514bcd2baecSBarry Smith   else if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER){
515416022c9SBarry Smith     return MatView_SeqAIJ_ASCII(A,viewer);
516416022c9SBarry Smith   }
517bcd2baecSBarry Smith   else if (vtype == BINARY_FILE_VIEWER) {
518416022c9SBarry Smith     return MatView_SeqAIJ_Binary(A,viewer);
519416022c9SBarry Smith   }
520bcd2baecSBarry Smith   else if (vtype == DRAW_VIEWER) {
521bcd2baecSBarry Smith     return MatView_SeqAIJ_Draw(A,viewer);
52217ab2063SBarry Smith   }
52317ab2063SBarry Smith   return 0;
52417ab2063SBarry Smith }
52519bcc07fSBarry Smith 
526c456f294SBarry Smith extern int Mat_AIJ_CheckInode(Mat);
527*026e39d0SSatish Balay #undef __FUNCTION__
528*026e39d0SSatish Balay #define __FUNCTION__ "MatAssemblyEnd_SeqAIJ"
529416022c9SBarry Smith static int MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
53017ab2063SBarry Smith {
531416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
53241c01911SSatish Balay   int        fshift = 0,i,j,*ai = a->i, *aj = a->j, *imax = a->imax,ierr;
533416022c9SBarry Smith   int        m = a->m, *ip, N, *ailen = a->ilen,shift = a->indexshift;
534416022c9SBarry Smith   Scalar     *aa = a->a, *ap;
53517ab2063SBarry Smith 
5366d4a8577SBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) return 0;
53717ab2063SBarry Smith 
53817ab2063SBarry Smith   for ( i=1; i<m; i++ ) {
539416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
54017ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
54117ab2063SBarry Smith     if (fshift) {
542416022c9SBarry Smith       ip = aj + ai[i] + shift; ap = aa + ai[i] + shift;
54317ab2063SBarry Smith       N = ailen[i];
54417ab2063SBarry Smith       for ( j=0; j<N; j++ ) {
54517ab2063SBarry Smith         ip[j-fshift] = ip[j];
54617ab2063SBarry Smith         ap[j-fshift] = ap[j];
54717ab2063SBarry Smith       }
54817ab2063SBarry Smith     }
54917ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
55017ab2063SBarry Smith   }
55117ab2063SBarry Smith   if (m) {
55217ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
55317ab2063SBarry Smith     ai[m] = ai[m-1] + ailen[m-1];
55417ab2063SBarry Smith   }
55517ab2063SBarry Smith   /* reset ilen and imax for each row */
55617ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
55717ab2063SBarry Smith     ailen[i] = imax[i] = ai[i+1] - ai[i];
55817ab2063SBarry Smith   }
559416022c9SBarry Smith   a->nz = ai[m] + shift;
56017ab2063SBarry Smith 
56117ab2063SBarry Smith   /* diagonals may have moved, so kill the diagonal pointers */
562416022c9SBarry Smith   if (fshift && a->diag) {
5630452661fSBarry Smith     PetscFree(a->diag);
564416022c9SBarry Smith     PLogObjectMemory(A,-(m+1)*sizeof(int));
565416022c9SBarry Smith     a->diag = 0;
56617ab2063SBarry Smith   }
5674e220ebcSLois Curfman McInnes   PLogInfo(A,"MatAssemblyEnd_SeqAIJ:Matrix size: %d X %d; storage space: %d unneeded, %d used\n",
5684e220ebcSLois Curfman McInnes            m,a->n,fshift,a->nz);
5694e220ebcSLois Curfman McInnes   PLogInfo(A,"MatAssemblyEnd_SeqAIJ:Number of mallocs during MatSetValues is %d\n",
570b810aeb4SBarry Smith            a->reallocs);
571dd5f02e7SSatish Balay   a->reallocs          = 0;
5724e220ebcSLois Curfman McInnes   A->info.nz_unneeded  = (double)fshift;
5734e220ebcSLois Curfman McInnes 
57476dd722bSSatish Balay   /* check out for identical nodes. If found, use inode functions */
57541c01911SSatish Balay   ierr = Mat_AIJ_CheckInode(A); CHKERRQ(ierr);
57617ab2063SBarry Smith   return 0;
57717ab2063SBarry Smith }
57817ab2063SBarry Smith 
579*026e39d0SSatish Balay #undef __FUNCTION__
580*026e39d0SSatish Balay #define __FUNCTION__ "MatZeroEntries_SeqAIJ"
581416022c9SBarry Smith static int MatZeroEntries_SeqAIJ(Mat A)
58217ab2063SBarry Smith {
583416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
584cddf8d76SBarry Smith   PetscMemzero(a->a,(a->i[a->m]+a->indexshift)*sizeof(Scalar));
58517ab2063SBarry Smith   return 0;
58617ab2063SBarry Smith }
587416022c9SBarry Smith 
588*026e39d0SSatish Balay #undef __FUNCTION__
589*026e39d0SSatish Balay #define __FUNCTION__ "MatDestroy_SeqAIJ"
59017ab2063SBarry Smith int MatDestroy_SeqAIJ(PetscObject obj)
59117ab2063SBarry Smith {
592416022c9SBarry Smith   Mat        A  = (Mat) obj;
593416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
59490f02eecSBarry Smith   int        ierr;
595d5d45c9bSBarry Smith 
59617ab2063SBarry Smith #if defined(PETSC_LOG)
597416022c9SBarry Smith   PLogObjectState(obj,"Rows=%d, Cols=%d, NZ=%d",a->m,a->n,a->nz);
59817ab2063SBarry Smith #endif
5990452661fSBarry Smith   PetscFree(a->a);
6000452661fSBarry Smith   if (!a->singlemalloc) { PetscFree(a->i); PetscFree(a->j);}
6010452661fSBarry Smith   if (a->diag) PetscFree(a->diag);
6020452661fSBarry Smith   if (a->ilen) PetscFree(a->ilen);
6030452661fSBarry Smith   if (a->imax) PetscFree(a->imax);
6040452661fSBarry Smith   if (a->solve_work) PetscFree(a->solve_work);
60576dd722bSSatish Balay   if (a->inode.size) PetscFree(a->inode.size);
6060452661fSBarry Smith   PetscFree(a);
60790f02eecSBarry Smith   if (A->mapping) {
60890f02eecSBarry Smith     ierr = ISLocalToGlobalMappingDestroy(A->mapping); CHKERRQ(ierr);
60990f02eecSBarry Smith   }
610f2655603SLois Curfman McInnes   PLogObjectDestroy(A);
611f2655603SLois Curfman McInnes   PetscHeaderDestroy(A);
61217ab2063SBarry Smith   return 0;
61317ab2063SBarry Smith }
61417ab2063SBarry Smith 
615*026e39d0SSatish Balay #undef __FUNCTION__
616*026e39d0SSatish Balay #define __FUNCTION__ "MatCompress_SeqAIJ"
617416022c9SBarry Smith static int MatCompress_SeqAIJ(Mat A)
61817ab2063SBarry Smith {
61917ab2063SBarry Smith   return 0;
62017ab2063SBarry Smith }
62117ab2063SBarry Smith 
622*026e39d0SSatish Balay #undef __FUNCTION__
623*026e39d0SSatish Balay #define __FUNCTION__ "MatSetOption_SeqAIJ"
624416022c9SBarry Smith static int MatSetOption_SeqAIJ(Mat A,MatOption op)
62517ab2063SBarry Smith {
626416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
6276d4a8577SBarry Smith   if      (op == MAT_ROW_ORIENTED)              a->roworiented = 1;
6286d4a8577SBarry Smith   else if (op == MAT_COLUMN_ORIENTED)           a->roworiented = 0;
6296d4a8577SBarry Smith   else if (op == MAT_COLUMNS_SORTED)            a->sorted      = 1;
630219d9a1aSLois Curfman McInnes   else if (op == MAT_COLUMNS_UNSORTED)          a->sorted      = 0;
6316d4a8577SBarry Smith   else if (op == MAT_NO_NEW_NONZERO_LOCATIONS)  a->nonew       = 1;
6326d4a8577SBarry Smith   else if (op == MAT_YES_NEW_NONZERO_LOCATIONS) a->nonew       = 0;
6336d4a8577SBarry Smith   else if (op == MAT_ROWS_SORTED ||
634219d9a1aSLois Curfman McInnes            op == MAT_ROWS_UNSORTED ||
6356d4a8577SBarry Smith            op == MAT_SYMMETRIC ||
6366d4a8577SBarry Smith            op == MAT_STRUCTURALLY_SYMMETRIC ||
63790f02eecSBarry Smith            op == MAT_YES_NEW_DIAGONALS ||
63890f02eecSBarry Smith            op == MAT_IGNORE_OFF_PROCESSOR_ENTRIES)
63994a424c1SBarry Smith     PLogInfo(A,"Info:MatSetOption_SeqAIJ:Option ignored\n");
6406d4a8577SBarry Smith   else if (op == MAT_NO_NEW_DIAGONALS)
6416d4a8577SBarry Smith     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqAIJ:MAT_NO_NEW_DIAGONALS");}
6426d4a8577SBarry Smith   else if (op == MAT_INODE_LIMIT_1)            a->inode.limit  = 1;
6436d4a8577SBarry Smith   else if (op == MAT_INODE_LIMIT_2)            a->inode.limit  = 2;
6446d4a8577SBarry Smith   else if (op == MAT_INODE_LIMIT_3)            a->inode.limit  = 3;
6456d4a8577SBarry Smith   else if (op == MAT_INODE_LIMIT_4)            a->inode.limit  = 4;
6466d4a8577SBarry Smith   else if (op == MAT_INODE_LIMIT_5)            a->inode.limit  = 5;
647e2f28af5SBarry Smith   else
6484d39ef84SLois Curfman McInnes     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqAIJ:unknown option");}
64917ab2063SBarry Smith   return 0;
65017ab2063SBarry Smith }
65117ab2063SBarry Smith 
652*026e39d0SSatish Balay #undef __FUNCTION__
653*026e39d0SSatish Balay #define __FUNCTION__ "MatGetDiagonal_SeqAIJ"
654416022c9SBarry Smith static int MatGetDiagonal_SeqAIJ(Mat A,Vec v)
65517ab2063SBarry Smith {
656416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
657416022c9SBarry Smith   int        i,j, n,shift = a->indexshift;
65817ab2063SBarry Smith   Scalar     *x, zero = 0.0;
65917ab2063SBarry Smith 
66017ab2063SBarry Smith   VecSet(&zero,v);
66190f02eecSBarry Smith   VecGetArray_Fast(v,x); VecGetLocalSize(v,&n);
662416022c9SBarry Smith   if (n != a->m) SETERRQ(1,"MatGetDiagonal_SeqAIJ:Nonconforming matrix and vector");
663416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
664416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
665416022c9SBarry Smith       if (a->j[j]+shift == i) {
666416022c9SBarry Smith         x[i] = a->a[j];
66717ab2063SBarry Smith         break;
66817ab2063SBarry Smith       }
66917ab2063SBarry Smith     }
67017ab2063SBarry Smith   }
67117ab2063SBarry Smith   return 0;
67217ab2063SBarry Smith }
67317ab2063SBarry Smith 
67417ab2063SBarry Smith /* -------------------------------------------------------*/
67517ab2063SBarry Smith /* Should check that shapes of vectors and matrices match */
67617ab2063SBarry Smith /* -------------------------------------------------------*/
677*026e39d0SSatish Balay #undef __FUNCTION__
678*026e39d0SSatish Balay #define __FUNCTION__ "MatMultTrans_SeqAIJ"
67944cd7ae7SLois Curfman McInnes int MatMultTrans_SeqAIJ(Mat A,Vec xx,Vec yy)
68017ab2063SBarry Smith {
681416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
68217ab2063SBarry Smith   Scalar     *x, *y, *v, alpha;
683416022c9SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift;
68417ab2063SBarry Smith 
68590f02eecSBarry Smith   VecGetArray_Fast(xx,x); VecGetArray_Fast(yy,y);
686cddf8d76SBarry Smith   PetscMemzero(y,a->n*sizeof(Scalar));
68717ab2063SBarry Smith   y = y + shift; /* shift for Fortran start by 1 indexing */
68817ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
689416022c9SBarry Smith     idx   = a->j + a->i[i] + shift;
690416022c9SBarry Smith     v     = a->a + a->i[i] + shift;
691416022c9SBarry Smith     n     = a->i[i+1] - a->i[i];
69217ab2063SBarry Smith     alpha = x[i];
69317ab2063SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
69417ab2063SBarry Smith   }
695416022c9SBarry Smith   PLogFlops(2*a->nz - a->n);
69617ab2063SBarry Smith   return 0;
69717ab2063SBarry Smith }
698d5d45c9bSBarry Smith 
699*026e39d0SSatish Balay #undef __FUNCTION__
700*026e39d0SSatish Balay #define __FUNCTION__ "MatMultTransAdd_SeqAIJ"
70144cd7ae7SLois Curfman McInnes int MatMultTransAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
70217ab2063SBarry Smith {
703416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
70417ab2063SBarry Smith   Scalar     *x, *y, *v, alpha;
705416022c9SBarry Smith   int        m = a->m, n, i, *idx,shift = a->indexshift;
70617ab2063SBarry Smith 
70790f02eecSBarry Smith   VecGetArray_Fast(xx,x); VecGetArray_Fast(yy,y);
70817ab2063SBarry Smith   if (zz != yy) VecCopy(zz,yy);
70917ab2063SBarry Smith   y = y + shift; /* shift for Fortran start by 1 indexing */
71017ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
711416022c9SBarry Smith     idx   = a->j + a->i[i] + shift;
712416022c9SBarry Smith     v     = a->a + a->i[i] + shift;
713416022c9SBarry Smith     n     = a->i[i+1] - a->i[i];
71417ab2063SBarry Smith     alpha = x[i];
71517ab2063SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
71617ab2063SBarry Smith   }
71790f02eecSBarry Smith   PLogFlops(2*a->nz);
71817ab2063SBarry Smith   return 0;
71917ab2063SBarry Smith }
72017ab2063SBarry Smith 
721*026e39d0SSatish Balay #undef __FUNCTION__
722*026e39d0SSatish Balay #define __FUNCTION__ "MatMult_SeqAIJ"
72344cd7ae7SLois Curfman McInnes int MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
72417ab2063SBarry Smith {
725416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
72617ab2063SBarry Smith   Scalar     *x, *y, *v, sum;
727416022c9SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift,*ii;
72817ab2063SBarry Smith 
72990f02eecSBarry Smith   VecGetArray_Fast(xx,x); VecGetArray_Fast(yy,y);
73017ab2063SBarry Smith   x    = x + shift; /* shift for Fortran start by 1 indexing */
731416022c9SBarry Smith   idx  = a->j;
732416022c9SBarry Smith   v    = a->a;
733416022c9SBarry Smith   ii   = a->i;
73417ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
735416022c9SBarry Smith     n    = ii[1] - ii[0]; ii++;
73617ab2063SBarry Smith     sum  = 0.0;
73717ab2063SBarry Smith     /* SPARSEDENSEDOT(sum,x,v,idx,n);  */
73817ab2063SBarry Smith     /* for ( j=n-1; j>-1; j--) sum += v[j]*x[idx[j]]; */
739416022c9SBarry Smith     while (n--) sum += *v++ * x[*idx++];
74017ab2063SBarry Smith     y[i] = sum;
74117ab2063SBarry Smith   }
742416022c9SBarry Smith   PLogFlops(2*a->nz - m);
74317ab2063SBarry Smith   return 0;
74417ab2063SBarry Smith }
74517ab2063SBarry Smith 
746*026e39d0SSatish Balay #undef __FUNCTION__
747*026e39d0SSatish Balay #define __FUNCTION__ "MatMultAdd_SeqAIJ"
74844cd7ae7SLois Curfman McInnes int MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
74917ab2063SBarry Smith {
750416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
75117ab2063SBarry Smith   Scalar     *x, *y, *z, *v, sum;
752cddf8d76SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift,*ii;
75317ab2063SBarry Smith 
75490f02eecSBarry Smith   VecGetArray_Fast(xx,x); VecGetArray_Fast(yy,y); VecGetArray_Fast(zz,z);
75517ab2063SBarry Smith   x    = x + shift; /* shift for Fortran start by 1 indexing */
756cddf8d76SBarry Smith   idx  = a->j;
757cddf8d76SBarry Smith   v    = a->a;
758cddf8d76SBarry Smith   ii   = a->i;
75917ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
760cddf8d76SBarry Smith     n    = ii[1] - ii[0]; ii++;
76117ab2063SBarry Smith     sum  = y[i];
762cddf8d76SBarry Smith     /* SPARSEDENSEDOT(sum,x,v,idx,n);  */
763cddf8d76SBarry Smith     while (n--) sum += *v++ * x[*idx++];
76417ab2063SBarry Smith     z[i] = sum;
76517ab2063SBarry Smith   }
766416022c9SBarry Smith   PLogFlops(2*a->nz);
76717ab2063SBarry Smith   return 0;
76817ab2063SBarry Smith }
76917ab2063SBarry Smith 
77017ab2063SBarry Smith /*
77117ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
77217ab2063SBarry Smith */
77317ab2063SBarry Smith 
774*026e39d0SSatish Balay #undef __FUNCTION__
775*026e39d0SSatish Balay #define __FUNCTION__ "MatMarkDiag_SeqAIJ"
776416022c9SBarry Smith int MatMarkDiag_SeqAIJ(Mat A)
77717ab2063SBarry Smith {
778416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
779416022c9SBarry Smith   int        i,j, *diag, m = a->m,shift = a->indexshift;
78017ab2063SBarry Smith 
7810452661fSBarry Smith   diag = (int *) PetscMalloc( (m+1)*sizeof(int)); CHKPTRQ(diag);
782416022c9SBarry Smith   PLogObjectMemory(A,(m+1)*sizeof(int));
783416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
784416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
785416022c9SBarry Smith       if (a->j[j]+shift == i) {
78617ab2063SBarry Smith         diag[i] = j - shift;
78717ab2063SBarry Smith         break;
78817ab2063SBarry Smith       }
78917ab2063SBarry Smith     }
79017ab2063SBarry Smith   }
791416022c9SBarry Smith   a->diag = diag;
79217ab2063SBarry Smith   return 0;
79317ab2063SBarry Smith }
79417ab2063SBarry Smith 
795*026e39d0SSatish Balay #undef __FUNCTION__
796*026e39d0SSatish Balay #define __FUNCTION__ "MatRelax_SeqAIJ"
79744cd7ae7SLois Curfman McInnes int MatRelax_SeqAIJ(Mat A,Vec bb,double omega,MatSORType flag,
79817ab2063SBarry Smith                            double fshift,int its,Vec xx)
79917ab2063SBarry Smith {
800416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
801416022c9SBarry Smith   Scalar     *x, *b, *bs,  d, *xs, sum, *v = a->a,*t,scale,*ts, *xb;
802d5d45c9bSBarry Smith   int        ierr, *idx, *diag,n = a->n, m = a->m, i, shift = a->indexshift;
80317ab2063SBarry Smith 
80490f02eecSBarry Smith   VecGetArray_Fast(xx,x); VecGetArray_Fast(bb,b);
805416022c9SBarry Smith   if (!a->diag) {if ((ierr = MatMarkDiag_SeqAIJ(A))) return ierr;}
806416022c9SBarry Smith   diag = a->diag;
807416022c9SBarry Smith   xs   = x + shift; /* shifted by one for index start of a or a->j*/
80817ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
80917ab2063SBarry Smith    /* apply ( U + D/omega) to the vector */
81017ab2063SBarry Smith     bs = b + shift;
81117ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
812416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
813416022c9SBarry Smith         n    = a->i[i+1] - diag[i] - 1;
814416022c9SBarry Smith         idx  = a->j + diag[i] + (!shift);
815416022c9SBarry Smith         v    = a->a + diag[i] + (!shift);
81617ab2063SBarry Smith         sum  = b[i]*d/omega;
81717ab2063SBarry Smith         SPARSEDENSEDOT(sum,bs,v,idx,n);
81817ab2063SBarry Smith         x[i] = sum;
81917ab2063SBarry Smith     }
82017ab2063SBarry Smith     return 0;
82117ab2063SBarry Smith   }
82217ab2063SBarry Smith   if (flag == SOR_APPLY_LOWER) {
82317ab2063SBarry Smith     SETERRQ(1,"MatRelax_SeqAIJ:SOR_APPLY_LOWER is not done");
82417ab2063SBarry Smith   }
825416022c9SBarry Smith   else if (flag & SOR_EISENSTAT) {
82617ab2063SBarry Smith     /* Let  A = L + U + D; where L is lower trianglar,
82717ab2063SBarry Smith     U is upper triangular, E is diagonal; This routine applies
82817ab2063SBarry Smith 
82917ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
83017ab2063SBarry Smith 
83117ab2063SBarry Smith     to a vector efficiently using Eisenstat's trick. This is for
83217ab2063SBarry Smith     the case of SSOR preconditioner, so E is D/omega where omega
83317ab2063SBarry Smith     is the relaxation factor.
83417ab2063SBarry Smith     */
8350452661fSBarry Smith     t = (Scalar *) PetscMalloc( m*sizeof(Scalar) ); CHKPTRQ(t);
83617ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
83717ab2063SBarry Smith 
83817ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
83917ab2063SBarry Smith     for ( i=m-1; i>=0; i-- ) {
840416022c9SBarry Smith       d    = fshift + a->a[diag[i] + shift];
841416022c9SBarry Smith       n    = a->i[i+1] - diag[i] - 1;
842416022c9SBarry Smith       idx  = a->j + diag[i] + (!shift);
843416022c9SBarry Smith       v    = a->a + diag[i] + (!shift);
84417ab2063SBarry Smith       sum  = b[i];
84517ab2063SBarry Smith       SPARSEDENSEMDOT(sum,xs,v,idx,n);
84617ab2063SBarry Smith       x[i] = omega*(sum/d);
84717ab2063SBarry Smith     }
84817ab2063SBarry Smith 
84917ab2063SBarry Smith     /*  t = b - (2*E - D)x */
850416022c9SBarry Smith     v = a->a;
85117ab2063SBarry Smith     for ( i=0; i<m; i++ ) { t[i] = b[i] - scale*(v[*diag++ + shift])*x[i]; }
85217ab2063SBarry Smith 
85317ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
854416022c9SBarry Smith     ts = t + shift; /* shifted by one for index start of a or a->j*/
855416022c9SBarry Smith     diag = a->diag;
85617ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
857416022c9SBarry Smith       d    = fshift + a->a[diag[i]+shift];
858416022c9SBarry Smith       n    = diag[i] - a->i[i];
859416022c9SBarry Smith       idx  = a->j + a->i[i] + shift;
860416022c9SBarry Smith       v    = a->a + a->i[i] + shift;
86117ab2063SBarry Smith       sum  = t[i];
86217ab2063SBarry Smith       SPARSEDENSEMDOT(sum,ts,v,idx,n);
86317ab2063SBarry Smith       t[i] = omega*(sum/d);
86417ab2063SBarry Smith     }
86517ab2063SBarry Smith 
86617ab2063SBarry Smith     /*  x = x + t */
86717ab2063SBarry Smith     for ( i=0; i<m; i++ ) { x[i] += t[i]; }
8680452661fSBarry Smith     PetscFree(t);
86917ab2063SBarry Smith     return 0;
87017ab2063SBarry Smith   }
87117ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
87217ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
87317ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
874416022c9SBarry Smith         d    = fshift + a->a[diag[i]+shift];
875416022c9SBarry Smith         n    = diag[i] - a->i[i];
876416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
877416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
87817ab2063SBarry Smith         sum  = b[i];
87917ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
88017ab2063SBarry Smith         x[i] = omega*(sum/d);
88117ab2063SBarry Smith       }
88217ab2063SBarry Smith       xb = x;
88317ab2063SBarry Smith     }
88417ab2063SBarry Smith     else xb = b;
88517ab2063SBarry Smith     if ((flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) &&
88617ab2063SBarry Smith         (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP)) {
88717ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
888416022c9SBarry Smith         x[i] *= a->a[diag[i]+shift];
88917ab2063SBarry Smith       }
89017ab2063SBarry Smith     }
89117ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
89217ab2063SBarry Smith       for ( i=m-1; i>=0; i-- ) {
893416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
894416022c9SBarry Smith         n    = a->i[i+1] - diag[i] - 1;
895416022c9SBarry Smith         idx  = a->j + diag[i] + (!shift);
896416022c9SBarry Smith         v    = a->a + diag[i] + (!shift);
89717ab2063SBarry Smith         sum  = xb[i];
89817ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
89917ab2063SBarry Smith         x[i] = omega*(sum/d);
90017ab2063SBarry Smith       }
90117ab2063SBarry Smith     }
90217ab2063SBarry Smith     its--;
90317ab2063SBarry Smith   }
90417ab2063SBarry Smith   while (its--) {
90517ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
90617ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
907416022c9SBarry Smith         d    = fshift + a->a[diag[i]+shift];
908416022c9SBarry Smith         n    = a->i[i+1] - a->i[i];
909416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
910416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
91117ab2063SBarry Smith         sum  = b[i];
91217ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
9137e33a6baSBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum + a->a[diag[i]+shift]*x[i])/d;
91417ab2063SBarry Smith       }
91517ab2063SBarry Smith     }
91617ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
91717ab2063SBarry Smith       for ( i=m-1; i>=0; i-- ) {
918416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
919416022c9SBarry Smith         n    = a->i[i+1] - a->i[i];
920416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
921416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
92217ab2063SBarry Smith         sum  = b[i];
92317ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
9247e33a6baSBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum + a->a[diag[i]+shift]*x[i])/d;
92517ab2063SBarry Smith       }
92617ab2063SBarry Smith     }
92717ab2063SBarry Smith   }
92817ab2063SBarry Smith   return 0;
92917ab2063SBarry Smith }
93017ab2063SBarry Smith 
931*026e39d0SSatish Balay #undef __FUNCTION__
932*026e39d0SSatish Balay #define __FUNCTION__ "MatGetInfo_SeqAIJ"
9334e220ebcSLois Curfman McInnes static int MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
93417ab2063SBarry Smith {
935416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
9364e220ebcSLois Curfman McInnes 
9374e220ebcSLois Curfman McInnes   info->rows_global    = (double)a->m;
9384e220ebcSLois Curfman McInnes   info->columns_global = (double)a->n;
9394e220ebcSLois Curfman McInnes   info->rows_local     = (double)a->m;
9404e220ebcSLois Curfman McInnes   info->columns_local  = (double)a->n;
9414e220ebcSLois Curfman McInnes   info->block_size     = 1.0;
9424e220ebcSLois Curfman McInnes   info->nz_allocated   = (double)a->maxnz;
9434e220ebcSLois Curfman McInnes   info->nz_used        = (double)a->nz;
9444e220ebcSLois Curfman McInnes   info->nz_unneeded    = (double)(a->maxnz - a->nz);
9454e220ebcSLois Curfman McInnes   /*  if (info->nz_unneeded != A->info.nz_unneeded)
9464e220ebcSLois Curfman McInnes     printf("space descrepancy: maxnz-nz = %d, nz_unneeded = %d\n",(int)info->nz_unneeded,(int)A->info.nz_unneeded); */
9474e220ebcSLois Curfman McInnes   info->assemblies     = (double)A->num_ass;
9484e220ebcSLois Curfman McInnes   info->mallocs        = (double)a->reallocs;
9494e220ebcSLois Curfman McInnes   info->memory         = A->mem;
9504e220ebcSLois Curfman McInnes   if (A->factor) {
9514e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
9524e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
9534e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
9544e220ebcSLois Curfman McInnes   } else {
9554e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
9564e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
9574e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
9584e220ebcSLois Curfman McInnes   }
95917ab2063SBarry Smith   return 0;
96017ab2063SBarry Smith }
96117ab2063SBarry Smith 
96217ab2063SBarry Smith extern int MatLUFactorSymbolic_SeqAIJ(Mat,IS,IS,double,Mat*);
96317ab2063SBarry Smith extern int MatLUFactorNumeric_SeqAIJ(Mat,Mat*);
96417ab2063SBarry Smith extern int MatLUFactor_SeqAIJ(Mat,IS,IS,double);
96517ab2063SBarry Smith extern int MatSolve_SeqAIJ(Mat,Vec,Vec);
96617ab2063SBarry Smith extern int MatSolveAdd_SeqAIJ(Mat,Vec,Vec,Vec);
96717ab2063SBarry Smith extern int MatSolveTrans_SeqAIJ(Mat,Vec,Vec);
96817ab2063SBarry Smith extern int MatSolveTransAdd_SeqAIJ(Mat,Vec,Vec,Vec);
96917ab2063SBarry Smith 
970*026e39d0SSatish Balay #undef __FUNCTION__
971*026e39d0SSatish Balay #define __FUNCTION__ "MatZeroRows_SeqAIJ"
97217ab2063SBarry Smith static int MatZeroRows_SeqAIJ(Mat A,IS is,Scalar *diag)
97317ab2063SBarry Smith {
974416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
975416022c9SBarry Smith   int         i,ierr,N, *rows,m = a->m - 1,shift = a->indexshift;
97617ab2063SBarry Smith 
97777c4ece6SBarry Smith   ierr = ISGetSize(is,&N); CHKERRQ(ierr);
97817ab2063SBarry Smith   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
97917ab2063SBarry Smith   if (diag) {
98017ab2063SBarry Smith     for ( i=0; i<N; i++ ) {
981416022c9SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ(1,"MatZeroRows_SeqAIJ:row out of range");
982416022c9SBarry Smith       if (a->ilen[rows[i]] > 0) { /* in case row was completely empty */
983416022c9SBarry Smith         a->ilen[rows[i]] = 1;
984416022c9SBarry Smith         a->a[a->i[rows[i]]+shift] = *diag;
985416022c9SBarry Smith         a->j[a->i[rows[i]]+shift] = rows[i]+shift;
98617ab2063SBarry Smith       }
98717ab2063SBarry Smith       else {
98817ab2063SBarry Smith         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],diag,INSERT_VALUES);
98917ab2063SBarry Smith         CHKERRQ(ierr);
99017ab2063SBarry Smith       }
99117ab2063SBarry Smith     }
99217ab2063SBarry Smith   }
99317ab2063SBarry Smith   else {
99417ab2063SBarry Smith     for ( i=0; i<N; i++ ) {
995416022c9SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ(1,"MatZeroRows_SeqAIJ:row out of range");
996416022c9SBarry Smith       a->ilen[rows[i]] = 0;
99717ab2063SBarry Smith     }
99817ab2063SBarry Smith   }
99917ab2063SBarry Smith   ISRestoreIndices(is,&rows);
100043a90d84SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
100117ab2063SBarry Smith   return 0;
100217ab2063SBarry Smith }
100317ab2063SBarry Smith 
1004*026e39d0SSatish Balay #undef __FUNCTION__
1005*026e39d0SSatish Balay #define __FUNCTION__ "MatGetSize_SeqAIJ"
1006416022c9SBarry Smith static int MatGetSize_SeqAIJ(Mat A,int *m,int *n)
100717ab2063SBarry Smith {
1008416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
1009416022c9SBarry Smith   *m = a->m; *n = a->n;
101017ab2063SBarry Smith   return 0;
101117ab2063SBarry Smith }
101217ab2063SBarry Smith 
1013*026e39d0SSatish Balay #undef __FUNCTION__
1014*026e39d0SSatish Balay #define __FUNCTION__ "MatGetOwnershipRange_SeqAIJ"
1015416022c9SBarry Smith static int MatGetOwnershipRange_SeqAIJ(Mat A,int *m,int *n)
101617ab2063SBarry Smith {
1017416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
1018416022c9SBarry Smith   *m = 0; *n = a->m;
101917ab2063SBarry Smith   return 0;
102017ab2063SBarry Smith }
1021*026e39d0SSatish Balay 
1022*026e39d0SSatish Balay #undef __FUNCTION__
1023*026e39d0SSatish Balay #define __FUNCTION__ "MatGetRow_SeqAIJ"
10244e093b46SBarry Smith int MatGetRow_SeqAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
102517ab2063SBarry Smith {
1026416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
1027c456f294SBarry Smith   int        *itmp,i,shift = a->indexshift;
102817ab2063SBarry Smith 
1029416022c9SBarry Smith   if (row < 0 || row >= a->m) SETERRQ(1,"MatGetRow_SeqAIJ:Row out of range");
103017ab2063SBarry Smith 
1031416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
1032416022c9SBarry Smith   if (v) *v = a->a + a->i[row] + shift;
103317ab2063SBarry Smith   if (idx) {
1034416022c9SBarry Smith     itmp = a->j + a->i[row] + shift;
10354e093b46SBarry Smith     if (*nz && shift) {
10360452661fSBarry Smith       *idx = (int *) PetscMalloc( (*nz)*sizeof(int) ); CHKPTRQ(*idx);
103717ab2063SBarry Smith       for ( i=0; i<(*nz); i++ ) {(*idx)[i] = itmp[i] + shift;}
10384e093b46SBarry Smith     } else if (*nz) {
10394e093b46SBarry Smith       *idx = itmp;
104017ab2063SBarry Smith     }
104117ab2063SBarry Smith     else *idx = 0;
104217ab2063SBarry Smith   }
104317ab2063SBarry Smith   return 0;
104417ab2063SBarry Smith }
104517ab2063SBarry Smith 
1046*026e39d0SSatish Balay #undef __FUNCTION__
1047*026e39d0SSatish Balay #define __FUNCTION__ "MatRestoreRow_SeqAIJ"
10484e093b46SBarry Smith int MatRestoreRow_SeqAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
104917ab2063SBarry Smith {
10504e093b46SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
10514e093b46SBarry Smith   if (idx) {if (*idx && a->indexshift) PetscFree(*idx);}
105217ab2063SBarry Smith   return 0;
105317ab2063SBarry Smith }
105417ab2063SBarry Smith 
1055*026e39d0SSatish Balay #undef __FUNCTION__
1056*026e39d0SSatish Balay #define __FUNCTION__ "MatNorm_SeqAIJ"
1057cddf8d76SBarry Smith static int MatNorm_SeqAIJ(Mat A,NormType type,double *norm)
105817ab2063SBarry Smith {
1059416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
1060416022c9SBarry Smith   Scalar     *v = a->a;
106117ab2063SBarry Smith   double     sum = 0.0;
1062416022c9SBarry Smith   int        i, j,shift = a->indexshift;
106317ab2063SBarry Smith 
106417ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
1065416022c9SBarry Smith     for (i=0; i<a->nz; i++ ) {
106617ab2063SBarry Smith #if defined(PETSC_COMPLEX)
106717ab2063SBarry Smith       sum += real(conj(*v)*(*v)); v++;
106817ab2063SBarry Smith #else
106917ab2063SBarry Smith       sum += (*v)*(*v); v++;
107017ab2063SBarry Smith #endif
107117ab2063SBarry Smith     }
107217ab2063SBarry Smith     *norm = sqrt(sum);
107317ab2063SBarry Smith   }
107417ab2063SBarry Smith   else if (type == NORM_1) {
107517ab2063SBarry Smith     double *tmp;
1076416022c9SBarry Smith     int    *jj = a->j;
10770452661fSBarry Smith     tmp = (double *) PetscMalloc( a->n*sizeof(double) ); CHKPTRQ(tmp);
1078cddf8d76SBarry Smith     PetscMemzero(tmp,a->n*sizeof(double));
107917ab2063SBarry Smith     *norm = 0.0;
1080416022c9SBarry Smith     for ( j=0; j<a->nz; j++ ) {
1081a2744918SBarry Smith         tmp[*jj++ + shift] += PetscAbsScalar(*v);  v++;
108217ab2063SBarry Smith     }
1083416022c9SBarry Smith     for ( j=0; j<a->n; j++ ) {
108417ab2063SBarry Smith       if (tmp[j] > *norm) *norm = tmp[j];
108517ab2063SBarry Smith     }
10860452661fSBarry Smith     PetscFree(tmp);
108717ab2063SBarry Smith   }
108817ab2063SBarry Smith   else if (type == NORM_INFINITY) {
108917ab2063SBarry Smith     *norm = 0.0;
1090416022c9SBarry Smith     for ( j=0; j<a->m; j++ ) {
1091416022c9SBarry Smith       v = a->a + a->i[j] + shift;
109217ab2063SBarry Smith       sum = 0.0;
1093416022c9SBarry Smith       for ( i=0; i<a->i[j+1]-a->i[j]; i++ ) {
1094cddf8d76SBarry Smith         sum += PetscAbsScalar(*v); v++;
109517ab2063SBarry Smith       }
109617ab2063SBarry Smith       if (sum > *norm) *norm = sum;
109717ab2063SBarry Smith     }
109817ab2063SBarry Smith   }
109917ab2063SBarry Smith   else {
110048d91487SBarry Smith     SETERRQ(1,"MatNorm_SeqAIJ:No support for two norm yet");
110117ab2063SBarry Smith   }
110217ab2063SBarry Smith   return 0;
110317ab2063SBarry Smith }
110417ab2063SBarry Smith 
1105*026e39d0SSatish Balay #undef __FUNCTION__
1106*026e39d0SSatish Balay #define __FUNCTION__ "MatTranspose_SeqAIJ"
1107416022c9SBarry Smith static int MatTranspose_SeqAIJ(Mat A,Mat *B)
110817ab2063SBarry Smith {
1109416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
1110416022c9SBarry Smith   Mat        C;
1111416022c9SBarry Smith   int        i, ierr, *aj = a->j, *ai = a->i, m = a->m, len, *col;
1112416022c9SBarry Smith   int        shift = a->indexshift;
1113d5d45c9bSBarry Smith   Scalar     *array = a->a;
111417ab2063SBarry Smith 
11153638b69dSLois Curfman McInnes   if (B == PETSC_NULL && m != a->n)
1116dfa27b74SSatish Balay     SETERRQ(1,"MatTranspose_SeqAIJ:Square matrix only for in-place");
11170452661fSBarry Smith   col = (int *) PetscMalloc((1+a->n)*sizeof(int)); CHKPTRQ(col);
1118cddf8d76SBarry Smith   PetscMemzero(col,(1+a->n)*sizeof(int));
111917ab2063SBarry Smith   if (shift) {
112017ab2063SBarry Smith     for ( i=0; i<ai[m]-1; i++ ) aj[i] -= 1;
112117ab2063SBarry Smith   }
112217ab2063SBarry Smith   for ( i=0; i<ai[m]+shift; i++ ) col[aj[i]] += 1;
1123416022c9SBarry Smith   ierr = MatCreateSeqAIJ(A->comm,a->n,m,0,col,&C); CHKERRQ(ierr);
11240452661fSBarry Smith   PetscFree(col);
112517ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
112617ab2063SBarry Smith     len = ai[i+1]-ai[i];
1127416022c9SBarry Smith     ierr = MatSetValues(C,len,aj,1,&i,array,INSERT_VALUES); CHKERRQ(ierr);
112817ab2063SBarry Smith     array += len; aj += len;
112917ab2063SBarry Smith   }
113017ab2063SBarry Smith   if (shift) {
113117ab2063SBarry Smith     for ( i=0; i<ai[m]-1; i++ ) aj[i] += 1;
113217ab2063SBarry Smith   }
113317ab2063SBarry Smith 
11346d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
11356d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
113617ab2063SBarry Smith 
11373638b69dSLois Curfman McInnes   if (B != PETSC_NULL) {
1138416022c9SBarry Smith     *B = C;
113917ab2063SBarry Smith   } else {
1140416022c9SBarry Smith     /* This isn't really an in-place transpose */
11410452661fSBarry Smith     PetscFree(a->a);
11420452661fSBarry Smith     if (!a->singlemalloc) {PetscFree(a->i); PetscFree(a->j);}
11430452661fSBarry Smith     if (a->diag) PetscFree(a->diag);
11440452661fSBarry Smith     if (a->ilen) PetscFree(a->ilen);
11450452661fSBarry Smith     if (a->imax) PetscFree(a->imax);
11460452661fSBarry Smith     if (a->solve_work) PetscFree(a->solve_work);
11471073c447SSatish Balay     if (a->inode.size) PetscFree(a->inode.size);
11480452661fSBarry Smith     PetscFree(a);
1149416022c9SBarry Smith     PetscMemcpy(A,C,sizeof(struct _Mat));
11500452661fSBarry Smith     PetscHeaderDestroy(C);
115117ab2063SBarry Smith   }
115217ab2063SBarry Smith   return 0;
115317ab2063SBarry Smith }
115417ab2063SBarry Smith 
1155*026e39d0SSatish Balay #undef __FUNCTION__
1156*026e39d0SSatish Balay #define __FUNCTION__ "MatDiagonalScale_SeqAIJ"
1157f0b747eeSBarry Smith static int MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
115817ab2063SBarry Smith {
1159416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
116017ab2063SBarry Smith   Scalar     *l,*r,x,*v;
1161d5d45c9bSBarry Smith   int        i,j,m = a->m, n = a->n, M, nz = a->nz, *jj,shift = a->indexshift;
116217ab2063SBarry Smith 
116317ab2063SBarry Smith   if (ll) {
11643ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
11653ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
11669b1297e1SSatish Balay     VecGetLocalSize_Fast(ll,m);
1167f0b747eeSBarry Smith     if (m != a->m) SETERRQ(1,"MatDiagonalScale_SeqAIJ:Left scaling vector wrong length");
116890f02eecSBarry Smith     VecGetArray_Fast(ll,l);
1169416022c9SBarry Smith     v = a->a;
117017ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
117117ab2063SBarry Smith       x = l[i];
1172416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
117317ab2063SBarry Smith       for ( j=0; j<M; j++ ) { (*v++) *= x;}
117417ab2063SBarry Smith     }
117544cd7ae7SLois Curfman McInnes     PLogFlops(nz);
117617ab2063SBarry Smith   }
117717ab2063SBarry Smith   if (rr) {
11789b1297e1SSatish Balay     VecGetLocalSize_Fast(rr,n);
1179f0b747eeSBarry Smith     if (n != a->n) SETERRQ(1,"MatDiagonalScale_SeqAIJ:Right scaling vector wrong length");
118090f02eecSBarry Smith     VecGetArray_Fast(rr,r);
1181416022c9SBarry Smith     v = a->a; jj = a->j;
118217ab2063SBarry Smith     for ( i=0; i<nz; i++ ) {
118317ab2063SBarry Smith       (*v++) *= r[*jj++ + shift];
118417ab2063SBarry Smith     }
118544cd7ae7SLois Curfman McInnes     PLogFlops(nz);
118617ab2063SBarry Smith   }
118717ab2063SBarry Smith   return 0;
118817ab2063SBarry Smith }
118917ab2063SBarry Smith 
1190*026e39d0SSatish Balay #undef __FUNCTION__
1191*026e39d0SSatish Balay #define __FUNCTION__ "MatGetSubMatrix_SeqAIJ"
1192cddf8d76SBarry Smith static int MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,MatGetSubMatrixCall scall,Mat *B)
119317ab2063SBarry Smith {
1194db02288aSLois Curfman McInnes   Mat_SeqAIJ   *a = (Mat_SeqAIJ *) A->data,*c;
119502834360SBarry Smith   int          nznew, *smap, i, k, kstart, kend, ierr, oldcols = a->n,*lens;
119699141d43SSatish Balay   int          row,mat_i,*mat_j,tcol,first,step,*mat_ilen;
1197a2744918SBarry Smith   register int sum,lensi;
119899141d43SSatish Balay   int          *irow, *icol, nrows, ncols, shift = a->indexshift,*ssmap;
119999141d43SSatish Balay   int          *starts,*j_new,*i_new,*aj = a->j, *ai = a->i,ii,*ailen = a->ilen;
120099141d43SSatish Balay   Scalar       *a_new,*mat_a;
1201416022c9SBarry Smith   Mat          C;
120217ab2063SBarry Smith 
1203b48a1e75SSatish Balay   ierr = ISSorted(isrow,(PetscTruth*)&i);
1204b48a1e75SSatish Balay   if (!i) SETERRQ(1,"MatGetSubmatrices_SeqAIJ:ISrow is not sorted");
120599141d43SSatish Balay   ierr = ISSorted(iscol,(PetscTruth*)&i);
1206b48a1e75SSatish Balay   if (!i) SETERRQ(1,"MatGetSubmatrices_SeqAIJ:IScol is not sorted");
120799141d43SSatish Balay 
120817ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow); CHKERRQ(ierr);
120917ab2063SBarry Smith   ierr = ISGetSize(isrow,&nrows); CHKERRQ(ierr);
121017ab2063SBarry Smith   ierr = ISGetSize(iscol,&ncols); CHKERRQ(ierr);
121117ab2063SBarry Smith 
12127264ac53SSatish Balay   if (ISStrideGetInfo(iscol,&first,&step) && step == 1) { /* no need to sort */
121302834360SBarry Smith     /* special case of contiguous rows */
121457faeb66SBarry Smith     lens   = (int *) PetscMalloc((ncols+nrows+1)*sizeof(int)); CHKPTRQ(lens);
121502834360SBarry Smith     starts = lens + ncols;
121602834360SBarry Smith     /* loop over new rows determining lens and starting points */
121702834360SBarry Smith     for (i=0; i<nrows; i++) {
1218a2744918SBarry Smith       kstart  = ai[irow[i]]+shift;
1219a2744918SBarry Smith       kend    = kstart + ailen[irow[i]];
122002834360SBarry Smith       for ( k=kstart; k<kend; k++ ) {
1221d8ced48eSBarry Smith         if (aj[k]+shift >= first) {
122202834360SBarry Smith           starts[i] = k;
122302834360SBarry Smith           break;
122402834360SBarry Smith 	}
122502834360SBarry Smith       }
1226a2744918SBarry Smith       sum = 0;
122702834360SBarry Smith       while (k < kend) {
1228d8ced48eSBarry Smith         if (aj[k++]+shift >= first+ncols) break;
1229a2744918SBarry Smith         sum++;
123002834360SBarry Smith       }
1231a2744918SBarry Smith       lens[i] = sum;
123202834360SBarry Smith     }
123302834360SBarry Smith     /* create submatrix */
1234cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
123508480c60SBarry Smith       int n_cols,n_rows;
123608480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols); CHKERRQ(ierr);
123708480c60SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(1,"MatGetSubMatrix_SeqAIJ:");
1238d8ced48eSBarry Smith       ierr = MatZeroEntries(*B); CHKERRQ(ierr);
123908480c60SBarry Smith       C = *B;
124008480c60SBarry Smith     }
124108480c60SBarry Smith     else {
124202834360SBarry Smith       ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr);
124308480c60SBarry Smith     }
1244db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*) C->data;
1245db02288aSLois Curfman McInnes 
124602834360SBarry Smith     /* loop over rows inserting into submatrix */
1247db02288aSLois Curfman McInnes     a_new    = c->a;
1248db02288aSLois Curfman McInnes     j_new    = c->j;
1249db02288aSLois Curfman McInnes     i_new    = c->i;
1250db02288aSLois Curfman McInnes     i_new[0] = -shift;
125102834360SBarry Smith     for (i=0; i<nrows; i++) {
1252a2744918SBarry Smith       ii    = starts[i];
1253a2744918SBarry Smith       lensi = lens[i];
1254a2744918SBarry Smith       for ( k=0; k<lensi; k++ ) {
1255a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
125602834360SBarry Smith       }
1257a2744918SBarry Smith       PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(Scalar));
1258a2744918SBarry Smith       a_new      += lensi;
1259a2744918SBarry Smith       i_new[i+1]  = i_new[i] + lensi;
1260a2744918SBarry Smith       c->ilen[i]  = lensi;
126102834360SBarry Smith     }
12620452661fSBarry Smith     PetscFree(lens);
126302834360SBarry Smith   }
126402834360SBarry Smith   else {
126502834360SBarry Smith     ierr = ISGetIndices(iscol,&icol); CHKERRQ(ierr);
12660452661fSBarry Smith     smap  = (int *) PetscMalloc((1+oldcols)*sizeof(int)); CHKPTRQ(smap);
126702834360SBarry Smith     ssmap = smap + shift;
126899141d43SSatish Balay     lens  = (int *) PetscMalloc((1+nrows)*sizeof(int)); CHKPTRQ(lens);
1269cddf8d76SBarry Smith     PetscMemzero(smap,oldcols*sizeof(int));
127017ab2063SBarry Smith     for ( i=0; i<ncols; i++ ) smap[icol[i]] = i+1;
127102834360SBarry Smith     /* determine lens of each row */
127202834360SBarry Smith     for (i=0; i<nrows; i++) {
1273d8ced48eSBarry Smith       kstart  = ai[irow[i]]+shift;
127402834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
127502834360SBarry Smith       lens[i] = 0;
127602834360SBarry Smith       for ( k=kstart; k<kend; k++ ) {
1277d8ced48eSBarry Smith         if (ssmap[aj[k]]) {
127802834360SBarry Smith           lens[i]++;
127902834360SBarry Smith         }
128002834360SBarry Smith       }
128102834360SBarry Smith     }
128217ab2063SBarry Smith     /* Create and fill new matrix */
1283a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
128499141d43SSatish Balay       c = (Mat_SeqAIJ *)((*B)->data);
128599141d43SSatish Balay 
128699141d43SSatish Balay       if (c->m  != nrows || c->n != ncols) SETERRQ(1,"MatGetSubMatrix_SeqAIJ:");
128799141d43SSatish Balay       if (PetscMemcmp(c->ilen,lens, c->m *sizeof(int))) {
128899141d43SSatish Balay         SETERRQ(1,"MatGetSubmatrices_SeqAIJ:Cannot reuse matrix. wrong no of nonzeros");
128999141d43SSatish Balay       }
129099141d43SSatish Balay       PetscMemzero(c->ilen,c->m*sizeof(int));
129108480c60SBarry Smith       C = *B;
129208480c60SBarry Smith     }
129308480c60SBarry Smith     else {
129402834360SBarry Smith       ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr);
129508480c60SBarry Smith     }
129699141d43SSatish Balay     c = (Mat_SeqAIJ *)(C->data);
129717ab2063SBarry Smith     for (i=0; i<nrows; i++) {
129899141d43SSatish Balay       row    = irow[i];
129917ab2063SBarry Smith       nznew  = 0;
130099141d43SSatish Balay       kstart = ai[row]+shift;
130199141d43SSatish Balay       kend   = kstart + a->ilen[row];
130299141d43SSatish Balay       mat_i  = c->i[i]+shift;
130399141d43SSatish Balay       mat_j  = c->j + mat_i;
130499141d43SSatish Balay       mat_a  = c->a + mat_i;
130599141d43SSatish Balay       mat_ilen = c->ilen + i;
130617ab2063SBarry Smith       for ( k=kstart; k<kend; k++ ) {
130799141d43SSatish Balay         if ((tcol=ssmap[a->j[k]])) {
130899141d43SSatish Balay           *mat_j++ = tcol - (!shift);
130999141d43SSatish Balay           *mat_a++ = a->a[k];
131099141d43SSatish Balay           (*mat_ilen)++;
131199141d43SSatish Balay 
131217ab2063SBarry Smith         }
131317ab2063SBarry Smith       }
131417ab2063SBarry Smith     }
131502834360SBarry Smith     /* Free work space */
131602834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol); CHKERRQ(ierr);
131799141d43SSatish Balay     PetscFree(smap); PetscFree(lens);
131802834360SBarry Smith   }
13196d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
13206d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
132117ab2063SBarry Smith 
132217ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow); CHKERRQ(ierr);
1323416022c9SBarry Smith   *B = C;
132417ab2063SBarry Smith   return 0;
132517ab2063SBarry Smith }
132617ab2063SBarry Smith 
1327a871dcd8SBarry Smith /*
132863b91edcSBarry Smith      note: This can only work for identity for row and col. It would
132963b91edcSBarry Smith    be good to check this and otherwise generate an error.
1330a871dcd8SBarry Smith */
1331*026e39d0SSatish Balay #undef __FUNCTION__
1332*026e39d0SSatish Balay #define __FUNCTION__ "MatILUFactor_SeqAIJ"
133363b91edcSBarry Smith static int MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,double efill,int fill)
1334a871dcd8SBarry Smith {
133563b91edcSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) inA->data;
133608480c60SBarry Smith   int        ierr;
133763b91edcSBarry Smith   Mat        outA;
133863b91edcSBarry Smith 
1339a871dcd8SBarry Smith   if (fill != 0) SETERRQ(1,"MatILUFactor_SeqAIJ:Only fill=0 supported");
1340a871dcd8SBarry Smith 
134163b91edcSBarry Smith   outA          = inA;
134263b91edcSBarry Smith   inA->factor   = FACTOR_LU;
134363b91edcSBarry Smith   a->row        = row;
134463b91edcSBarry Smith   a->col        = col;
134563b91edcSBarry Smith 
13460452661fSBarry Smith   a->solve_work = (Scalar *) PetscMalloc( (a->m+1)*sizeof(Scalar)); CHKPTRQ(a->solve_work);
134763b91edcSBarry Smith 
134808480c60SBarry Smith   if (!a->diag) {
134908480c60SBarry Smith     ierr = MatMarkDiag_SeqAIJ(inA); CHKERRQ(ierr);
135063b91edcSBarry Smith   }
135163b91edcSBarry Smith   ierr = MatLUFactorNumeric_SeqAIJ(inA,&outA); CHKERRQ(ierr);
1352a871dcd8SBarry Smith   return 0;
1353a871dcd8SBarry Smith }
1354a871dcd8SBarry Smith 
1355f0b747eeSBarry Smith #include "pinclude/plapack.h"
1356*026e39d0SSatish Balay #undef __FUNCTION__
1357*026e39d0SSatish Balay #define __FUNCTION__ "MatScale_SeqAIJ"
1358f0b747eeSBarry Smith static int MatScale_SeqAIJ(Scalar *alpha,Mat inA)
1359f0b747eeSBarry Smith {
1360f0b747eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) inA->data;
1361f0b747eeSBarry Smith   int        one = 1;
1362f0b747eeSBarry Smith   BLscal_( &a->nz, alpha, a->a, &one );
1363f0b747eeSBarry Smith   PLogFlops(a->nz);
1364f0b747eeSBarry Smith   return 0;
1365f0b747eeSBarry Smith }
1366f0b747eeSBarry Smith 
1367*026e39d0SSatish Balay #undef __FUNCTION__
1368*026e39d0SSatish Balay #define __FUNCTION__ "MatGetSubMatrices_SeqAIJ"
1369cddf8d76SBarry Smith static int MatGetSubMatrices_SeqAIJ(Mat A,int n, IS *irow,IS *icol,MatGetSubMatrixCall scall,
1370cddf8d76SBarry Smith                                     Mat **B)
1371cddf8d76SBarry Smith {
1372cddf8d76SBarry Smith   int ierr,i;
1373cddf8d76SBarry Smith 
1374cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
13750452661fSBarry Smith     *B = (Mat *) PetscMalloc( (n+1)*sizeof(Mat) ); CHKPTRQ(*B);
1376cddf8d76SBarry Smith   }
1377cddf8d76SBarry Smith 
1378cddf8d76SBarry Smith   for ( i=0; i<n; i++ ) {
1379905e6a2fSBarry Smith     ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],scall,&(*B)[i]);CHKERRQ(ierr);
1380cddf8d76SBarry Smith   }
1381cddf8d76SBarry Smith   return 0;
1382cddf8d76SBarry Smith }
1383cddf8d76SBarry Smith 
1384*026e39d0SSatish Balay #undef __FUNCTION__
1385*026e39d0SSatish Balay #define __FUNCTION__ "MatGetBlockSize_SeqAIJ"
13865a838052SSatish Balay static int MatGetBlockSize_SeqAIJ(Mat A, int *bs)
13875a838052SSatish Balay {
13885a838052SSatish Balay   *bs = 1;
13895a838052SSatish Balay   return 0;
13905a838052SSatish Balay }
13915a838052SSatish Balay 
1392*026e39d0SSatish Balay #undef __FUNCTION__
1393*026e39d0SSatish Balay #define __FUNCTION__ "MatIncreaseOverlap_SeqAIJ"
1394e4d965acSSatish Balay static int MatIncreaseOverlap_SeqAIJ(Mat A, int is_max, IS *is, int ov)
13954dcbc457SBarry Smith {
1396e4d965acSSatish Balay   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
139706763907SSatish Balay   int        shift, row, i,j,k,l,m,n, *idx,ierr, *nidx, isz, val;
13988a047759SSatish Balay   int        start, end, *ai, *aj;
139906763907SSatish Balay   char       *table;
14008a047759SSatish Balay   shift = a->indexshift;
1401e4d965acSSatish Balay   m     = a->m;
1402e4d965acSSatish Balay   ai    = a->i;
14038a047759SSatish Balay   aj    = a->j+shift;
14048a047759SSatish Balay 
1405e4d965acSSatish Balay   if (ov < 0)  SETERRQ(1,"MatIncreaseOverlap_SeqAIJ: illegal overlap value used");
140606763907SSatish Balay 
140706763907SSatish Balay   table = (char *) PetscMalloc((m/BITSPERBYTE +1)*sizeof(char)); CHKPTRQ(table);
140806763907SSatish Balay   nidx  = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(nidx);
140906763907SSatish Balay 
1410e4d965acSSatish Balay   for ( i=0; i<is_max; i++ ) {
1411e4d965acSSatish Balay     /* Initialise the two local arrays */
1412e4d965acSSatish Balay     isz  = 0;
141306763907SSatish Balay     PetscMemzero(table,(m/BITSPERBYTE +1)*sizeof(char));
1414e4d965acSSatish Balay 
1415e4d965acSSatish Balay                 /* Extract the indices, assume there can be duplicate entries */
14164dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);  CHKERRQ(ierr);
141777c4ece6SBarry Smith     ierr = ISGetSize(is[i],&n);  CHKERRQ(ierr);
1418e4d965acSSatish Balay 
1419e4d965acSSatish Balay     /* Enter these into the temp arrays i.e mark table[row], enter row into new index */
1420e4d965acSSatish Balay     for ( j=0; j<n ; ++j){
142106763907SSatish Balay       if(!BT_LOOKUP(table, idx[j])) { nidx[isz++] = idx[j];}
14224dcbc457SBarry Smith     }
142306763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);  CHKERRQ(ierr);
142406763907SSatish Balay     ierr = ISDestroy(is[i]); CHKERRQ(ierr);
1425e4d965acSSatish Balay 
142604a348a9SBarry Smith     k = 0;
142704a348a9SBarry Smith     for ( j=0; j<ov; j++){ /* for each overlap*/
142804a348a9SBarry Smith       n = isz;
142906763907SSatish Balay       for ( ; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
1430e4d965acSSatish Balay         row   = nidx[k];
1431e4d965acSSatish Balay         start = ai[row];
1432e4d965acSSatish Balay         end   = ai[row+1];
143304a348a9SBarry Smith         for ( l = start; l<end ; l++){
14348a047759SSatish Balay           val = aj[l] + shift;
143506763907SSatish Balay           if (!BT_LOOKUP(table,val)) {nidx[isz++] = val;}
1436e4d965acSSatish Balay         }
1437e4d965acSSatish Balay       }
1438e4d965acSSatish Balay     }
1439537820f0SBarry Smith     ierr = ISCreateGeneral(MPI_COMM_SELF, isz, nidx, (is+i)); CHKERRQ(ierr);
1440e4d965acSSatish Balay   }
144104a348a9SBarry Smith   PetscFree(table);
144206763907SSatish Balay   PetscFree(nidx);
1443e4d965acSSatish Balay   return 0;
14444dcbc457SBarry Smith }
144517ab2063SBarry Smith 
1446*026e39d0SSatish Balay #undef __FUNCTION__
1447*026e39d0SSatish Balay #define __FUNCTION__ "MatPrintHelp_SeqAIJ"
1448682d7d0cSBarry Smith int MatPrintHelp_SeqAIJ(Mat A)
1449682d7d0cSBarry Smith {
1450682d7d0cSBarry Smith   static int called = 0;
1451682d7d0cSBarry Smith   MPI_Comm   comm = A->comm;
1452682d7d0cSBarry Smith 
1453682d7d0cSBarry Smith   if (called) return 0; else called = 1;
145477c4ece6SBarry Smith   PetscPrintf(comm," Options for MATSEQAIJ and MATMPIAIJ matrix formats (the defaults):\n");
145577c4ece6SBarry Smith   PetscPrintf(comm,"  -mat_lu_pivotthreshold <threshold>\n");
145677c4ece6SBarry Smith   PetscPrintf(comm,"  -mat_aij_oneindex - internal indices begin at 1 instead of the default 0.\n");
145777c4ece6SBarry Smith   PetscPrintf(comm,"  -mat_aij_no_inode  - Do not use inodes\n");
145877c4ece6SBarry Smith   PetscPrintf(comm,"  -mat_aij_inode_limit <limit> - Set inode limit (max limit=5)\n");
1459682d7d0cSBarry Smith #if defined(HAVE_ESSL)
146077c4ece6SBarry Smith   PetscPrintf(comm,"  -mat_aij_essl  - Use IBM sparse LU factorization and solve.\n");
1461682d7d0cSBarry Smith #endif
1462682d7d0cSBarry Smith   return 0;
1463682d7d0cSBarry Smith }
1464205e38a3SBarry Smith static int MatEqual_SeqAIJ(Mat A,Mat B, PetscTruth* flg);
1465a93ec695SBarry Smith extern int MatFDColoringCreate_SeqAIJ(Mat,ISColoring,MatFDColoring);
1466a93ec695SBarry Smith extern int MatColoringPatch_SeqAIJ(Mat,int,int *,ISColoring *);
1467a93ec695SBarry Smith 
1468682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
146917ab2063SBarry Smith static struct _MatOps MatOps = {MatSetValues_SeqAIJ,
147017ab2063SBarry Smith        MatGetRow_SeqAIJ,MatRestoreRow_SeqAIJ,
1471416022c9SBarry Smith        MatMult_SeqAIJ,MatMultAdd_SeqAIJ,
1472416022c9SBarry Smith        MatMultTrans_SeqAIJ,MatMultTransAdd_SeqAIJ,
147317ab2063SBarry Smith        MatSolve_SeqAIJ,MatSolveAdd_SeqAIJ,
147417ab2063SBarry Smith        MatSolveTrans_SeqAIJ,MatSolveTransAdd_SeqAIJ,
147517ab2063SBarry Smith        MatLUFactor_SeqAIJ,0,
147617ab2063SBarry Smith        MatRelax_SeqAIJ,
147717ab2063SBarry Smith        MatTranspose_SeqAIJ,
14787264ac53SSatish Balay        MatGetInfo_SeqAIJ,MatEqual_SeqAIJ,
1479f0b747eeSBarry Smith        MatGetDiagonal_SeqAIJ,MatDiagonalScale_SeqAIJ,MatNorm_SeqAIJ,
148017ab2063SBarry Smith        0,MatAssemblyEnd_SeqAIJ,
148117ab2063SBarry Smith        MatCompress_SeqAIJ,
148217ab2063SBarry Smith        MatSetOption_SeqAIJ,MatZeroEntries_SeqAIJ,MatZeroRows_SeqAIJ,
148317ab2063SBarry Smith        MatLUFactorSymbolic_SeqAIJ,MatLUFactorNumeric_SeqAIJ,0,0,
148417ab2063SBarry Smith        MatGetSize_SeqAIJ,MatGetSize_SeqAIJ,MatGetOwnershipRange_SeqAIJ,
148517ab2063SBarry Smith        MatILUFactorSymbolic_SeqAIJ,0,
148617ab2063SBarry Smith        0,0,MatConvert_SeqAIJ,
14873d1612f7SBarry Smith        MatConvertSameType_SeqAIJ,0,0,
1488cddf8d76SBarry Smith        MatILUFactor_SeqAIJ,0,0,
14897eb43aa7SLois Curfman McInnes        MatGetSubMatrices_SeqAIJ,MatIncreaseOverlap_SeqAIJ,
1490682d7d0cSBarry Smith        MatGetValues_SeqAIJ,0,
1491f0b747eeSBarry Smith        MatPrintHelp_SeqAIJ,
14925a838052SSatish Balay        MatScale_SeqAIJ,0,0,
14936945ee14SBarry Smith        MatILUDTFactor_SeqAIJ,
14946945ee14SBarry Smith        MatGetBlockSize_SeqAIJ,
14953b2fbd54SBarry Smith        MatGetRowIJ_SeqAIJ,
14963b2fbd54SBarry Smith        MatRestoreRowIJ_SeqAIJ,
14973b2fbd54SBarry Smith        MatGetColumnIJ_SeqAIJ,
1498a93ec695SBarry Smith        MatRestoreColumnIJ_SeqAIJ,
1499a93ec695SBarry Smith        MatFDColoringCreate_SeqAIJ,
1500a93ec695SBarry Smith        MatColoringPatch_SeqAIJ};
150117ab2063SBarry Smith 
150217ab2063SBarry Smith extern int MatUseSuperLU_SeqAIJ(Mat);
150317ab2063SBarry Smith extern int MatUseEssl_SeqAIJ(Mat);
150417ab2063SBarry Smith extern int MatUseDXML_SeqAIJ(Mat);
150517ab2063SBarry Smith 
1506*026e39d0SSatish Balay #undef __FUNCTION__
1507*026e39d0SSatish Balay #define __FUNCTION__ "MatCreateSeqAIJ"
150817ab2063SBarry Smith /*@C
1509682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
15100d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
15116e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
15122bd5e0b2SLois Curfman McInnes    (or the array nzz).  By setting these parameters accurately, performance
15132bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
151417ab2063SBarry Smith 
151517ab2063SBarry Smith    Input Parameters:
151617ab2063SBarry Smith .  comm - MPI communicator, set to MPI_COMM_SELF
151717ab2063SBarry Smith .  m - number of rows
151817ab2063SBarry Smith .  n - number of columns
151917ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
15202bd5e0b2SLois Curfman McInnes .  nzz - array containing the number of nonzeros in the various rows
15212bd5e0b2SLois Curfman McInnes          (possibly different for each row) or PETSC_NULL
152217ab2063SBarry Smith 
152317ab2063SBarry Smith    Output Parameter:
1524416022c9SBarry Smith .  A - the matrix
152517ab2063SBarry Smith 
152617ab2063SBarry Smith    Notes:
152717ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
152817ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
15290002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
153044cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
153117ab2063SBarry Smith 
153217ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
1533a40aa06bSLois Curfman McInnes    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
15343d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
15356da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
153617ab2063SBarry Smith 
1537682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
1538682d7d0cSBarry Smith    improve numerical efficiency of Matrix vector products and solves. We
1539682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
15406c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
15416c7ebb05SLois Curfman McInnes 
15426c7ebb05SLois Curfman McInnes    Options Database Keys:
15436c7ebb05SLois Curfman McInnes $    -mat_aij_no_inode  - Do not use inodes
15446e62573dSLois Curfman McInnes $    -mat_aij_inode_limit <limit> - Set inode limit.
15456e62573dSLois Curfman McInnes $        (max limit=5)
15466e62573dSLois Curfman McInnes $    -mat_aij_oneindex - Internally use indexing starting at 1
15476e62573dSLois Curfman McInnes $        rather than 0.  Note: When calling MatSetValues(),
15486e62573dSLois Curfman McInnes $        the user still MUST index entries starting at 0!
154917ab2063SBarry Smith 
155017ab2063SBarry Smith .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues()
155117ab2063SBarry Smith @*/
1552416022c9SBarry Smith int MatCreateSeqAIJ(MPI_Comm comm,int m,int n,int nz,int *nnz, Mat *A)
155317ab2063SBarry Smith {
1554416022c9SBarry Smith   Mat        B;
1555416022c9SBarry Smith   Mat_SeqAIJ *b;
15566945ee14SBarry Smith   int        i, len, ierr, flg,size;
15576945ee14SBarry Smith 
15586945ee14SBarry Smith   MPI_Comm_size(comm,&size);
15596945ee14SBarry Smith   if (size > 1) SETERRQ(1,"MatCreateSeqAIJ:Comm must be of size 1");
1560d5d45c9bSBarry Smith 
1561416022c9SBarry Smith   *A                  = 0;
15620452661fSBarry Smith   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSEQAIJ,comm);
1563416022c9SBarry Smith   PLogObjectCreate(B);
15640452661fSBarry Smith   B->data             = (void *) (b = PetscNew(Mat_SeqAIJ)); CHKPTRQ(b);
156544cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_SeqAIJ));
1566416022c9SBarry Smith   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
1567416022c9SBarry Smith   B->destroy          = MatDestroy_SeqAIJ;
1568416022c9SBarry Smith   B->view             = MatView_SeqAIJ;
1569416022c9SBarry Smith   B->factor           = 0;
1570416022c9SBarry Smith   B->lupivotthreshold = 1.0;
157190f02eecSBarry Smith   B->mapping          = 0;
15727a743949SBarry Smith   ierr = OptionsGetDouble(PETSC_NULL,"-mat_lu_pivotthreshold",&B->lupivotthreshold,
157369957df2SSatish Balay                           &flg); CHKERRQ(ierr);
15747a743949SBarry Smith   b->ilu_preserve_row_sums = PETSC_FALSE;
15757a743949SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-pc_ilu_preserve_row_sums",
15767a743949SBarry Smith                         (int*) &b->ilu_preserve_row_sums); CHKERRQ(ierr);
1577416022c9SBarry Smith   b->row              = 0;
1578416022c9SBarry Smith   b->col              = 0;
1579416022c9SBarry Smith   b->indexshift       = 0;
1580b810aeb4SBarry Smith   b->reallocs         = 0;
158169957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_oneindex", &flg); CHKERRQ(ierr);
158269957df2SSatish Balay   if (flg) b->indexshift = -1;
158317ab2063SBarry Smith 
158444cd7ae7SLois Curfman McInnes   b->m = m; B->m = m; B->M = m;
158544cd7ae7SLois Curfman McInnes   b->n = n; B->n = n; B->N = n;
15860452661fSBarry Smith   b->imax = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(b->imax);
1587b4fd4287SBarry Smith   if (nnz == PETSC_NULL) {
15887b8455f0SLois Curfman McInnes     if (nz == PETSC_DEFAULT) nz = 10;
15897b8455f0SLois Curfman McInnes     else if (nz <= 0)        nz = 1;
1590416022c9SBarry Smith     for ( i=0; i<m; i++ ) b->imax[i] = nz;
159117ab2063SBarry Smith     nz = nz*m;
159217ab2063SBarry Smith   }
159317ab2063SBarry Smith   else {
159417ab2063SBarry Smith     nz = 0;
1595416022c9SBarry Smith     for ( i=0; i<m; i++ ) {b->imax[i] = nnz[i]; nz += nnz[i];}
159617ab2063SBarry Smith   }
159717ab2063SBarry Smith 
159817ab2063SBarry Smith   /* allocate the matrix space */
1599416022c9SBarry Smith   len     = nz*(sizeof(int) + sizeof(Scalar)) + (b->m+1)*sizeof(int);
16000452661fSBarry Smith   b->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(b->a);
1601416022c9SBarry Smith   b->j  = (int *) (b->a + nz);
1602cddf8d76SBarry Smith   PetscMemzero(b->j,nz*sizeof(int));
1603416022c9SBarry Smith   b->i  = b->j + nz;
1604416022c9SBarry Smith   b->singlemalloc = 1;
160517ab2063SBarry Smith 
1606416022c9SBarry Smith   b->i[0] = -b->indexshift;
160717ab2063SBarry Smith   for (i=1; i<m+1; i++) {
1608416022c9SBarry Smith     b->i[i] = b->i[i-1] + b->imax[i-1];
160917ab2063SBarry Smith   }
161017ab2063SBarry Smith 
1611416022c9SBarry Smith   /* b->ilen will count nonzeros in each row so far. */
16120452661fSBarry Smith   b->ilen = (int *) PetscMalloc((m+1)*sizeof(int));
1613416022c9SBarry Smith   PLogObjectMemory(B,len+2*(m+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqAIJ));
1614416022c9SBarry Smith   for ( i=0; i<b->m; i++ ) { b->ilen[i] = 0;}
161517ab2063SBarry Smith 
1616416022c9SBarry Smith   b->nz               = 0;
1617416022c9SBarry Smith   b->maxnz            = nz;
1618416022c9SBarry Smith   b->sorted           = 0;
1619416022c9SBarry Smith   b->roworiented      = 1;
1620416022c9SBarry Smith   b->nonew            = 0;
1621416022c9SBarry Smith   b->diag             = 0;
1622416022c9SBarry Smith   b->solve_work       = 0;
162371bd300dSLois Curfman McInnes   b->spptr            = 0;
1624754ec7b1SSatish Balay   b->inode.node_count = 0;
1625754ec7b1SSatish Balay   b->inode.size       = 0;
16266c7ebb05SLois Curfman McInnes   b->inode.limit      = 5;
16276c7ebb05SLois Curfman McInnes   b->inode.max_limit  = 5;
16284e220ebcSLois Curfman McInnes   B->info.nz_unneeded = (double)b->maxnz;
162917ab2063SBarry Smith 
1630416022c9SBarry Smith   *A = B;
16314e220ebcSLois Curfman McInnes 
16324b14c69eSBarry Smith   /*  SuperLU is not currently supported through PETSc */
16334b14c69eSBarry Smith #if defined(HAVE_SUPERLU)
163469957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_superlu", &flg); CHKERRQ(ierr);
163569957df2SSatish Balay   if (flg) { ierr = MatUseSuperLU_SeqAIJ(B); CHKERRQ(ierr); }
16364b14c69eSBarry Smith #endif
163769957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_essl", &flg); CHKERRQ(ierr);
163869957df2SSatish Balay   if (flg) { ierr = MatUseEssl_SeqAIJ(B); CHKERRQ(ierr); }
163969957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_dxml", &flg); CHKERRQ(ierr);
164069957df2SSatish Balay   if (flg) {
1641416022c9SBarry Smith     if (!b->indexshift) SETERRQ(1,"MatCreateSeqAIJ:need -mat_aij_oneindex with -mat_aij_dxml");
1642416022c9SBarry Smith     ierr = MatUseDXML_SeqAIJ(B); CHKERRQ(ierr);
164317ab2063SBarry Smith   }
164469957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-help", &flg); CHKERRQ(ierr);
164569957df2SSatish Balay   if (flg) {ierr = MatPrintHelp(B); CHKERRQ(ierr); }
164617ab2063SBarry Smith   return 0;
164717ab2063SBarry Smith }
164817ab2063SBarry Smith 
1649*026e39d0SSatish Balay #undef __FUNCTION__
1650*026e39d0SSatish Balay #define __FUNCTION__ "MatConvertSameType_SeqAIJ"
16513d1612f7SBarry Smith int MatConvertSameType_SeqAIJ(Mat A,Mat *B,int cpvalues)
165217ab2063SBarry Smith {
1653416022c9SBarry Smith   Mat        C;
1654416022c9SBarry Smith   Mat_SeqAIJ *c,*a = (Mat_SeqAIJ *) A->data;
165508480c60SBarry Smith   int        i,len, m = a->m,shift = a->indexshift;
165617ab2063SBarry Smith 
16574043dd9cSLois Curfman McInnes   *B = 0;
16580452661fSBarry Smith   PetscHeaderCreate(C,_Mat,MAT_COOKIE,MATSEQAIJ,A->comm);
1659416022c9SBarry Smith   PLogObjectCreate(C);
16600452661fSBarry Smith   C->data       = (void *) (c = PetscNew(Mat_SeqAIJ)); CHKPTRQ(c);
166141c01911SSatish Balay   PetscMemcpy(&C->ops,&A->ops,sizeof(struct _MatOps));
1662416022c9SBarry Smith   C->destroy    = MatDestroy_SeqAIJ;
1663416022c9SBarry Smith   C->view       = MatView_SeqAIJ;
1664416022c9SBarry Smith   C->factor     = A->factor;
1665416022c9SBarry Smith   c->row        = 0;
1666416022c9SBarry Smith   c->col        = 0;
1667416022c9SBarry Smith   c->indexshift = shift;
1668c456f294SBarry Smith   C->assembled  = PETSC_TRUE;
166917ab2063SBarry Smith 
167044cd7ae7SLois Curfman McInnes   c->m = C->m   = a->m;
167144cd7ae7SLois Curfman McInnes   c->n = C->n   = a->n;
167244cd7ae7SLois Curfman McInnes   C->M          = a->m;
167344cd7ae7SLois Curfman McInnes   C->N          = a->n;
167417ab2063SBarry Smith 
16750452661fSBarry Smith   c->imax       = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(c->imax);
16760452661fSBarry Smith   c->ilen       = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(c->ilen);
167717ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
1678416022c9SBarry Smith     c->imax[i] = a->imax[i];
1679416022c9SBarry Smith     c->ilen[i] = a->ilen[i];
168017ab2063SBarry Smith   }
168117ab2063SBarry Smith 
168217ab2063SBarry Smith   /* allocate the matrix space */
1683416022c9SBarry Smith   c->singlemalloc = 1;
1684416022c9SBarry Smith   len     = (m+1)*sizeof(int)+(a->i[m])*(sizeof(Scalar)+sizeof(int));
16850452661fSBarry Smith   c->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(c->a);
1686416022c9SBarry Smith   c->j  = (int *) (c->a + a->i[m] + shift);
1687416022c9SBarry Smith   c->i  = c->j + a->i[m] + shift;
1688416022c9SBarry Smith   PetscMemcpy(c->i,a->i,(m+1)*sizeof(int));
168917ab2063SBarry Smith   if (m > 0) {
1690416022c9SBarry Smith     PetscMemcpy(c->j,a->j,(a->i[m]+shift)*sizeof(int));
169108480c60SBarry Smith     if (cpvalues == COPY_VALUES) {
1692416022c9SBarry Smith       PetscMemcpy(c->a,a->a,(a->i[m]+shift)*sizeof(Scalar));
169317ab2063SBarry Smith     }
169408480c60SBarry Smith   }
169517ab2063SBarry Smith 
1696416022c9SBarry Smith   PLogObjectMemory(C,len+2*(m+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqAIJ));
1697416022c9SBarry Smith   c->sorted      = a->sorted;
1698416022c9SBarry Smith   c->roworiented = a->roworiented;
1699416022c9SBarry Smith   c->nonew       = a->nonew;
17007a743949SBarry Smith   c->ilu_preserve_row_sums = a->ilu_preserve_row_sums;
170117ab2063SBarry Smith 
1702416022c9SBarry Smith   if (a->diag) {
17030452661fSBarry Smith     c->diag = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(c->diag);
1704416022c9SBarry Smith     PLogObjectMemory(C,(m+1)*sizeof(int));
170517ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
1706416022c9SBarry Smith       c->diag[i] = a->diag[i];
170717ab2063SBarry Smith     }
170817ab2063SBarry Smith   }
1709416022c9SBarry Smith   else c->diag          = 0;
17106c7ebb05SLois Curfman McInnes   c->inode.limit        = a->inode.limit;
17116c7ebb05SLois Curfman McInnes   c->inode.max_limit    = a->inode.max_limit;
1712754ec7b1SSatish Balay   if (a->inode.size){
1713daed632aSSatish Balay     c->inode.size       = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(c->inode.size);
1714754ec7b1SSatish Balay     c->inode.node_count = a->inode.node_count;
1715daed632aSSatish Balay     PetscMemcpy( c->inode.size, a->inode.size, (m+1)*sizeof(int));
1716754ec7b1SSatish Balay   } else {
1717754ec7b1SSatish Balay     c->inode.size       = 0;
1718754ec7b1SSatish Balay     c->inode.node_count = 0;
1719754ec7b1SSatish Balay   }
1720416022c9SBarry Smith   c->nz                 = a->nz;
1721416022c9SBarry Smith   c->maxnz              = a->maxnz;
1722416022c9SBarry Smith   c->solve_work         = 0;
172376dd722bSSatish Balay   c->spptr              = 0;      /* Dangerous -I'm throwing away a->spptr */
1724754ec7b1SSatish Balay 
1725416022c9SBarry Smith   *B = C;
172617ab2063SBarry Smith   return 0;
172717ab2063SBarry Smith }
172817ab2063SBarry Smith 
1729*026e39d0SSatish Balay #undef __FUNCTION__
1730*026e39d0SSatish Balay #define __FUNCTION__ "MatLoad_SeqAIJ"
173119bcc07fSBarry Smith int MatLoad_SeqAIJ(Viewer viewer,MatType type,Mat *A)
173217ab2063SBarry Smith {
1733416022c9SBarry Smith   Mat_SeqAIJ   *a;
1734416022c9SBarry Smith   Mat          B;
173517699dbbSLois Curfman McInnes   int          i, nz, ierr, fd, header[4],size,*rowlengths = 0,M,N,shift;
1736bcd2baecSBarry Smith   MPI_Comm     comm;
173717ab2063SBarry Smith 
173819bcc07fSBarry Smith   PetscObjectGetComm((PetscObject) viewer,&comm);
173917699dbbSLois Curfman McInnes   MPI_Comm_size(comm,&size);
174017699dbbSLois Curfman McInnes   if (size > 1) SETERRQ(1,"MatLoad_SeqAIJ:view must have one processor");
174190ace30eSBarry Smith   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
174277c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,header,4,BINARY_INT); CHKERRQ(ierr);
174348d91487SBarry Smith   if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_SeqAIJ:not matrix object in file");
174417ab2063SBarry Smith   M = header[1]; N = header[2]; nz = header[3];
174517ab2063SBarry Smith 
174617ab2063SBarry Smith   /* read in row lengths */
17470452661fSBarry Smith   rowlengths = (int*) PetscMalloc( M*sizeof(int) ); CHKPTRQ(rowlengths);
174877c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,rowlengths,M,BINARY_INT); CHKERRQ(ierr);
174917ab2063SBarry Smith 
175017ab2063SBarry Smith   /* create our matrix */
1751416022c9SBarry Smith   ierr = MatCreateSeqAIJ(comm,M,N,0,rowlengths,A); CHKERRQ(ierr);
1752416022c9SBarry Smith   B = *A;
1753416022c9SBarry Smith   a = (Mat_SeqAIJ *) B->data;
1754416022c9SBarry Smith   shift = a->indexshift;
175517ab2063SBarry Smith 
175617ab2063SBarry Smith   /* read in column indices and adjust for Fortran indexing*/
175777c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,a->j,nz,BINARY_INT); CHKERRQ(ierr);
175817ab2063SBarry Smith   if (shift) {
175917ab2063SBarry Smith     for ( i=0; i<nz; i++ ) {
1760416022c9SBarry Smith       a->j[i] += 1;
176117ab2063SBarry Smith     }
176217ab2063SBarry Smith   }
176317ab2063SBarry Smith 
176417ab2063SBarry Smith   /* read in nonzero values */
176577c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,a->a,nz,BINARY_SCALAR); CHKERRQ(ierr);
176617ab2063SBarry Smith 
176717ab2063SBarry Smith   /* set matrix "i" values */
1768416022c9SBarry Smith   a->i[0] = -shift;
176917ab2063SBarry Smith   for ( i=1; i<= M; i++ ) {
1770416022c9SBarry Smith     a->i[i]      = a->i[i-1] + rowlengths[i-1];
1771416022c9SBarry Smith     a->ilen[i-1] = rowlengths[i-1];
177217ab2063SBarry Smith   }
17730452661fSBarry Smith   PetscFree(rowlengths);
177417ab2063SBarry Smith 
17756d4a8577SBarry Smith   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
17766d4a8577SBarry Smith   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
177717ab2063SBarry Smith   return 0;
177817ab2063SBarry Smith }
177917ab2063SBarry Smith 
1780*026e39d0SSatish Balay #undef __FUNCTION__
1781*026e39d0SSatish Balay #define __FUNCTION__ "MatEqual_SeqAIJ"
1782686e14cbSSatish Balay static int MatEqual_SeqAIJ(Mat A,Mat B, PetscTruth* flg)
17837264ac53SSatish Balay {
17847264ac53SSatish Balay   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *b = (Mat_SeqAIJ *)B->data;
17857264ac53SSatish Balay 
1786bcd2baecSBarry Smith   if (B->type !=MATSEQAIJ)SETERRQ(1,"MatEqual_SeqAIJ:Matrices must be same type");
17877264ac53SSatish Balay 
17887264ac53SSatish Balay   /* If the  matrix dimensions are not equal, or no of nonzeros or shift */
17897264ac53SSatish Balay   if ((a->m != b->m ) || (a->n !=b->n) ||( a->nz != b->nz)||
1790bcd2baecSBarry Smith       (a->indexshift != b->indexshift)) {
179177c4ece6SBarry Smith     *flg = PETSC_FALSE; return 0;
1792bcd2baecSBarry Smith   }
17937264ac53SSatish Balay 
17947264ac53SSatish Balay   /* if the a->i are the same */
1795bcd2baecSBarry Smith   if (PetscMemcmp(a->i,b->i, (a->n+1)*sizeof(int))) {
179677c4ece6SBarry Smith     *flg = PETSC_FALSE; return 0;
17977264ac53SSatish Balay   }
17987264ac53SSatish Balay 
17997264ac53SSatish Balay   /* if a->j are the same */
1800bcd2baecSBarry Smith   if (PetscMemcmp(a->j, b->j, (a->nz)*sizeof(int))) {
180177c4ece6SBarry Smith     *flg = PETSC_FALSE; return 0;
1802bcd2baecSBarry Smith   }
1803bcd2baecSBarry Smith 
1804bcd2baecSBarry Smith   /* if a->a are the same */
180519bcc07fSBarry Smith   if (PetscMemcmp(a->a, b->a, (a->nz)*sizeof(Scalar))) {
180677c4ece6SBarry Smith     *flg = PETSC_FALSE; return 0;
18077264ac53SSatish Balay   }
180877c4ece6SBarry Smith   *flg = PETSC_TRUE;
18097264ac53SSatish Balay   return 0;
18107264ac53SSatish Balay 
18117264ac53SSatish Balay }
1812