xref: /petsc/src/mat/impls/aij/seq/aij.c (revision a93ec695a732b2c002410144a93bed7b59604242)
16d84be18SBarry Smith 
26945ee14SBarry Smith 
317ab2063SBarry Smith #ifndef lint
4*a93ec695SBarry Smith static char vcid[] = "$Id: aij.c,v 1.187 1996/09/23 16:21:45 bsmith Exp bsmith $";
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 */
20a2ce50c7SBarry Smith int MatILUDTFactor_SeqAIJ(Mat A,double dt,int maxnz,IS row,IS col,Mat *fact)
21a2ce50c7SBarry Smith {
22a2ce50c7SBarry Smith   /* Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data; */
23a2ce50c7SBarry Smith   int        ierr = 1;
24a2ce50c7SBarry Smith 
25a2ce50c7SBarry Smith   SETERRQ(ierr,"MatILUDTFactor_SeqAIJ:Not implemented");
26a2ce50c7SBarry Smith }
27a2ce50c7SBarry Smith 
28bcd2baecSBarry Smith extern int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**);
2917ab2063SBarry Smith 
303b2fbd54SBarry Smith static int MatGetRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia,int **ja,
316945ee14SBarry Smith                            PetscTruth *done)
3217ab2063SBarry Smith {
33416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
346945ee14SBarry Smith   int        ierr,i,ishift;
3517ab2063SBarry Smith 
366945ee14SBarry Smith   *n     = A->n;
376945ee14SBarry Smith   if (!ia) return 0;
386945ee14SBarry Smith   ishift = a->indexshift;
396945ee14SBarry Smith   if (symmetric) {
406945ee14SBarry Smith     ierr = MatToSymmetricIJ_SeqAIJ(a->n,a->i,a->j,ishift,oshift,ia,ja); CHKERRQ(ierr);
416945ee14SBarry Smith   } else if (oshift == 0 && ishift == -1) {
426945ee14SBarry Smith     int nz = a->i[a->n];
433b2fbd54SBarry Smith     /* malloc space and  subtract 1 from i and j indices */
443b2fbd54SBarry Smith     *ia = (int *) PetscMalloc( (a->n+1)*sizeof(int) ); CHKPTRQ(*ia);
453b2fbd54SBarry Smith     *ja = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(*ja);
463b2fbd54SBarry Smith     for ( i=0; i<nz; i++ ) (*ja)[i] = a->j[i] - 1;
473b2fbd54SBarry Smith     for ( i=0; i<a->n+1; i++ ) (*ia)[i] = a->i[i] - 1;
486945ee14SBarry Smith   } else if (oshift == 1 && ishift == 0) {
496945ee14SBarry Smith     int nz = a->i[a->n] + 1;
503b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
513b2fbd54SBarry Smith     *ia = (int *) PetscMalloc( (a->n+1)*sizeof(int) ); CHKPTRQ(*ia);
523b2fbd54SBarry Smith     *ja = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(*ja);
533b2fbd54SBarry Smith     for ( i=0; i<nz; i++ ) (*ja)[i] = a->j[i] + 1;
543b2fbd54SBarry Smith     for ( i=0; i<a->n+1; i++ ) (*ia)[i] = a->i[i] + 1;
556945ee14SBarry Smith   } else {
566945ee14SBarry Smith     *ia = a->i; *ja = a->j;
57a2ce50c7SBarry Smith   }
58a2ce50c7SBarry Smith 
59a2744918SBarry Smith   return 0;
60a2744918SBarry Smith }
61a2744918SBarry Smith 
623b2fbd54SBarry Smith static int MatRestoreRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia,int **ja,
636945ee14SBarry Smith                                PetscTruth *done)
646945ee14SBarry Smith {
656945ee14SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
663b2fbd54SBarry Smith   int        ishift = a->indexshift;
676945ee14SBarry Smith 
686945ee14SBarry Smith   if (!ia) return 0;
693b2fbd54SBarry Smith   if (symmetric || (oshift == 0 && ishift == -1) || (oshift == 1 && ishift == 0)) {
706945ee14SBarry Smith     PetscFree(*ia);
716945ee14SBarry Smith     PetscFree(*ja);
72bcd2baecSBarry Smith   }
7317ab2063SBarry Smith   return 0;
7417ab2063SBarry Smith }
7517ab2063SBarry Smith 
763b2fbd54SBarry Smith static int MatGetColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja,
773b2fbd54SBarry Smith                            PetscTruth *done)
783b2fbd54SBarry Smith {
793b2fbd54SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
80*a93ec695SBarry Smith   int        ierr,i,ishift = a->indexshift,*collengths,*cia,*cja,n = A->n,m = A->m;
81*a93ec695SBarry Smith   int        nz = a->i[m]+ishift,row,*jj,mr,col;
823b2fbd54SBarry Smith 
833b2fbd54SBarry Smith   *nn     = A->n;
843b2fbd54SBarry Smith   if (!ia) return 0;
853b2fbd54SBarry Smith   if (symmetric) {
863b2fbd54SBarry Smith     ierr = MatToSymmetricIJ_SeqAIJ(a->n,a->i,a->j,ishift,oshift,ia,ja); CHKERRQ(ierr);
873b2fbd54SBarry Smith   } else {
883b2fbd54SBarry Smith     collengths = (int *) PetscMalloc( n*sizeof(int) ); CHKPTRQ(collengths);
893b2fbd54SBarry Smith     PetscMemzero(collengths,n*sizeof(int));
903b2fbd54SBarry Smith     cia        = (int *) PetscMalloc( (n+1)*sizeof(int) ); CHKPTRQ(cia);
91*a93ec695SBarry Smith     cja        = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(cja);
923b2fbd54SBarry Smith     jj = a->j;
933b2fbd54SBarry Smith     for ( i=0; i<nz; i++ ) {
943b2fbd54SBarry Smith       collengths[jj[i] + ishift]++;
953b2fbd54SBarry Smith     }
963b2fbd54SBarry Smith     cia[0] = oshift;
973b2fbd54SBarry Smith     for ( i=0; i<n; i++) {
983b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
993b2fbd54SBarry Smith     }
1003b2fbd54SBarry Smith     PetscMemzero(collengths,n*sizeof(int));
1013b2fbd54SBarry Smith     jj = a->j;
102*a93ec695SBarry Smith     for ( row=0; row<m; row++ ) {
103*a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
104*a93ec695SBarry Smith       for ( i=0; i<mr; i++ ) {
1053b2fbd54SBarry Smith         col = *jj++ + ishift;
1063b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
1073b2fbd54SBarry Smith       }
1083b2fbd54SBarry Smith     }
1093b2fbd54SBarry Smith     PetscFree(collengths);
1103b2fbd54SBarry Smith     *ia = cia; *ja = cja;
1113b2fbd54SBarry Smith   }
1123b2fbd54SBarry Smith 
1133b2fbd54SBarry Smith   return 0;
1143b2fbd54SBarry Smith }
1153b2fbd54SBarry Smith 
1163b2fbd54SBarry Smith static int MatRestoreColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia,
1173b2fbd54SBarry Smith                                      int **ja,PetscTruth *done)
1183b2fbd54SBarry Smith {
1193b2fbd54SBarry Smith   if (!ia) return 0;
1203b2fbd54SBarry Smith 
1213b2fbd54SBarry Smith   PetscFree(*ia);
1223b2fbd54SBarry Smith   PetscFree(*ja);
1233b2fbd54SBarry Smith 
1243b2fbd54SBarry Smith   return 0;
1253b2fbd54SBarry Smith }
1263b2fbd54SBarry Smith 
127227d817aSBarry Smith #define CHUNKSIZE   15
12817ab2063SBarry Smith 
12917ab2063SBarry Smith /* This version has row oriented v  */
130416022c9SBarry Smith static int MatSetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is)
13117ab2063SBarry Smith {
132416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
133416022c9SBarry Smith   int        *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax, N, sorted = a->sorted;
1344b0e389bSBarry Smith   int        *imax = a->imax, *ai = a->i, *ailen = a->ilen,roworiented = a->roworiented;
135d5d45c9bSBarry Smith   int        *aj = a->j, nonew = a->nonew,shift = a->indexshift;
136416022c9SBarry Smith   Scalar     *ap,value, *aa = a->a;
13717ab2063SBarry Smith 
13817ab2063SBarry Smith   for ( k=0; k<m; k++ ) { /* loop over added rows */
139416022c9SBarry Smith     row  = im[k];
1403b2fbd54SBarry Smith #if defined(PETSC_BOPT_g)
14117ab2063SBarry Smith     if (row < 0) SETERRQ(1,"MatSetValues_SeqAIJ:Negative row");
142416022c9SBarry Smith     if (row >= a->m) SETERRQ(1,"MatSetValues_SeqAIJ:Row too large");
1433b2fbd54SBarry Smith #endif
14417ab2063SBarry Smith     rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
14517ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
146416022c9SBarry Smith     low = 0;
14717ab2063SBarry Smith     for ( l=0; l<n; l++ ) { /* loop over added columns */
1483b2fbd54SBarry Smith #if defined(PETSC_BOPT_g)
149416022c9SBarry Smith       if (in[l] < 0) SETERRQ(1,"MatSetValues_SeqAIJ:Negative column");
150416022c9SBarry Smith       if (in[l] >= a->n) SETERRQ(1,"MatSetValues_SeqAIJ:Column too large");
1513b2fbd54SBarry Smith #endif
1524b0e389bSBarry Smith       col = in[l] - shift;
1534b0e389bSBarry Smith       if (roworiented) {
1544b0e389bSBarry Smith         value = *v++;
1554b0e389bSBarry Smith       }
1564b0e389bSBarry Smith       else {
1574b0e389bSBarry Smith         value = v[k + l*m];
1584b0e389bSBarry Smith       }
159416022c9SBarry Smith       if (!sorted) low = 0; high = nrow;
160416022c9SBarry Smith       while (high-low > 5) {
161416022c9SBarry Smith         t = (low+high)/2;
162416022c9SBarry Smith         if (rp[t] > col) high = t;
163416022c9SBarry Smith         else             low  = t;
16417ab2063SBarry Smith       }
165416022c9SBarry Smith       for ( i=low; i<high; i++ ) {
16617ab2063SBarry Smith         if (rp[i] > col) break;
16717ab2063SBarry Smith         if (rp[i] == col) {
168416022c9SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
16917ab2063SBarry Smith           else                  ap[i] = value;
17017ab2063SBarry Smith           goto noinsert;
17117ab2063SBarry Smith         }
17217ab2063SBarry Smith       }
17317ab2063SBarry Smith       if (nonew) goto noinsert;
17417ab2063SBarry Smith       if (nrow >= rmax) {
17517ab2063SBarry Smith         /* there is no extra room in row, therefore enlarge */
176416022c9SBarry Smith         int    new_nz = ai[a->m] + CHUNKSIZE,len,*new_i,*new_j;
17717ab2063SBarry Smith         Scalar *new_a;
17817ab2063SBarry Smith 
17917ab2063SBarry Smith         /* malloc new storage space */
180416022c9SBarry Smith         len     = new_nz*(sizeof(int)+sizeof(Scalar))+(a->m+1)*sizeof(int);
1810452661fSBarry Smith         new_a   = (Scalar *) PetscMalloc( len ); CHKPTRQ(new_a);
18217ab2063SBarry Smith         new_j   = (int *) (new_a + new_nz);
18317ab2063SBarry Smith         new_i   = new_j + new_nz;
18417ab2063SBarry Smith 
18517ab2063SBarry Smith         /* copy over old data into new slots */
18617ab2063SBarry Smith         for ( ii=0; ii<row+1; ii++ ) {new_i[ii] = ai[ii];}
187416022c9SBarry Smith         for ( ii=row+1; ii<a->m+1; ii++ ) {new_i[ii] = ai[ii]+CHUNKSIZE;}
188416022c9SBarry Smith         PetscMemcpy(new_j,aj,(ai[row]+nrow+shift)*sizeof(int));
189416022c9SBarry Smith         len = (new_nz - CHUNKSIZE - ai[row] - nrow - shift);
190416022c9SBarry Smith         PetscMemcpy(new_j+ai[row]+shift+nrow+CHUNKSIZE,aj+ai[row]+shift+nrow,
19117ab2063SBarry Smith                                                            len*sizeof(int));
192416022c9SBarry Smith         PetscMemcpy(new_a,aa,(ai[row]+nrow+shift)*sizeof(Scalar));
193416022c9SBarry Smith         PetscMemcpy(new_a+ai[row]+shift+nrow+CHUNKSIZE,aa+ai[row]+shift+nrow,
19417ab2063SBarry Smith                                                            len*sizeof(Scalar));
19517ab2063SBarry Smith         /* free up old matrix storage */
1960452661fSBarry Smith         PetscFree(a->a);
1970452661fSBarry Smith         if (!a->singlemalloc) {PetscFree(a->i);PetscFree(a->j);}
198416022c9SBarry Smith         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
199416022c9SBarry Smith         a->singlemalloc = 1;
20017ab2063SBarry Smith 
20117ab2063SBarry Smith         rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
202416022c9SBarry Smith         rmax = imax[row] = imax[row] + CHUNKSIZE;
203416022c9SBarry Smith         PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + sizeof(Scalar)));
204416022c9SBarry Smith         a->maxnz += CHUNKSIZE;
205b810aeb4SBarry Smith         a->reallocs++;
20617ab2063SBarry Smith       }
207416022c9SBarry Smith       N = nrow++ - 1; a->nz++;
208416022c9SBarry Smith       /* shift up all the later entries in this row */
209416022c9SBarry Smith       for ( ii=N; ii>=i; ii-- ) {
21017ab2063SBarry Smith         rp[ii+1] = rp[ii];
21117ab2063SBarry Smith         ap[ii+1] = ap[ii];
21217ab2063SBarry Smith       }
21317ab2063SBarry Smith       rp[i] = col;
21417ab2063SBarry Smith       ap[i] = value;
21517ab2063SBarry Smith       noinsert:;
216416022c9SBarry Smith       low = i + 1;
21717ab2063SBarry Smith     }
21817ab2063SBarry Smith     ailen[row] = nrow;
21917ab2063SBarry Smith   }
22017ab2063SBarry Smith   return 0;
22117ab2063SBarry Smith }
22217ab2063SBarry Smith 
2237eb43aa7SLois Curfman McInnes static int MatGetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v)
2247eb43aa7SLois Curfman McInnes {
2257eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
226b49de8d1SLois Curfman McInnes   int        *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
2277eb43aa7SLois Curfman McInnes   int        *ai = a->i, *ailen = a->ilen, shift = a->indexshift;
2287eb43aa7SLois Curfman McInnes   Scalar     *ap, *aa = a->a, zero = 0.0;
2297eb43aa7SLois Curfman McInnes 
2307eb43aa7SLois Curfman McInnes   for ( k=0; k<m; k++ ) { /* loop over rows */
2317eb43aa7SLois Curfman McInnes     row  = im[k];
2327eb43aa7SLois Curfman McInnes     if (row < 0) SETERRQ(1,"MatGetValues_SeqAIJ:Negative row");
2337eb43aa7SLois Curfman McInnes     if (row >= a->m) SETERRQ(1,"MatGetValues_SeqAIJ:Row too large");
2347eb43aa7SLois Curfman McInnes     rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
2357eb43aa7SLois Curfman McInnes     nrow = ailen[row];
2367eb43aa7SLois Curfman McInnes     for ( l=0; l<n; l++ ) { /* loop over columns */
2377eb43aa7SLois Curfman McInnes       if (in[l] < 0) SETERRQ(1,"MatGetValues_SeqAIJ:Negative column");
2387eb43aa7SLois Curfman McInnes       if (in[l] >= a->n) SETERRQ(1,"MatGetValues_SeqAIJ:Column too large");
2397eb43aa7SLois Curfman McInnes       col = in[l] - shift;
2407eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
2417eb43aa7SLois Curfman McInnes       while (high-low > 5) {
2427eb43aa7SLois Curfman McInnes         t = (low+high)/2;
2437eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
2447eb43aa7SLois Curfman McInnes         else             low  = t;
2457eb43aa7SLois Curfman McInnes       }
2467eb43aa7SLois Curfman McInnes       for ( i=low; i<high; i++ ) {
2477eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
2487eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
249b49de8d1SLois Curfman McInnes           *v++ = ap[i];
2507eb43aa7SLois Curfman McInnes           goto finished;
2517eb43aa7SLois Curfman McInnes         }
2527eb43aa7SLois Curfman McInnes       }
253b49de8d1SLois Curfman McInnes       *v++ = zero;
2547eb43aa7SLois Curfman McInnes       finished:;
2557eb43aa7SLois Curfman McInnes     }
2567eb43aa7SLois Curfman McInnes   }
2577eb43aa7SLois Curfman McInnes   return 0;
2587eb43aa7SLois Curfman McInnes }
2597eb43aa7SLois Curfman McInnes 
26017ab2063SBarry Smith #include "draw.h"
26117ab2063SBarry Smith #include "pinclude/pviewer.h"
26277c4ece6SBarry Smith #include "sys.h"
26317ab2063SBarry Smith 
264416022c9SBarry Smith static int MatView_SeqAIJ_Binary(Mat A,Viewer viewer)
26517ab2063SBarry Smith {
266416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
267416022c9SBarry Smith   int        i, fd, *col_lens, ierr;
26817ab2063SBarry Smith 
26990ace30eSBarry Smith   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
2700452661fSBarry Smith   col_lens = (int *) PetscMalloc( (4+a->m)*sizeof(int) ); CHKPTRQ(col_lens);
271416022c9SBarry Smith   col_lens[0] = MAT_COOKIE;
272416022c9SBarry Smith   col_lens[1] = a->m;
273416022c9SBarry Smith   col_lens[2] = a->n;
274416022c9SBarry Smith   col_lens[3] = a->nz;
275416022c9SBarry Smith 
276416022c9SBarry Smith   /* store lengths of each row and write (including header) to file */
277416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
278416022c9SBarry Smith     col_lens[4+i] = a->i[i+1] - a->i[i];
27917ab2063SBarry Smith   }
28077c4ece6SBarry Smith   ierr = PetscBinaryWrite(fd,col_lens,4+a->m,BINARY_INT,1); CHKERRQ(ierr);
2810452661fSBarry Smith   PetscFree(col_lens);
282416022c9SBarry Smith 
283416022c9SBarry Smith   /* store column indices (zero start index) */
284416022c9SBarry Smith   if (a->indexshift) {
285416022c9SBarry Smith     for ( i=0; i<a->nz; i++ ) a->j[i]--;
28617ab2063SBarry Smith   }
28777c4ece6SBarry Smith   ierr = PetscBinaryWrite(fd,a->j,a->nz,BINARY_INT,0); CHKERRQ(ierr);
288416022c9SBarry Smith   if (a->indexshift) {
289416022c9SBarry Smith     for ( i=0; i<a->nz; i++ ) a->j[i]++;
29017ab2063SBarry Smith   }
291416022c9SBarry Smith 
292416022c9SBarry Smith   /* store nonzero values */
29377c4ece6SBarry Smith   ierr = PetscBinaryWrite(fd,a->a,a->nz,BINARY_SCALAR,0); CHKERRQ(ierr);
29417ab2063SBarry Smith   return 0;
29517ab2063SBarry Smith }
296416022c9SBarry Smith 
297416022c9SBarry Smith static int MatView_SeqAIJ_ASCII(Mat A,Viewer viewer)
298416022c9SBarry Smith {
299416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ *) A->data;
300496e697eSBarry Smith   int         ierr, i,j, m = a->m, shift = a->indexshift, format, flg1,flg2;
30117ab2063SBarry Smith   FILE        *fd;
30217ab2063SBarry Smith   char        *outputname;
30317ab2063SBarry Smith 
30490ace30eSBarry Smith   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
305416022c9SBarry Smith   ierr = ViewerFileGetOutputname_Private(viewer,&outputname); CHKERRQ(ierr);
30690ace30eSBarry Smith   ierr = ViewerGetFormat(viewer,&format);
307*a93ec695SBarry Smith   if (format == VIEWER_FORMAT_ASCII_INFO) {
30895e01e2fSLois Curfman McInnes     return 0;
30995e01e2fSLois Curfman McInnes   }
310*a93ec695SBarry Smith   else if (format == VIEWER_FORMAT_ASCII_INFO_LONG) {
311496e697eSBarry Smith     ierr = OptionsHasName(PETSC_NULL,"-mat_aij_no_inode",&flg1); CHKERRQ(ierr);
312496e697eSBarry Smith     ierr = OptionsHasName(PETSC_NULL,"-mat_no_unroll",&flg2); CHKERRQ(ierr);
313496e697eSBarry Smith     if (flg1 || flg2) fprintf(fd,"  not using I-node routines\n");
31495e01e2fSLois Curfman McInnes     else     fprintf(fd,"  using I-node routines: found %d nodes, limit used is %d\n",
31595e01e2fSLois Curfman McInnes         a->inode.node_count,a->inode.limit);
31617ab2063SBarry Smith   }
317*a93ec695SBarry Smith   else if (format == VIEWER_FORMAT_ASCII_MATLAB) {
318416022c9SBarry Smith     fprintf(fd,"%% Size = %d %d \n",m,a->n);
3194e220ebcSLois Curfman McInnes     fprintf(fd,"%% Nonzeros = %d \n",a->nz);
3204e220ebcSLois Curfman McInnes     fprintf(fd,"zzz = zeros(%d,3);\n",a->nz);
32117ab2063SBarry Smith     fprintf(fd,"zzz = [\n");
32217ab2063SBarry Smith 
32317ab2063SBarry Smith     for (i=0; i<m; i++) {
324416022c9SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
32517ab2063SBarry Smith #if defined(PETSC_COMPLEX)
3266945ee14SBarry Smith         fprintf(fd,"%d %d  %18.16e + %18.16e i \n",i+1,a->j[j]+!shift,real(a->a[j]),
327416022c9SBarry Smith                    imag(a->a[j]));
32817ab2063SBarry Smith #else
3297a743949SBarry Smith         fprintf(fd,"%d %d  %18.16e\n", i+1, a->j[j]+!shift, a->a[j]);
33017ab2063SBarry Smith #endif
33117ab2063SBarry Smith       }
33217ab2063SBarry Smith     }
33317ab2063SBarry Smith     fprintf(fd,"];\n %s = spconvert(zzz);\n",outputname);
33417ab2063SBarry Smith   }
335*a93ec695SBarry Smith   else if (format == VIEWER_FORMAT_ASCII_COMMON) {
33644cd7ae7SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
33744cd7ae7SLois Curfman McInnes       fprintf(fd,"row %d:",i);
33844cd7ae7SLois Curfman McInnes       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
33944cd7ae7SLois Curfman McInnes #if defined(PETSC_COMPLEX)
34044cd7ae7SLois Curfman McInnes         if (imag(a->a[j]) != 0.0 && real(a->a[j]) != 0.0)
34144cd7ae7SLois Curfman McInnes           fprintf(fd," %d %g + %g i",a->j[j]+shift,real(a->a[j]),imag(a->a[j]));
34244cd7ae7SLois Curfman McInnes         else if (real(a->a[j]) != 0.0)
34344cd7ae7SLois Curfman McInnes           fprintf(fd," %d %g ",a->j[j]+shift,real(a->a[j]));
34444cd7ae7SLois Curfman McInnes #else
34544cd7ae7SLois Curfman McInnes         if (a->a[j] != 0.0) fprintf(fd," %d %g ",a->j[j]+shift,a->a[j]);
34644cd7ae7SLois Curfman McInnes #endif
34744cd7ae7SLois Curfman McInnes       }
34844cd7ae7SLois Curfman McInnes       fprintf(fd,"\n");
34944cd7ae7SLois Curfman McInnes     }
35044cd7ae7SLois Curfman McInnes   }
35117ab2063SBarry Smith   else {
35217ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
35317ab2063SBarry Smith       fprintf(fd,"row %d:",i);
354416022c9SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
35517ab2063SBarry Smith #if defined(PETSC_COMPLEX)
356416022c9SBarry Smith         if (imag(a->a[j]) != 0.0) {
357416022c9SBarry Smith           fprintf(fd," %d %g + %g i",a->j[j]+shift,real(a->a[j]),imag(a->a[j]));
35817ab2063SBarry Smith         }
35917ab2063SBarry Smith         else {
360416022c9SBarry Smith           fprintf(fd," %d %g ",a->j[j]+shift,real(a->a[j]));
36117ab2063SBarry Smith         }
36217ab2063SBarry Smith #else
363416022c9SBarry Smith         fprintf(fd," %d %g ",a->j[j]+shift,a->a[j]);
36417ab2063SBarry Smith #endif
36517ab2063SBarry Smith       }
36617ab2063SBarry Smith       fprintf(fd,"\n");
36717ab2063SBarry Smith     }
36817ab2063SBarry Smith   }
36917ab2063SBarry Smith   fflush(fd);
370416022c9SBarry Smith   return 0;
371416022c9SBarry Smith }
372416022c9SBarry Smith 
373416022c9SBarry Smith static int MatView_SeqAIJ_Draw(Mat A,Viewer viewer)
374416022c9SBarry Smith {
375416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ *) A->data;
376cddf8d76SBarry Smith   int         ierr, i,j, m = a->m, shift = a->indexshift,pause,color;
377cddf8d76SBarry Smith   double      xl,yl,xr,yr,w,h,xc,yc,scale = 1.0,x_l,x_r,y_l,y_r;
378bcd2baecSBarry Smith   Draw        draw;
379cddf8d76SBarry Smith   DrawButton  button;
38019bcc07fSBarry Smith   PetscTruth  isnull;
381cddf8d76SBarry Smith 
382bcd2baecSBarry Smith   ViewerDrawGetDraw(viewer,&draw);
38319bcc07fSBarry Smith   ierr = DrawIsNull(draw,&isnull); CHKERRQ(ierr); if (isnull) return 0;
38419bcc07fSBarry Smith 
385416022c9SBarry Smith   xr  = a->n; yr = a->m; h = yr/10.0; w = xr/10.0;
386416022c9SBarry Smith   xr += w;    yr += h;  xl = -w;     yl = -h;
387416022c9SBarry Smith   ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
388416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
389cddf8d76SBarry Smith   color = DRAW_BLUE;
390416022c9SBarry Smith   for ( i=0; i<m; i++ ) {
391cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
392416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
393cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
394cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
395cddf8d76SBarry Smith       if (real(a->a[j]) >=  0.) continue;
396cddf8d76SBarry Smith #else
397cddf8d76SBarry Smith       if (a->a[j] >=  0.) continue;
398cddf8d76SBarry Smith #endif
399cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
400cddf8d76SBarry Smith     }
401cddf8d76SBarry Smith   }
402cddf8d76SBarry Smith   color = DRAW_CYAN;
403cddf8d76SBarry Smith   for ( i=0; i<m; i++ ) {
404cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
405cddf8d76SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
406cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
407cddf8d76SBarry Smith       if (a->a[j] !=  0.) continue;
408cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
409cddf8d76SBarry Smith     }
410cddf8d76SBarry Smith   }
411cddf8d76SBarry Smith   color = DRAW_RED;
412cddf8d76SBarry Smith   for ( i=0; i<m; i++ ) {
413cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
414cddf8d76SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
415cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
416cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
417cddf8d76SBarry Smith       if (real(a->a[j]) <=  0.) continue;
418cddf8d76SBarry Smith #else
419cddf8d76SBarry Smith       if (a->a[j] <=  0.) continue;
420cddf8d76SBarry Smith #endif
421cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
422416022c9SBarry Smith     }
423416022c9SBarry Smith   }
424416022c9SBarry Smith   DrawFlush(draw);
425cddf8d76SBarry Smith   DrawGetPause(draw,&pause);
426cddf8d76SBarry Smith   if (pause >= 0) { PetscSleep(pause); return 0;}
427cddf8d76SBarry Smith 
428cddf8d76SBarry Smith   /* allow the matrix to zoom or shrink */
4296945ee14SBarry Smith   ierr = DrawCheckResizedWindow(draw);
430cddf8d76SBarry Smith   ierr = DrawGetMouseButton(draw,&button,&xc,&yc,0,0);
431cddf8d76SBarry Smith   while (button != BUTTON_RIGHT) {
432cddf8d76SBarry Smith     DrawClear(draw);
433cddf8d76SBarry Smith     if (button == BUTTON_LEFT) scale = .5;
434cddf8d76SBarry Smith     else if (button == BUTTON_CENTER) scale = 2.;
435cddf8d76SBarry Smith     xl = scale*(xl + w - xc) + xc - w*scale;
436cddf8d76SBarry Smith     xr = scale*(xr - w - xc) + xc + w*scale;
437cddf8d76SBarry Smith     yl = scale*(yl + h - yc) + yc - h*scale;
438cddf8d76SBarry Smith     yr = scale*(yr - h - yc) + yc + h*scale;
439cddf8d76SBarry Smith     w *= scale; h *= scale;
440cddf8d76SBarry Smith     ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
441cddf8d76SBarry Smith     color = DRAW_BLUE;
442cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
443cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
444cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
445cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
446cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
447cddf8d76SBarry Smith         if (real(a->a[j]) >=  0.) continue;
448cddf8d76SBarry Smith #else
449cddf8d76SBarry Smith         if (a->a[j] >=  0.) continue;
450cddf8d76SBarry Smith #endif
451cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
452cddf8d76SBarry Smith       }
453cddf8d76SBarry Smith     }
454cddf8d76SBarry Smith     color = DRAW_CYAN;
455cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
456cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
457cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
458cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
459cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
460cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
461cddf8d76SBarry Smith       }
462cddf8d76SBarry Smith     }
463cddf8d76SBarry Smith     color = DRAW_RED;
464cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
465cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
466cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
467cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
468cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
469cddf8d76SBarry Smith         if (real(a->a[j]) <=  0.) continue;
470cddf8d76SBarry Smith #else
471cddf8d76SBarry Smith         if (a->a[j] <=  0.) continue;
472cddf8d76SBarry Smith #endif
473cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
474cddf8d76SBarry Smith       }
475cddf8d76SBarry Smith     }
4766945ee14SBarry Smith     ierr = DrawCheckResizedWindow(draw);
477cddf8d76SBarry Smith     ierr = DrawGetMouseButton(draw,&button,&xc,&yc,0,0);
478cddf8d76SBarry Smith   }
479416022c9SBarry Smith   return 0;
480416022c9SBarry Smith }
481416022c9SBarry Smith 
482416022c9SBarry Smith static int MatView_SeqAIJ(PetscObject obj,Viewer viewer)
483416022c9SBarry Smith {
484416022c9SBarry Smith   Mat         A = (Mat) obj;
485416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ*) A->data;
486bcd2baecSBarry Smith   ViewerType  vtype;
487bcd2baecSBarry Smith   int         ierr;
488416022c9SBarry Smith 
489bcd2baecSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
490bcd2baecSBarry Smith   if (vtype == MATLAB_VIEWER) {
491416022c9SBarry Smith     return ViewerMatlabPutSparse_Private(viewer,a->m,a->n,a->nz,a->a,a->i,a->j);
492416022c9SBarry Smith   }
493bcd2baecSBarry Smith   else if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER){
494416022c9SBarry Smith     return MatView_SeqAIJ_ASCII(A,viewer);
495416022c9SBarry Smith   }
496bcd2baecSBarry Smith   else if (vtype == BINARY_FILE_VIEWER) {
497416022c9SBarry Smith     return MatView_SeqAIJ_Binary(A,viewer);
498416022c9SBarry Smith   }
499bcd2baecSBarry Smith   else if (vtype == DRAW_VIEWER) {
500bcd2baecSBarry Smith     return MatView_SeqAIJ_Draw(A,viewer);
50117ab2063SBarry Smith   }
50217ab2063SBarry Smith   return 0;
50317ab2063SBarry Smith }
50419bcc07fSBarry Smith 
505c456f294SBarry Smith extern int Mat_AIJ_CheckInode(Mat);
506416022c9SBarry Smith static int MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
50717ab2063SBarry Smith {
508416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
50941c01911SSatish Balay   int        fshift = 0,i,j,*ai = a->i, *aj = a->j, *imax = a->imax,ierr;
510416022c9SBarry Smith   int        m = a->m, *ip, N, *ailen = a->ilen,shift = a->indexshift;
511416022c9SBarry Smith   Scalar     *aa = a->a, *ap;
51217ab2063SBarry Smith 
5136d4a8577SBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) return 0;
51417ab2063SBarry Smith 
51517ab2063SBarry Smith   for ( i=1; i<m; i++ ) {
516416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
51717ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
51817ab2063SBarry Smith     if (fshift) {
519416022c9SBarry Smith       ip = aj + ai[i] + shift; ap = aa + ai[i] + shift;
52017ab2063SBarry Smith       N = ailen[i];
52117ab2063SBarry Smith       for ( j=0; j<N; j++ ) {
52217ab2063SBarry Smith         ip[j-fshift] = ip[j];
52317ab2063SBarry Smith         ap[j-fshift] = ap[j];
52417ab2063SBarry Smith       }
52517ab2063SBarry Smith     }
52617ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
52717ab2063SBarry Smith   }
52817ab2063SBarry Smith   if (m) {
52917ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
53017ab2063SBarry Smith     ai[m] = ai[m-1] + ailen[m-1];
53117ab2063SBarry Smith   }
53217ab2063SBarry Smith   /* reset ilen and imax for each row */
53317ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
53417ab2063SBarry Smith     ailen[i] = imax[i] = ai[i+1] - ai[i];
53517ab2063SBarry Smith   }
536416022c9SBarry Smith   a->nz = ai[m] + shift;
53717ab2063SBarry Smith 
53817ab2063SBarry Smith   /* diagonals may have moved, so kill the diagonal pointers */
539416022c9SBarry Smith   if (fshift && a->diag) {
5400452661fSBarry Smith     PetscFree(a->diag);
541416022c9SBarry Smith     PLogObjectMemory(A,-(m+1)*sizeof(int));
542416022c9SBarry Smith     a->diag = 0;
54317ab2063SBarry Smith   }
5444e220ebcSLois Curfman McInnes   PLogInfo(A,"MatAssemblyEnd_SeqAIJ:Matrix size: %d X %d; storage space: %d unneeded, %d used\n",
5454e220ebcSLois Curfman McInnes            m,a->n,fshift,a->nz);
5464e220ebcSLois Curfman McInnes   PLogInfo(A,"MatAssemblyEnd_SeqAIJ:Number of mallocs during MatSetValues is %d\n",
547b810aeb4SBarry Smith            a->reallocs);
5484e220ebcSLois Curfman McInnes   A->info.nz_unneeded  = (double)fshift;
5494e220ebcSLois Curfman McInnes 
55076dd722bSSatish Balay   /* check out for identical nodes. If found, use inode functions */
55141c01911SSatish Balay   ierr = Mat_AIJ_CheckInode(A); CHKERRQ(ierr);
55217ab2063SBarry Smith   return 0;
55317ab2063SBarry Smith }
55417ab2063SBarry Smith 
555416022c9SBarry Smith static int MatZeroEntries_SeqAIJ(Mat A)
55617ab2063SBarry Smith {
557416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
558cddf8d76SBarry Smith   PetscMemzero(a->a,(a->i[a->m]+a->indexshift)*sizeof(Scalar));
55917ab2063SBarry Smith   return 0;
56017ab2063SBarry Smith }
561416022c9SBarry Smith 
56217ab2063SBarry Smith int MatDestroy_SeqAIJ(PetscObject obj)
56317ab2063SBarry Smith {
564416022c9SBarry Smith   Mat        A  = (Mat) obj;
565416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
566d5d45c9bSBarry Smith 
56717ab2063SBarry Smith #if defined(PETSC_LOG)
568416022c9SBarry Smith   PLogObjectState(obj,"Rows=%d, Cols=%d, NZ=%d",a->m,a->n,a->nz);
56917ab2063SBarry Smith #endif
5700452661fSBarry Smith   PetscFree(a->a);
5710452661fSBarry Smith   if (!a->singlemalloc) { PetscFree(a->i); PetscFree(a->j);}
5720452661fSBarry Smith   if (a->diag) PetscFree(a->diag);
5730452661fSBarry Smith   if (a->ilen) PetscFree(a->ilen);
5740452661fSBarry Smith   if (a->imax) PetscFree(a->imax);
5750452661fSBarry Smith   if (a->solve_work) PetscFree(a->solve_work);
57676dd722bSSatish Balay   if (a->inode.size) PetscFree(a->inode.size);
5770452661fSBarry Smith   PetscFree(a);
578f2655603SLois Curfman McInnes   PLogObjectDestroy(A);
579f2655603SLois Curfman McInnes   PetscHeaderDestroy(A);
58017ab2063SBarry Smith   return 0;
58117ab2063SBarry Smith }
58217ab2063SBarry Smith 
583416022c9SBarry Smith static int MatCompress_SeqAIJ(Mat A)
58417ab2063SBarry Smith {
58517ab2063SBarry Smith   return 0;
58617ab2063SBarry Smith }
58717ab2063SBarry Smith 
588416022c9SBarry Smith static int MatSetOption_SeqAIJ(Mat A,MatOption op)
58917ab2063SBarry Smith {
590416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
5916d4a8577SBarry Smith   if      (op == MAT_ROW_ORIENTED)              a->roworiented = 1;
5926d4a8577SBarry Smith   else if (op == MAT_COLUMN_ORIENTED)           a->roworiented = 0;
5936d4a8577SBarry Smith   else if (op == MAT_COLUMNS_SORTED)            a->sorted      = 1;
5946d4a8577SBarry Smith   else if (op == MAT_NO_NEW_NONZERO_LOCATIONS)  a->nonew       = 1;
5956d4a8577SBarry Smith   else if (op == MAT_YES_NEW_NONZERO_LOCATIONS) a->nonew       = 0;
5966d4a8577SBarry Smith   else if (op == MAT_ROWS_SORTED ||
5976d4a8577SBarry Smith            op == MAT_SYMMETRIC ||
5986d4a8577SBarry Smith            op == MAT_STRUCTURALLY_SYMMETRIC ||
5996d4a8577SBarry Smith            op == MAT_YES_NEW_DIAGONALS)
60094a424c1SBarry Smith     PLogInfo(A,"Info:MatSetOption_SeqAIJ:Option ignored\n");
6016d4a8577SBarry Smith   else if (op == MAT_NO_NEW_DIAGONALS)
6026d4a8577SBarry Smith     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqAIJ:MAT_NO_NEW_DIAGONALS");}
6036d4a8577SBarry Smith   else if (op == MAT_INODE_LIMIT_1)            a->inode.limit  = 1;
6046d4a8577SBarry Smith   else if (op == MAT_INODE_LIMIT_2)            a->inode.limit  = 2;
6056d4a8577SBarry Smith   else if (op == MAT_INODE_LIMIT_3)            a->inode.limit  = 3;
6066d4a8577SBarry Smith   else if (op == MAT_INODE_LIMIT_4)            a->inode.limit  = 4;
6076d4a8577SBarry Smith   else if (op == MAT_INODE_LIMIT_5)            a->inode.limit  = 5;
608e2f28af5SBarry Smith   else
6094d39ef84SLois Curfman McInnes     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqAIJ:unknown option");}
61017ab2063SBarry Smith   return 0;
61117ab2063SBarry Smith }
61217ab2063SBarry Smith 
613416022c9SBarry Smith static int MatGetDiagonal_SeqAIJ(Mat A,Vec v)
61417ab2063SBarry Smith {
615416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
616416022c9SBarry Smith   int        i,j, n,shift = a->indexshift;
61717ab2063SBarry Smith   Scalar     *x, zero = 0.0;
61817ab2063SBarry Smith 
61917ab2063SBarry Smith   VecSet(&zero,v);
62017ab2063SBarry Smith   VecGetArray(v,&x); VecGetLocalSize(v,&n);
621416022c9SBarry Smith   if (n != a->m) SETERRQ(1,"MatGetDiagonal_SeqAIJ:Nonconforming matrix and vector");
622416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
623416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
624416022c9SBarry Smith       if (a->j[j]+shift == i) {
625416022c9SBarry Smith         x[i] = a->a[j];
62617ab2063SBarry Smith         break;
62717ab2063SBarry Smith       }
62817ab2063SBarry Smith     }
62917ab2063SBarry Smith   }
63017ab2063SBarry Smith   return 0;
63117ab2063SBarry Smith }
63217ab2063SBarry Smith 
63317ab2063SBarry Smith /* -------------------------------------------------------*/
63417ab2063SBarry Smith /* Should check that shapes of vectors and matrices match */
63517ab2063SBarry Smith /* -------------------------------------------------------*/
63644cd7ae7SLois Curfman McInnes int MatMultTrans_SeqAIJ(Mat A,Vec xx,Vec yy)
63717ab2063SBarry Smith {
638416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
63917ab2063SBarry Smith   Scalar     *x, *y, *v, alpha;
640416022c9SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift;
64117ab2063SBarry Smith 
64217ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
643cddf8d76SBarry Smith   PetscMemzero(y,a->n*sizeof(Scalar));
64417ab2063SBarry Smith   y = y + shift; /* shift for Fortran start by 1 indexing */
64517ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
646416022c9SBarry Smith     idx   = a->j + a->i[i] + shift;
647416022c9SBarry Smith     v     = a->a + a->i[i] + shift;
648416022c9SBarry Smith     n     = a->i[i+1] - a->i[i];
64917ab2063SBarry Smith     alpha = x[i];
65017ab2063SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
65117ab2063SBarry Smith   }
652416022c9SBarry Smith   PLogFlops(2*a->nz - a->n);
65317ab2063SBarry Smith   return 0;
65417ab2063SBarry Smith }
655d5d45c9bSBarry Smith 
65644cd7ae7SLois Curfman McInnes int MatMultTransAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
65717ab2063SBarry Smith {
658416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
65917ab2063SBarry Smith   Scalar     *x, *y, *v, alpha;
660416022c9SBarry Smith   int        m = a->m, n, i, *idx,shift = a->indexshift;
66117ab2063SBarry Smith 
66217ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
66317ab2063SBarry Smith   if (zz != yy) VecCopy(zz,yy);
66417ab2063SBarry Smith   y = y + shift; /* shift for Fortran start by 1 indexing */
66517ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
666416022c9SBarry Smith     idx   = a->j + a->i[i] + shift;
667416022c9SBarry Smith     v     = a->a + a->i[i] + shift;
668416022c9SBarry Smith     n     = a->i[i+1] - a->i[i];
66917ab2063SBarry Smith     alpha = x[i];
67017ab2063SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
67117ab2063SBarry Smith   }
67217ab2063SBarry Smith   return 0;
67317ab2063SBarry Smith }
67417ab2063SBarry Smith 
67544cd7ae7SLois Curfman McInnes int MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
67617ab2063SBarry Smith {
677416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
67817ab2063SBarry Smith   Scalar     *x, *y, *v, sum;
679416022c9SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift,*ii;
68017ab2063SBarry Smith 
68117ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
68217ab2063SBarry Smith   x    = x + shift; /* shift for Fortran start by 1 indexing */
683416022c9SBarry Smith   idx  = a->j;
684416022c9SBarry Smith   v    = a->a;
685416022c9SBarry Smith   ii   = a->i;
68617ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
687416022c9SBarry Smith     n    = ii[1] - ii[0]; ii++;
68817ab2063SBarry Smith     sum  = 0.0;
68917ab2063SBarry Smith     /* SPARSEDENSEDOT(sum,x,v,idx,n);  */
69017ab2063SBarry Smith     /* for ( j=n-1; j>-1; j--) sum += v[j]*x[idx[j]]; */
691416022c9SBarry Smith     while (n--) sum += *v++ * x[*idx++];
69217ab2063SBarry Smith     y[i] = sum;
69317ab2063SBarry Smith   }
694416022c9SBarry Smith   PLogFlops(2*a->nz - m);
69517ab2063SBarry Smith   return 0;
69617ab2063SBarry Smith }
69717ab2063SBarry Smith 
69844cd7ae7SLois Curfman McInnes int MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
69917ab2063SBarry Smith {
700416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
70117ab2063SBarry Smith   Scalar     *x, *y, *z, *v, sum;
702cddf8d76SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift,*ii;
70317ab2063SBarry Smith 
70417ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z);
70517ab2063SBarry Smith   x    = x + shift; /* shift for Fortran start by 1 indexing */
706cddf8d76SBarry Smith   idx  = a->j;
707cddf8d76SBarry Smith   v    = a->a;
708cddf8d76SBarry Smith   ii   = a->i;
70917ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
710cddf8d76SBarry Smith     n    = ii[1] - ii[0]; ii++;
71117ab2063SBarry Smith     sum  = y[i];
712cddf8d76SBarry Smith     /* SPARSEDENSEDOT(sum,x,v,idx,n);  */
713cddf8d76SBarry Smith     while (n--) sum += *v++ * x[*idx++];
71417ab2063SBarry Smith     z[i] = sum;
71517ab2063SBarry Smith   }
716416022c9SBarry Smith   PLogFlops(2*a->nz);
71717ab2063SBarry Smith   return 0;
71817ab2063SBarry Smith }
71917ab2063SBarry Smith 
72017ab2063SBarry Smith /*
72117ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
72217ab2063SBarry Smith */
72317ab2063SBarry Smith 
724416022c9SBarry Smith int MatMarkDiag_SeqAIJ(Mat A)
72517ab2063SBarry Smith {
726416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
727416022c9SBarry Smith   int        i,j, *diag, m = a->m,shift = a->indexshift;
72817ab2063SBarry Smith 
7290452661fSBarry Smith   diag = (int *) PetscMalloc( (m+1)*sizeof(int)); CHKPTRQ(diag);
730416022c9SBarry Smith   PLogObjectMemory(A,(m+1)*sizeof(int));
731416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
732416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
733416022c9SBarry Smith       if (a->j[j]+shift == i) {
73417ab2063SBarry Smith         diag[i] = j - shift;
73517ab2063SBarry Smith         break;
73617ab2063SBarry Smith       }
73717ab2063SBarry Smith     }
73817ab2063SBarry Smith   }
739416022c9SBarry Smith   a->diag = diag;
74017ab2063SBarry Smith   return 0;
74117ab2063SBarry Smith }
74217ab2063SBarry Smith 
74344cd7ae7SLois Curfman McInnes int MatRelax_SeqAIJ(Mat A,Vec bb,double omega,MatSORType flag,
74417ab2063SBarry Smith                            double fshift,int its,Vec xx)
74517ab2063SBarry Smith {
746416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
747416022c9SBarry Smith   Scalar     *x, *b, *bs,  d, *xs, sum, *v = a->a,*t,scale,*ts, *xb;
748d5d45c9bSBarry Smith   int        ierr, *idx, *diag,n = a->n, m = a->m, i, shift = a->indexshift;
74917ab2063SBarry Smith 
75017ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(bb,&b);
751416022c9SBarry Smith   if (!a->diag) {if ((ierr = MatMarkDiag_SeqAIJ(A))) return ierr;}
752416022c9SBarry Smith   diag = a->diag;
753416022c9SBarry Smith   xs   = x + shift; /* shifted by one for index start of a or a->j*/
75417ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
75517ab2063SBarry Smith    /* apply ( U + D/omega) to the vector */
75617ab2063SBarry Smith     bs = b + shift;
75717ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
758416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
759416022c9SBarry Smith         n    = a->i[i+1] - diag[i] - 1;
760416022c9SBarry Smith         idx  = a->j + diag[i] + (!shift);
761416022c9SBarry Smith         v    = a->a + diag[i] + (!shift);
76217ab2063SBarry Smith         sum  = b[i]*d/omega;
76317ab2063SBarry Smith         SPARSEDENSEDOT(sum,bs,v,idx,n);
76417ab2063SBarry Smith         x[i] = sum;
76517ab2063SBarry Smith     }
76617ab2063SBarry Smith     return 0;
76717ab2063SBarry Smith   }
76817ab2063SBarry Smith   if (flag == SOR_APPLY_LOWER) {
76917ab2063SBarry Smith     SETERRQ(1,"MatRelax_SeqAIJ:SOR_APPLY_LOWER is not done");
77017ab2063SBarry Smith   }
771416022c9SBarry Smith   else if (flag & SOR_EISENSTAT) {
77217ab2063SBarry Smith     /* Let  A = L + U + D; where L is lower trianglar,
77317ab2063SBarry Smith     U is upper triangular, E is diagonal; This routine applies
77417ab2063SBarry Smith 
77517ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
77617ab2063SBarry Smith 
77717ab2063SBarry Smith     to a vector efficiently using Eisenstat's trick. This is for
77817ab2063SBarry Smith     the case of SSOR preconditioner, so E is D/omega where omega
77917ab2063SBarry Smith     is the relaxation factor.
78017ab2063SBarry Smith     */
7810452661fSBarry Smith     t = (Scalar *) PetscMalloc( m*sizeof(Scalar) ); CHKPTRQ(t);
78217ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
78317ab2063SBarry Smith 
78417ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
78517ab2063SBarry Smith     for ( i=m-1; i>=0; i-- ) {
786416022c9SBarry Smith       d    = fshift + a->a[diag[i] + shift];
787416022c9SBarry Smith       n    = a->i[i+1] - diag[i] - 1;
788416022c9SBarry Smith       idx  = a->j + diag[i] + (!shift);
789416022c9SBarry Smith       v    = a->a + diag[i] + (!shift);
79017ab2063SBarry Smith       sum  = b[i];
79117ab2063SBarry Smith       SPARSEDENSEMDOT(sum,xs,v,idx,n);
79217ab2063SBarry Smith       x[i] = omega*(sum/d);
79317ab2063SBarry Smith     }
79417ab2063SBarry Smith 
79517ab2063SBarry Smith     /*  t = b - (2*E - D)x */
796416022c9SBarry Smith     v = a->a;
79717ab2063SBarry Smith     for ( i=0; i<m; i++ ) { t[i] = b[i] - scale*(v[*diag++ + shift])*x[i]; }
79817ab2063SBarry Smith 
79917ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
800416022c9SBarry Smith     ts = t + shift; /* shifted by one for index start of a or a->j*/
801416022c9SBarry Smith     diag = a->diag;
80217ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
803416022c9SBarry Smith       d    = fshift + a->a[diag[i]+shift];
804416022c9SBarry Smith       n    = diag[i] - a->i[i];
805416022c9SBarry Smith       idx  = a->j + a->i[i] + shift;
806416022c9SBarry Smith       v    = a->a + a->i[i] + shift;
80717ab2063SBarry Smith       sum  = t[i];
80817ab2063SBarry Smith       SPARSEDENSEMDOT(sum,ts,v,idx,n);
80917ab2063SBarry Smith       t[i] = omega*(sum/d);
81017ab2063SBarry Smith     }
81117ab2063SBarry Smith 
81217ab2063SBarry Smith     /*  x = x + t */
81317ab2063SBarry Smith     for ( i=0; i<m; i++ ) { x[i] += t[i]; }
8140452661fSBarry Smith     PetscFree(t);
81517ab2063SBarry Smith     return 0;
81617ab2063SBarry Smith   }
81717ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
81817ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
81917ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
820416022c9SBarry Smith         d    = fshift + a->a[diag[i]+shift];
821416022c9SBarry Smith         n    = diag[i] - a->i[i];
822416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
823416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
82417ab2063SBarry Smith         sum  = b[i];
82517ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
82617ab2063SBarry Smith         x[i] = omega*(sum/d);
82717ab2063SBarry Smith       }
82817ab2063SBarry Smith       xb = x;
82917ab2063SBarry Smith     }
83017ab2063SBarry Smith     else xb = b;
83117ab2063SBarry Smith     if ((flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) &&
83217ab2063SBarry Smith         (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP)) {
83317ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
834416022c9SBarry Smith         x[i] *= a->a[diag[i]+shift];
83517ab2063SBarry Smith       }
83617ab2063SBarry Smith     }
83717ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
83817ab2063SBarry Smith       for ( i=m-1; i>=0; i-- ) {
839416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
840416022c9SBarry Smith         n    = a->i[i+1] - diag[i] - 1;
841416022c9SBarry Smith         idx  = a->j + diag[i] + (!shift);
842416022c9SBarry Smith         v    = a->a + diag[i] + (!shift);
84317ab2063SBarry Smith         sum  = xb[i];
84417ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
84517ab2063SBarry Smith         x[i] = omega*(sum/d);
84617ab2063SBarry Smith       }
84717ab2063SBarry Smith     }
84817ab2063SBarry Smith     its--;
84917ab2063SBarry Smith   }
85017ab2063SBarry Smith   while (its--) {
85117ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
85217ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
853416022c9SBarry Smith         d    = fshift + a->a[diag[i]+shift];
854416022c9SBarry Smith         n    = a->i[i+1] - a->i[i];
855416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
856416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
85717ab2063SBarry Smith         sum  = b[i];
85817ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
8597e33a6baSBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum + a->a[diag[i]+shift]*x[i])/d;
86017ab2063SBarry Smith       }
86117ab2063SBarry Smith     }
86217ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
86317ab2063SBarry Smith       for ( i=m-1; i>=0; i-- ) {
864416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
865416022c9SBarry Smith         n    = a->i[i+1] - a->i[i];
866416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
867416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
86817ab2063SBarry Smith         sum  = b[i];
86917ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
8707e33a6baSBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum + a->a[diag[i]+shift]*x[i])/d;
87117ab2063SBarry Smith       }
87217ab2063SBarry Smith     }
87317ab2063SBarry Smith   }
87417ab2063SBarry Smith   return 0;
87517ab2063SBarry Smith }
87617ab2063SBarry Smith 
8774e220ebcSLois Curfman McInnes static int MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
87817ab2063SBarry Smith {
879416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
8804e220ebcSLois Curfman McInnes 
8814e220ebcSLois Curfman McInnes   info->rows_global    = (double)a->m;
8824e220ebcSLois Curfman McInnes   info->columns_global = (double)a->n;
8834e220ebcSLois Curfman McInnes   info->rows_local     = (double)a->m;
8844e220ebcSLois Curfman McInnes   info->columns_local  = (double)a->n;
8854e220ebcSLois Curfman McInnes   info->block_size     = 1.0;
8864e220ebcSLois Curfman McInnes   info->nz_allocated   = (double)a->maxnz;
8874e220ebcSLois Curfman McInnes   info->nz_used        = (double)a->nz;
8884e220ebcSLois Curfman McInnes   info->nz_unneeded    = (double)(a->maxnz - a->nz);
8894e220ebcSLois Curfman McInnes   /*  if (info->nz_unneeded != A->info.nz_unneeded)
8904e220ebcSLois Curfman McInnes     printf("space descrepancy: maxnz-nz = %d, nz_unneeded = %d\n",(int)info->nz_unneeded,(int)A->info.nz_unneeded); */
8914e220ebcSLois Curfman McInnes   info->assemblies     = (double)A->num_ass;
8924e220ebcSLois Curfman McInnes   info->mallocs        = (double)a->reallocs;
8934e220ebcSLois Curfman McInnes   info->memory         = A->mem;
8944e220ebcSLois Curfman McInnes   if (A->factor) {
8954e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
8964e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
8974e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
8984e220ebcSLois Curfman McInnes   } else {
8994e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
9004e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
9014e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
9024e220ebcSLois Curfman McInnes   }
90317ab2063SBarry Smith   return 0;
90417ab2063SBarry Smith }
90517ab2063SBarry Smith 
90617ab2063SBarry Smith extern int MatLUFactorSymbolic_SeqAIJ(Mat,IS,IS,double,Mat*);
90717ab2063SBarry Smith extern int MatLUFactorNumeric_SeqAIJ(Mat,Mat*);
90817ab2063SBarry Smith extern int MatLUFactor_SeqAIJ(Mat,IS,IS,double);
90917ab2063SBarry Smith extern int MatSolve_SeqAIJ(Mat,Vec,Vec);
91017ab2063SBarry Smith extern int MatSolveAdd_SeqAIJ(Mat,Vec,Vec,Vec);
91117ab2063SBarry Smith extern int MatSolveTrans_SeqAIJ(Mat,Vec,Vec);
91217ab2063SBarry Smith extern int MatSolveTransAdd_SeqAIJ(Mat,Vec,Vec,Vec);
91317ab2063SBarry Smith 
91417ab2063SBarry Smith static int MatZeroRows_SeqAIJ(Mat A,IS is,Scalar *diag)
91517ab2063SBarry Smith {
916416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
917416022c9SBarry Smith   int         i,ierr,N, *rows,m = a->m - 1,shift = a->indexshift;
91817ab2063SBarry Smith 
91977c4ece6SBarry Smith   ierr = ISGetSize(is,&N); CHKERRQ(ierr);
92017ab2063SBarry Smith   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
92117ab2063SBarry Smith   if (diag) {
92217ab2063SBarry Smith     for ( i=0; i<N; i++ ) {
923416022c9SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ(1,"MatZeroRows_SeqAIJ:row out of range");
924416022c9SBarry Smith       if (a->ilen[rows[i]] > 0) { /* in case row was completely empty */
925416022c9SBarry Smith         a->ilen[rows[i]] = 1;
926416022c9SBarry Smith         a->a[a->i[rows[i]]+shift] = *diag;
927416022c9SBarry Smith         a->j[a->i[rows[i]]+shift] = rows[i]+shift;
92817ab2063SBarry Smith       }
92917ab2063SBarry Smith       else {
93017ab2063SBarry Smith         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],diag,INSERT_VALUES);
93117ab2063SBarry Smith         CHKERRQ(ierr);
93217ab2063SBarry Smith       }
93317ab2063SBarry Smith     }
93417ab2063SBarry Smith   }
93517ab2063SBarry Smith   else {
93617ab2063SBarry Smith     for ( i=0; i<N; i++ ) {
937416022c9SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ(1,"MatZeroRows_SeqAIJ:row out of range");
938416022c9SBarry Smith       a->ilen[rows[i]] = 0;
93917ab2063SBarry Smith     }
94017ab2063SBarry Smith   }
94117ab2063SBarry Smith   ISRestoreIndices(is,&rows);
9426d4a8577SBarry Smith   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
9436d4a8577SBarry Smith   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
94417ab2063SBarry Smith   return 0;
94517ab2063SBarry Smith }
94617ab2063SBarry Smith 
947416022c9SBarry Smith static int MatGetSize_SeqAIJ(Mat A,int *m,int *n)
94817ab2063SBarry Smith {
949416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
950416022c9SBarry Smith   *m = a->m; *n = a->n;
95117ab2063SBarry Smith   return 0;
95217ab2063SBarry Smith }
95317ab2063SBarry Smith 
954416022c9SBarry Smith static int MatGetOwnershipRange_SeqAIJ(Mat A,int *m,int *n)
95517ab2063SBarry Smith {
956416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
957416022c9SBarry Smith   *m = 0; *n = a->m;
95817ab2063SBarry Smith   return 0;
95917ab2063SBarry Smith }
9604e093b46SBarry Smith int MatGetRow_SeqAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
96117ab2063SBarry Smith {
962416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
963c456f294SBarry Smith   int        *itmp,i,shift = a->indexshift;
96417ab2063SBarry Smith 
965416022c9SBarry Smith   if (row < 0 || row >= a->m) SETERRQ(1,"MatGetRow_SeqAIJ:Row out of range");
96617ab2063SBarry Smith 
967416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
968416022c9SBarry Smith   if (v) *v = a->a + a->i[row] + shift;
96917ab2063SBarry Smith   if (idx) {
970416022c9SBarry Smith     itmp = a->j + a->i[row] + shift;
9714e093b46SBarry Smith     if (*nz && shift) {
9720452661fSBarry Smith       *idx = (int *) PetscMalloc( (*nz)*sizeof(int) ); CHKPTRQ(*idx);
97317ab2063SBarry Smith       for ( i=0; i<(*nz); i++ ) {(*idx)[i] = itmp[i] + shift;}
9744e093b46SBarry Smith     } else if (*nz) {
9754e093b46SBarry Smith       *idx = itmp;
97617ab2063SBarry Smith     }
97717ab2063SBarry Smith     else *idx = 0;
97817ab2063SBarry Smith   }
97917ab2063SBarry Smith   return 0;
98017ab2063SBarry Smith }
98117ab2063SBarry Smith 
9824e093b46SBarry Smith int MatRestoreRow_SeqAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
98317ab2063SBarry Smith {
9844e093b46SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
9854e093b46SBarry Smith   if (idx) {if (*idx && a->indexshift) PetscFree(*idx);}
98617ab2063SBarry Smith   return 0;
98717ab2063SBarry Smith }
98817ab2063SBarry Smith 
989cddf8d76SBarry Smith static int MatNorm_SeqAIJ(Mat A,NormType type,double *norm)
99017ab2063SBarry Smith {
991416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
992416022c9SBarry Smith   Scalar     *v = a->a;
99317ab2063SBarry Smith   double     sum = 0.0;
994416022c9SBarry Smith   int        i, j,shift = a->indexshift;
99517ab2063SBarry Smith 
99617ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
997416022c9SBarry Smith     for (i=0; i<a->nz; i++ ) {
99817ab2063SBarry Smith #if defined(PETSC_COMPLEX)
99917ab2063SBarry Smith       sum += real(conj(*v)*(*v)); v++;
100017ab2063SBarry Smith #else
100117ab2063SBarry Smith       sum += (*v)*(*v); v++;
100217ab2063SBarry Smith #endif
100317ab2063SBarry Smith     }
100417ab2063SBarry Smith     *norm = sqrt(sum);
100517ab2063SBarry Smith   }
100617ab2063SBarry Smith   else if (type == NORM_1) {
100717ab2063SBarry Smith     double *tmp;
1008416022c9SBarry Smith     int    *jj = a->j;
10090452661fSBarry Smith     tmp = (double *) PetscMalloc( a->n*sizeof(double) ); CHKPTRQ(tmp);
1010cddf8d76SBarry Smith     PetscMemzero(tmp,a->n*sizeof(double));
101117ab2063SBarry Smith     *norm = 0.0;
1012416022c9SBarry Smith     for ( j=0; j<a->nz; j++ ) {
1013a2744918SBarry Smith         tmp[*jj++ + shift] += PetscAbsScalar(*v);  v++;
101417ab2063SBarry Smith     }
1015416022c9SBarry Smith     for ( j=0; j<a->n; j++ ) {
101617ab2063SBarry Smith       if (tmp[j] > *norm) *norm = tmp[j];
101717ab2063SBarry Smith     }
10180452661fSBarry Smith     PetscFree(tmp);
101917ab2063SBarry Smith   }
102017ab2063SBarry Smith   else if (type == NORM_INFINITY) {
102117ab2063SBarry Smith     *norm = 0.0;
1022416022c9SBarry Smith     for ( j=0; j<a->m; j++ ) {
1023416022c9SBarry Smith       v = a->a + a->i[j] + shift;
102417ab2063SBarry Smith       sum = 0.0;
1025416022c9SBarry Smith       for ( i=0; i<a->i[j+1]-a->i[j]; i++ ) {
1026cddf8d76SBarry Smith         sum += PetscAbsScalar(*v); v++;
102717ab2063SBarry Smith       }
102817ab2063SBarry Smith       if (sum > *norm) *norm = sum;
102917ab2063SBarry Smith     }
103017ab2063SBarry Smith   }
103117ab2063SBarry Smith   else {
103248d91487SBarry Smith     SETERRQ(1,"MatNorm_SeqAIJ:No support for two norm yet");
103317ab2063SBarry Smith   }
103417ab2063SBarry Smith   return 0;
103517ab2063SBarry Smith }
103617ab2063SBarry Smith 
1037416022c9SBarry Smith static int MatTranspose_SeqAIJ(Mat A,Mat *B)
103817ab2063SBarry Smith {
1039416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
1040416022c9SBarry Smith   Mat        C;
1041416022c9SBarry Smith   int        i, ierr, *aj = a->j, *ai = a->i, m = a->m, len, *col;
1042416022c9SBarry Smith   int        shift = a->indexshift;
1043d5d45c9bSBarry Smith   Scalar     *array = a->a;
104417ab2063SBarry Smith 
10453638b69dSLois Curfman McInnes   if (B == PETSC_NULL && m != a->n)
1046dfa27b74SSatish Balay     SETERRQ(1,"MatTranspose_SeqAIJ:Square matrix only for in-place");
10470452661fSBarry Smith   col = (int *) PetscMalloc((1+a->n)*sizeof(int)); CHKPTRQ(col);
1048cddf8d76SBarry Smith   PetscMemzero(col,(1+a->n)*sizeof(int));
104917ab2063SBarry Smith   if (shift) {
105017ab2063SBarry Smith     for ( i=0; i<ai[m]-1; i++ ) aj[i] -= 1;
105117ab2063SBarry Smith   }
105217ab2063SBarry Smith   for ( i=0; i<ai[m]+shift; i++ ) col[aj[i]] += 1;
1053416022c9SBarry Smith   ierr = MatCreateSeqAIJ(A->comm,a->n,m,0,col,&C); CHKERRQ(ierr);
10540452661fSBarry Smith   PetscFree(col);
105517ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
105617ab2063SBarry Smith     len = ai[i+1]-ai[i];
1057416022c9SBarry Smith     ierr = MatSetValues(C,len,aj,1,&i,array,INSERT_VALUES); CHKERRQ(ierr);
105817ab2063SBarry Smith     array += len; aj += len;
105917ab2063SBarry Smith   }
106017ab2063SBarry Smith   if (shift) {
106117ab2063SBarry Smith     for ( i=0; i<ai[m]-1; i++ ) aj[i] += 1;
106217ab2063SBarry Smith   }
106317ab2063SBarry Smith 
10646d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
10656d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
106617ab2063SBarry Smith 
10673638b69dSLois Curfman McInnes   if (B != PETSC_NULL) {
1068416022c9SBarry Smith     *B = C;
106917ab2063SBarry Smith   } else {
1070416022c9SBarry Smith     /* This isn't really an in-place transpose */
10710452661fSBarry Smith     PetscFree(a->a);
10720452661fSBarry Smith     if (!a->singlemalloc) {PetscFree(a->i); PetscFree(a->j);}
10730452661fSBarry Smith     if (a->diag) PetscFree(a->diag);
10740452661fSBarry Smith     if (a->ilen) PetscFree(a->ilen);
10750452661fSBarry Smith     if (a->imax) PetscFree(a->imax);
10760452661fSBarry Smith     if (a->solve_work) PetscFree(a->solve_work);
10771073c447SSatish Balay     if (a->inode.size) PetscFree(a->inode.size);
10780452661fSBarry Smith     PetscFree(a);
1079416022c9SBarry Smith     PetscMemcpy(A,C,sizeof(struct _Mat));
10800452661fSBarry Smith     PetscHeaderDestroy(C);
108117ab2063SBarry Smith   }
108217ab2063SBarry Smith   return 0;
108317ab2063SBarry Smith }
108417ab2063SBarry Smith 
1085f0b747eeSBarry Smith static int MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
108617ab2063SBarry Smith {
1087416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
108817ab2063SBarry Smith   Scalar     *l,*r,x,*v;
1089d5d45c9bSBarry Smith   int        i,j,m = a->m, n = a->n, M, nz = a->nz, *jj,shift = a->indexshift;
109017ab2063SBarry Smith 
109117ab2063SBarry Smith   if (ll) {
109217ab2063SBarry Smith     VecGetArray(ll,&l); VecGetSize(ll,&m);
1093f0b747eeSBarry Smith     if (m != a->m) SETERRQ(1,"MatDiagonalScale_SeqAIJ:Left scaling vector wrong length");
1094416022c9SBarry Smith     v = a->a;
109517ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
109617ab2063SBarry Smith       x = l[i];
1097416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
109817ab2063SBarry Smith       for ( j=0; j<M; j++ ) { (*v++) *= x;}
109917ab2063SBarry Smith     }
110044cd7ae7SLois Curfman McInnes     PLogFlops(nz);
110117ab2063SBarry Smith   }
110217ab2063SBarry Smith   if (rr) {
110317ab2063SBarry Smith     VecGetArray(rr,&r); VecGetSize(rr,&n);
1104f0b747eeSBarry Smith     if (n != a->n) SETERRQ(1,"MatDiagonalScale_SeqAIJ:Right scaling vector wrong length");
1105416022c9SBarry Smith     v = a->a; jj = a->j;
110617ab2063SBarry Smith     for ( i=0; i<nz; i++ ) {
110717ab2063SBarry Smith       (*v++) *= r[*jj++ + shift];
110817ab2063SBarry Smith     }
110944cd7ae7SLois Curfman McInnes     PLogFlops(nz);
111017ab2063SBarry Smith   }
111117ab2063SBarry Smith   return 0;
111217ab2063SBarry Smith }
111317ab2063SBarry Smith 
1114cddf8d76SBarry Smith static int MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,MatGetSubMatrixCall scall,Mat *B)
111517ab2063SBarry Smith {
1116db02288aSLois Curfman McInnes   Mat_SeqAIJ   *a = (Mat_SeqAIJ *) A->data,*c;
111702834360SBarry Smith   int          nznew, *smap, i, k, kstart, kend, ierr, oldcols = a->n,*lens;
111899141d43SSatish Balay   int          row,mat_i,*mat_j,tcol,first,step,*mat_ilen;
1119a2744918SBarry Smith   register int sum,lensi;
112099141d43SSatish Balay   int          *irow, *icol, nrows, ncols, shift = a->indexshift,*ssmap;
112199141d43SSatish Balay   int          *starts,*j_new,*i_new,*aj = a->j, *ai = a->i,ii,*ailen = a->ilen;
112299141d43SSatish Balay   Scalar       *a_new,*mat_a;
1123416022c9SBarry Smith   Mat          C;
112417ab2063SBarry Smith 
1125b48a1e75SSatish Balay   ierr = ISSorted(isrow,(PetscTruth*)&i);
1126b48a1e75SSatish Balay   if (!i) SETERRQ(1,"MatGetSubmatrices_SeqAIJ:ISrow is not sorted");
112799141d43SSatish Balay   ierr = ISSorted(iscol,(PetscTruth*)&i);
1128b48a1e75SSatish Balay   if (!i) SETERRQ(1,"MatGetSubmatrices_SeqAIJ:IScol is not sorted");
112999141d43SSatish Balay 
113017ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow); CHKERRQ(ierr);
113117ab2063SBarry Smith   ierr = ISGetSize(isrow,&nrows); CHKERRQ(ierr);
113217ab2063SBarry Smith   ierr = ISGetSize(iscol,&ncols); CHKERRQ(ierr);
113317ab2063SBarry Smith 
11347264ac53SSatish Balay   if (ISStrideGetInfo(iscol,&first,&step) && step == 1) { /* no need to sort */
113502834360SBarry Smith     /* special case of contiguous rows */
113657faeb66SBarry Smith     lens   = (int *) PetscMalloc((ncols+nrows+1)*sizeof(int)); CHKPTRQ(lens);
113702834360SBarry Smith     starts = lens + ncols;
113802834360SBarry Smith     /* loop over new rows determining lens and starting points */
113902834360SBarry Smith     for (i=0; i<nrows; i++) {
1140a2744918SBarry Smith       kstart  = ai[irow[i]]+shift;
1141a2744918SBarry Smith       kend    = kstart + ailen[irow[i]];
114202834360SBarry Smith       for ( k=kstart; k<kend; k++ ) {
1143d8ced48eSBarry Smith         if (aj[k]+shift >= first) {
114402834360SBarry Smith           starts[i] = k;
114502834360SBarry Smith           break;
114602834360SBarry Smith 	}
114702834360SBarry Smith       }
1148a2744918SBarry Smith       sum = 0;
114902834360SBarry Smith       while (k < kend) {
1150d8ced48eSBarry Smith         if (aj[k++]+shift >= first+ncols) break;
1151a2744918SBarry Smith         sum++;
115202834360SBarry Smith       }
1153a2744918SBarry Smith       lens[i] = sum;
115402834360SBarry Smith     }
115502834360SBarry Smith     /* create submatrix */
1156cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
115708480c60SBarry Smith       int n_cols,n_rows;
115808480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols); CHKERRQ(ierr);
115908480c60SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(1,"MatGetSubMatrix_SeqAIJ:");
1160d8ced48eSBarry Smith       ierr = MatZeroEntries(*B); CHKERRQ(ierr);
116108480c60SBarry Smith       C = *B;
116208480c60SBarry Smith     }
116308480c60SBarry Smith     else {
116402834360SBarry Smith       ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr);
116508480c60SBarry Smith     }
1166db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*) C->data;
1167db02288aSLois Curfman McInnes 
116802834360SBarry Smith     /* loop over rows inserting into submatrix */
1169db02288aSLois Curfman McInnes     a_new    = c->a;
1170db02288aSLois Curfman McInnes     j_new    = c->j;
1171db02288aSLois Curfman McInnes     i_new    = c->i;
1172db02288aSLois Curfman McInnes     i_new[0] = -shift;
117302834360SBarry Smith     for (i=0; i<nrows; i++) {
1174a2744918SBarry Smith       ii    = starts[i];
1175a2744918SBarry Smith       lensi = lens[i];
1176a2744918SBarry Smith       for ( k=0; k<lensi; k++ ) {
1177a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
117802834360SBarry Smith       }
1179a2744918SBarry Smith       PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(Scalar));
1180a2744918SBarry Smith       a_new      += lensi;
1181a2744918SBarry Smith       i_new[i+1]  = i_new[i] + lensi;
1182a2744918SBarry Smith       c->ilen[i]  = lensi;
118302834360SBarry Smith     }
11840452661fSBarry Smith     PetscFree(lens);
118502834360SBarry Smith   }
118602834360SBarry Smith   else {
118702834360SBarry Smith     ierr = ISGetIndices(iscol,&icol); CHKERRQ(ierr);
11880452661fSBarry Smith     smap  = (int *) PetscMalloc((1+oldcols)*sizeof(int)); CHKPTRQ(smap);
118902834360SBarry Smith     ssmap = smap + shift;
119099141d43SSatish Balay     lens  = (int *) PetscMalloc((1+nrows)*sizeof(int)); CHKPTRQ(lens);
1191cddf8d76SBarry Smith     PetscMemzero(smap,oldcols*sizeof(int));
119217ab2063SBarry Smith     for ( i=0; i<ncols; i++ ) smap[icol[i]] = i+1;
119302834360SBarry Smith     /* determine lens of each row */
119402834360SBarry Smith     for (i=0; i<nrows; i++) {
1195d8ced48eSBarry Smith       kstart  = ai[irow[i]]+shift;
119602834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
119702834360SBarry Smith       lens[i] = 0;
119802834360SBarry Smith       for ( k=kstart; k<kend; k++ ) {
1199d8ced48eSBarry Smith         if (ssmap[aj[k]]) {
120002834360SBarry Smith           lens[i]++;
120102834360SBarry Smith         }
120202834360SBarry Smith       }
120302834360SBarry Smith     }
120417ab2063SBarry Smith     /* Create and fill new matrix */
1205a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
120699141d43SSatish Balay       c = (Mat_SeqAIJ *)((*B)->data);
120799141d43SSatish Balay 
120899141d43SSatish Balay       if (c->m  != nrows || c->n != ncols) SETERRQ(1,"MatGetSubMatrix_SeqAIJ:");
120999141d43SSatish Balay       if (PetscMemcmp(c->ilen,lens, c->m *sizeof(int))) {
121099141d43SSatish Balay         SETERRQ(1,"MatGetSubmatrices_SeqAIJ:Cannot reuse matrix. wrong no of nonzeros");
121199141d43SSatish Balay       }
121299141d43SSatish Balay       PetscMemzero(c->ilen,c->m*sizeof(int));
121308480c60SBarry Smith       C = *B;
121408480c60SBarry Smith     }
121508480c60SBarry Smith     else {
121602834360SBarry Smith       ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr);
121708480c60SBarry Smith     }
121899141d43SSatish Balay     c = (Mat_SeqAIJ *)(C->data);
121917ab2063SBarry Smith     for (i=0; i<nrows; i++) {
122099141d43SSatish Balay       row    = irow[i];
122117ab2063SBarry Smith       nznew  = 0;
122299141d43SSatish Balay       kstart = ai[row]+shift;
122399141d43SSatish Balay       kend   = kstart + a->ilen[row];
122499141d43SSatish Balay       mat_i  = c->i[i]+shift;
122599141d43SSatish Balay       mat_j  = c->j + mat_i;
122699141d43SSatish Balay       mat_a  = c->a + mat_i;
122799141d43SSatish Balay       mat_ilen = c->ilen + i;
122817ab2063SBarry Smith       for ( k=kstart; k<kend; k++ ) {
122999141d43SSatish Balay         if ((tcol=ssmap[a->j[k]])) {
123099141d43SSatish Balay           *mat_j++ = tcol - (!shift);
123199141d43SSatish Balay           *mat_a++ = a->a[k];
123299141d43SSatish Balay           (*mat_ilen)++;
123399141d43SSatish Balay 
123417ab2063SBarry Smith         }
123517ab2063SBarry Smith       }
123617ab2063SBarry Smith     }
123702834360SBarry Smith     /* Free work space */
123802834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol); CHKERRQ(ierr);
123999141d43SSatish Balay     PetscFree(smap); PetscFree(lens);
124002834360SBarry Smith   }
12416d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
12426d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
124317ab2063SBarry Smith 
124417ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow); CHKERRQ(ierr);
1245416022c9SBarry Smith   *B = C;
124617ab2063SBarry Smith   return 0;
124717ab2063SBarry Smith }
124817ab2063SBarry Smith 
1249a871dcd8SBarry Smith /*
125063b91edcSBarry Smith      note: This can only work for identity for row and col. It would
125163b91edcSBarry Smith    be good to check this and otherwise generate an error.
1252a871dcd8SBarry Smith */
125363b91edcSBarry Smith static int MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,double efill,int fill)
1254a871dcd8SBarry Smith {
125563b91edcSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) inA->data;
125608480c60SBarry Smith   int        ierr;
125763b91edcSBarry Smith   Mat        outA;
125863b91edcSBarry Smith 
1259a871dcd8SBarry Smith   if (fill != 0) SETERRQ(1,"MatILUFactor_SeqAIJ:Only fill=0 supported");
1260a871dcd8SBarry Smith 
126163b91edcSBarry Smith   outA          = inA;
126263b91edcSBarry Smith   inA->factor   = FACTOR_LU;
126363b91edcSBarry Smith   a->row        = row;
126463b91edcSBarry Smith   a->col        = col;
126563b91edcSBarry Smith 
12660452661fSBarry Smith   a->solve_work = (Scalar *) PetscMalloc( (a->m+1)*sizeof(Scalar)); CHKPTRQ(a->solve_work);
126763b91edcSBarry Smith 
126808480c60SBarry Smith   if (!a->diag) {
126908480c60SBarry Smith     ierr = MatMarkDiag_SeqAIJ(inA); CHKERRQ(ierr);
127063b91edcSBarry Smith   }
127163b91edcSBarry Smith   ierr = MatLUFactorNumeric_SeqAIJ(inA,&outA); CHKERRQ(ierr);
1272a871dcd8SBarry Smith   return 0;
1273a871dcd8SBarry Smith }
1274a871dcd8SBarry Smith 
1275f0b747eeSBarry Smith #include "pinclude/plapack.h"
1276f0b747eeSBarry Smith static int MatScale_SeqAIJ(Scalar *alpha,Mat inA)
1277f0b747eeSBarry Smith {
1278f0b747eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) inA->data;
1279f0b747eeSBarry Smith   int        one = 1;
1280f0b747eeSBarry Smith   BLscal_( &a->nz, alpha, a->a, &one );
1281f0b747eeSBarry Smith   PLogFlops(a->nz);
1282f0b747eeSBarry Smith   return 0;
1283f0b747eeSBarry Smith }
1284f0b747eeSBarry Smith 
1285cddf8d76SBarry Smith static int MatGetSubMatrices_SeqAIJ(Mat A,int n, IS *irow,IS *icol,MatGetSubMatrixCall scall,
1286cddf8d76SBarry Smith                                     Mat **B)
1287cddf8d76SBarry Smith {
1288cddf8d76SBarry Smith   int ierr,i;
1289cddf8d76SBarry Smith 
1290cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
12910452661fSBarry Smith     *B = (Mat *) PetscMalloc( (n+1)*sizeof(Mat) ); CHKPTRQ(*B);
1292cddf8d76SBarry Smith   }
1293cddf8d76SBarry Smith 
1294cddf8d76SBarry Smith   for ( i=0; i<n; i++ ) {
1295905e6a2fSBarry Smith     ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],scall,&(*B)[i]);CHKERRQ(ierr);
1296cddf8d76SBarry Smith   }
1297cddf8d76SBarry Smith   return 0;
1298cddf8d76SBarry Smith }
1299cddf8d76SBarry Smith 
13005a838052SSatish Balay static int MatGetBlockSize_SeqAIJ(Mat A, int *bs)
13015a838052SSatish Balay {
13025a838052SSatish Balay   *bs = 1;
13035a838052SSatish Balay   return 0;
13045a838052SSatish Balay }
13055a838052SSatish Balay 
1306e4d965acSSatish Balay static int MatIncreaseOverlap_SeqAIJ(Mat A, int is_max, IS *is, int ov)
13074dcbc457SBarry Smith {
1308e4d965acSSatish Balay   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
130906763907SSatish Balay   int        shift, row, i,j,k,l,m,n, *idx,ierr, *nidx, isz, val;
13108a047759SSatish Balay   int        start, end, *ai, *aj;
131106763907SSatish Balay   char       *table;
13128a047759SSatish Balay   shift = a->indexshift;
1313e4d965acSSatish Balay   m     = a->m;
1314e4d965acSSatish Balay   ai    = a->i;
13158a047759SSatish Balay   aj    = a->j+shift;
13168a047759SSatish Balay 
1317e4d965acSSatish Balay   if (ov < 0)  SETERRQ(1,"MatIncreaseOverlap_SeqAIJ: illegal overlap value used");
131806763907SSatish Balay 
131906763907SSatish Balay   table = (char *) PetscMalloc((m/BITSPERBYTE +1)*sizeof(char)); CHKPTRQ(table);
132006763907SSatish Balay   nidx  = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(nidx);
132106763907SSatish Balay 
1322e4d965acSSatish Balay   for ( i=0; i<is_max; i++ ) {
1323e4d965acSSatish Balay     /* Initialise the two local arrays */
1324e4d965acSSatish Balay     isz  = 0;
132506763907SSatish Balay     PetscMemzero(table,(m/BITSPERBYTE +1)*sizeof(char));
1326e4d965acSSatish Balay 
1327e4d965acSSatish Balay                 /* Extract the indices, assume there can be duplicate entries */
13284dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);  CHKERRQ(ierr);
132977c4ece6SBarry Smith     ierr = ISGetSize(is[i],&n);  CHKERRQ(ierr);
1330e4d965acSSatish Balay 
1331e4d965acSSatish Balay     /* Enter these into the temp arrays i.e mark table[row], enter row into new index */
1332e4d965acSSatish Balay     for ( j=0; j<n ; ++j){
133306763907SSatish Balay       if(!BT_LOOKUP(table, idx[j])) { nidx[isz++] = idx[j];}
13344dcbc457SBarry Smith     }
133506763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);  CHKERRQ(ierr);
133606763907SSatish Balay     ierr = ISDestroy(is[i]); CHKERRQ(ierr);
1337e4d965acSSatish Balay 
133804a348a9SBarry Smith     k = 0;
133904a348a9SBarry Smith     for ( j=0; j<ov; j++){ /* for each overlap*/
134004a348a9SBarry Smith       n = isz;
134106763907SSatish Balay       for ( ; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
1342e4d965acSSatish Balay         row   = nidx[k];
1343e4d965acSSatish Balay         start = ai[row];
1344e4d965acSSatish Balay         end   = ai[row+1];
134504a348a9SBarry Smith         for ( l = start; l<end ; l++){
13468a047759SSatish Balay           val = aj[l] + shift;
134706763907SSatish Balay           if (!BT_LOOKUP(table,val)) {nidx[isz++] = val;}
1348e4d965acSSatish Balay         }
1349e4d965acSSatish Balay       }
1350e4d965acSSatish Balay     }
1351537820f0SBarry Smith     ierr = ISCreateGeneral(MPI_COMM_SELF, isz, nidx, (is+i)); CHKERRQ(ierr);
1352e4d965acSSatish Balay   }
135304a348a9SBarry Smith   PetscFree(table);
135406763907SSatish Balay   PetscFree(nidx);
1355e4d965acSSatish Balay   return 0;
13564dcbc457SBarry Smith }
135717ab2063SBarry Smith 
1358682d7d0cSBarry Smith int MatPrintHelp_SeqAIJ(Mat A)
1359682d7d0cSBarry Smith {
1360682d7d0cSBarry Smith   static int called = 0;
1361682d7d0cSBarry Smith   MPI_Comm   comm = A->comm;
1362682d7d0cSBarry Smith 
1363682d7d0cSBarry Smith   if (called) return 0; else called = 1;
136477c4ece6SBarry Smith   PetscPrintf(comm," Options for MATSEQAIJ and MATMPIAIJ matrix formats (the defaults):\n");
136577c4ece6SBarry Smith   PetscPrintf(comm,"  -mat_lu_pivotthreshold <threshold>\n");
136677c4ece6SBarry Smith   PetscPrintf(comm,"  -mat_aij_oneindex - internal indices begin at 1 instead of the default 0.\n");
136777c4ece6SBarry Smith   PetscPrintf(comm,"  -mat_aij_no_inode  - Do not use inodes\n");
136877c4ece6SBarry Smith   PetscPrintf(comm,"  -mat_aij_inode_limit <limit> - Set inode limit (max limit=5)\n");
1369682d7d0cSBarry Smith #if defined(HAVE_ESSL)
137077c4ece6SBarry Smith   PetscPrintf(comm,"  -mat_aij_essl  - Use IBM sparse LU factorization and solve.\n");
1371682d7d0cSBarry Smith #endif
1372682d7d0cSBarry Smith   return 0;
1373682d7d0cSBarry Smith }
1374205e38a3SBarry Smith static int MatEqual_SeqAIJ(Mat A,Mat B, PetscTruth* flg);
1375*a93ec695SBarry Smith extern int MatFDColoringCreate_SeqAIJ(Mat,ISColoring,MatFDColoring);
1376*a93ec695SBarry Smith extern int MatColoringPatch_SeqAIJ(Mat,int,int *,ISColoring *);
1377*a93ec695SBarry Smith 
1378682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
137917ab2063SBarry Smith static struct _MatOps MatOps = {MatSetValues_SeqAIJ,
138017ab2063SBarry Smith        MatGetRow_SeqAIJ,MatRestoreRow_SeqAIJ,
1381416022c9SBarry Smith        MatMult_SeqAIJ,MatMultAdd_SeqAIJ,
1382416022c9SBarry Smith        MatMultTrans_SeqAIJ,MatMultTransAdd_SeqAIJ,
138317ab2063SBarry Smith        MatSolve_SeqAIJ,MatSolveAdd_SeqAIJ,
138417ab2063SBarry Smith        MatSolveTrans_SeqAIJ,MatSolveTransAdd_SeqAIJ,
138517ab2063SBarry Smith        MatLUFactor_SeqAIJ,0,
138617ab2063SBarry Smith        MatRelax_SeqAIJ,
138717ab2063SBarry Smith        MatTranspose_SeqAIJ,
13887264ac53SSatish Balay        MatGetInfo_SeqAIJ,MatEqual_SeqAIJ,
1389f0b747eeSBarry Smith        MatGetDiagonal_SeqAIJ,MatDiagonalScale_SeqAIJ,MatNorm_SeqAIJ,
139017ab2063SBarry Smith        0,MatAssemblyEnd_SeqAIJ,
139117ab2063SBarry Smith        MatCompress_SeqAIJ,
139217ab2063SBarry Smith        MatSetOption_SeqAIJ,MatZeroEntries_SeqAIJ,MatZeroRows_SeqAIJ,
139317ab2063SBarry Smith        MatLUFactorSymbolic_SeqAIJ,MatLUFactorNumeric_SeqAIJ,0,0,
139417ab2063SBarry Smith        MatGetSize_SeqAIJ,MatGetSize_SeqAIJ,MatGetOwnershipRange_SeqAIJ,
139517ab2063SBarry Smith        MatILUFactorSymbolic_SeqAIJ,0,
139617ab2063SBarry Smith        0,0,MatConvert_SeqAIJ,
13973d1612f7SBarry Smith        MatConvertSameType_SeqAIJ,0,0,
1398cddf8d76SBarry Smith        MatILUFactor_SeqAIJ,0,0,
13997eb43aa7SLois Curfman McInnes        MatGetSubMatrices_SeqAIJ,MatIncreaseOverlap_SeqAIJ,
1400682d7d0cSBarry Smith        MatGetValues_SeqAIJ,0,
1401f0b747eeSBarry Smith        MatPrintHelp_SeqAIJ,
14025a838052SSatish Balay        MatScale_SeqAIJ,0,0,
14036945ee14SBarry Smith        MatILUDTFactor_SeqAIJ,
14046945ee14SBarry Smith        MatGetBlockSize_SeqAIJ,
14053b2fbd54SBarry Smith        MatGetRowIJ_SeqAIJ,
14063b2fbd54SBarry Smith        MatRestoreRowIJ_SeqAIJ,
14073b2fbd54SBarry Smith        MatGetColumnIJ_SeqAIJ,
1408*a93ec695SBarry Smith        MatRestoreColumnIJ_SeqAIJ,
1409*a93ec695SBarry Smith        MatFDColoringCreate_SeqAIJ,
1410*a93ec695SBarry Smith        MatColoringPatch_SeqAIJ};
141117ab2063SBarry Smith 
141217ab2063SBarry Smith extern int MatUseSuperLU_SeqAIJ(Mat);
141317ab2063SBarry Smith extern int MatUseEssl_SeqAIJ(Mat);
141417ab2063SBarry Smith extern int MatUseDXML_SeqAIJ(Mat);
141517ab2063SBarry Smith 
141617ab2063SBarry Smith /*@C
1417682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
14180d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
14196e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
14202bd5e0b2SLois Curfman McInnes    (or the array nzz).  By setting these parameters accurately, performance
14212bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
142217ab2063SBarry Smith 
142317ab2063SBarry Smith    Input Parameters:
142417ab2063SBarry Smith .  comm - MPI communicator, set to MPI_COMM_SELF
142517ab2063SBarry Smith .  m - number of rows
142617ab2063SBarry Smith .  n - number of columns
142717ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
14282bd5e0b2SLois Curfman McInnes .  nzz - array containing the number of nonzeros in the various rows
14292bd5e0b2SLois Curfman McInnes          (possibly different for each row) or PETSC_NULL
143017ab2063SBarry Smith 
143117ab2063SBarry Smith    Output Parameter:
1432416022c9SBarry Smith .  A - the matrix
143317ab2063SBarry Smith 
143417ab2063SBarry Smith    Notes:
143517ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
143617ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
14370002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
143844cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
143917ab2063SBarry Smith 
144017ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
1441a40aa06bSLois Curfman McInnes    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
14423d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
14433d323bbdSBarry Smith    will get TERRIBLE performance, see the users' manual chapter on
14440d15e28bSLois Curfman McInnes    matrices and the file $(PETSC_DIR)/Performance.
144517ab2063SBarry Smith 
1446682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
1447682d7d0cSBarry Smith    improve numerical efficiency of Matrix vector products and solves. We
1448682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
14496c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
14506c7ebb05SLois Curfman McInnes 
14516c7ebb05SLois Curfman McInnes    Options Database Keys:
14526c7ebb05SLois Curfman McInnes $    -mat_aij_no_inode  - Do not use inodes
14536e62573dSLois Curfman McInnes $    -mat_aij_inode_limit <limit> - Set inode limit.
14546e62573dSLois Curfman McInnes $        (max limit=5)
14556e62573dSLois Curfman McInnes $    -mat_aij_oneindex - Internally use indexing starting at 1
14566e62573dSLois Curfman McInnes $        rather than 0.  Note: When calling MatSetValues(),
14576e62573dSLois Curfman McInnes $        the user still MUST index entries starting at 0!
145817ab2063SBarry Smith 
145917ab2063SBarry Smith .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues()
146017ab2063SBarry Smith @*/
1461416022c9SBarry Smith int MatCreateSeqAIJ(MPI_Comm comm,int m,int n,int nz,int *nnz, Mat *A)
146217ab2063SBarry Smith {
1463416022c9SBarry Smith   Mat        B;
1464416022c9SBarry Smith   Mat_SeqAIJ *b;
14656945ee14SBarry Smith   int        i, len, ierr, flg,size;
14666945ee14SBarry Smith 
14676945ee14SBarry Smith   MPI_Comm_size(comm,&size);
14686945ee14SBarry Smith   if (size > 1) SETERRQ(1,"MatCreateSeqAIJ:Comm must be of size 1");
1469d5d45c9bSBarry Smith 
1470416022c9SBarry Smith   *A                  = 0;
14710452661fSBarry Smith   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSEQAIJ,comm);
1472416022c9SBarry Smith   PLogObjectCreate(B);
14730452661fSBarry Smith   B->data             = (void *) (b = PetscNew(Mat_SeqAIJ)); CHKPTRQ(b);
147444cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_SeqAIJ));
1475416022c9SBarry Smith   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
1476416022c9SBarry Smith   B->destroy          = MatDestroy_SeqAIJ;
1477416022c9SBarry Smith   B->view             = MatView_SeqAIJ;
1478416022c9SBarry Smith   B->factor           = 0;
1479416022c9SBarry Smith   B->lupivotthreshold = 1.0;
14807a743949SBarry Smith   ierr = OptionsGetDouble(PETSC_NULL,"-mat_lu_pivotthreshold",&B->lupivotthreshold,
148169957df2SSatish Balay                           &flg); CHKERRQ(ierr);
14827a743949SBarry Smith   b->ilu_preserve_row_sums = PETSC_FALSE;
14837a743949SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-pc_ilu_preserve_row_sums",
14847a743949SBarry Smith                         (int*) &b->ilu_preserve_row_sums); CHKERRQ(ierr);
1485416022c9SBarry Smith   b->row              = 0;
1486416022c9SBarry Smith   b->col              = 0;
1487416022c9SBarry Smith   b->indexshift       = 0;
1488b810aeb4SBarry Smith   b->reallocs         = 0;
148969957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_oneindex", &flg); CHKERRQ(ierr);
149069957df2SSatish Balay   if (flg) b->indexshift = -1;
149117ab2063SBarry Smith 
149244cd7ae7SLois Curfman McInnes   b->m = m; B->m = m; B->M = m;
149344cd7ae7SLois Curfman McInnes   b->n = n; B->n = n; B->N = n;
14940452661fSBarry Smith   b->imax = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(b->imax);
1495b4fd4287SBarry Smith   if (nnz == PETSC_NULL) {
14967b8455f0SLois Curfman McInnes     if (nz == PETSC_DEFAULT) nz = 10;
14977b8455f0SLois Curfman McInnes     else if (nz <= 0)        nz = 1;
1498416022c9SBarry Smith     for ( i=0; i<m; i++ ) b->imax[i] = nz;
149917ab2063SBarry Smith     nz = nz*m;
150017ab2063SBarry Smith   }
150117ab2063SBarry Smith   else {
150217ab2063SBarry Smith     nz = 0;
1503416022c9SBarry Smith     for ( i=0; i<m; i++ ) {b->imax[i] = nnz[i]; nz += nnz[i];}
150417ab2063SBarry Smith   }
150517ab2063SBarry Smith 
150617ab2063SBarry Smith   /* allocate the matrix space */
1507416022c9SBarry Smith   len     = nz*(sizeof(int) + sizeof(Scalar)) + (b->m+1)*sizeof(int);
15080452661fSBarry Smith   b->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(b->a);
1509416022c9SBarry Smith   b->j  = (int *) (b->a + nz);
1510cddf8d76SBarry Smith   PetscMemzero(b->j,nz*sizeof(int));
1511416022c9SBarry Smith   b->i  = b->j + nz;
1512416022c9SBarry Smith   b->singlemalloc = 1;
151317ab2063SBarry Smith 
1514416022c9SBarry Smith   b->i[0] = -b->indexshift;
151517ab2063SBarry Smith   for (i=1; i<m+1; i++) {
1516416022c9SBarry Smith     b->i[i] = b->i[i-1] + b->imax[i-1];
151717ab2063SBarry Smith   }
151817ab2063SBarry Smith 
1519416022c9SBarry Smith   /* b->ilen will count nonzeros in each row so far. */
15200452661fSBarry Smith   b->ilen = (int *) PetscMalloc((m+1)*sizeof(int));
1521416022c9SBarry Smith   PLogObjectMemory(B,len+2*(m+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqAIJ));
1522416022c9SBarry Smith   for ( i=0; i<b->m; i++ ) { b->ilen[i] = 0;}
152317ab2063SBarry Smith 
1524416022c9SBarry Smith   b->nz               = 0;
1525416022c9SBarry Smith   b->maxnz            = nz;
1526416022c9SBarry Smith   b->sorted           = 0;
1527416022c9SBarry Smith   b->roworiented      = 1;
1528416022c9SBarry Smith   b->nonew            = 0;
1529416022c9SBarry Smith   b->diag             = 0;
1530416022c9SBarry Smith   b->solve_work       = 0;
153171bd300dSLois Curfman McInnes   b->spptr            = 0;
1532754ec7b1SSatish Balay   b->inode.node_count = 0;
1533754ec7b1SSatish Balay   b->inode.size       = 0;
15346c7ebb05SLois Curfman McInnes   b->inode.limit      = 5;
15356c7ebb05SLois Curfman McInnes   b->inode.max_limit  = 5;
15364e220ebcSLois Curfman McInnes   B->info.nz_unneeded = (double)b->maxnz;
153717ab2063SBarry Smith 
1538416022c9SBarry Smith   *A = B;
15394e220ebcSLois Curfman McInnes 
15404b14c69eSBarry Smith   /*  SuperLU is not currently supported through PETSc */
15414b14c69eSBarry Smith #if defined(HAVE_SUPERLU)
154269957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_superlu", &flg); CHKERRQ(ierr);
154369957df2SSatish Balay   if (flg) { ierr = MatUseSuperLU_SeqAIJ(B); CHKERRQ(ierr); }
15444b14c69eSBarry Smith #endif
154569957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_essl", &flg); CHKERRQ(ierr);
154669957df2SSatish Balay   if (flg) { ierr = MatUseEssl_SeqAIJ(B); CHKERRQ(ierr); }
154769957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_dxml", &flg); CHKERRQ(ierr);
154869957df2SSatish Balay   if (flg) {
1549416022c9SBarry Smith     if (!b->indexshift) SETERRQ(1,"MatCreateSeqAIJ:need -mat_aij_oneindex with -mat_aij_dxml");
1550416022c9SBarry Smith     ierr = MatUseDXML_SeqAIJ(B); CHKERRQ(ierr);
155117ab2063SBarry Smith   }
155269957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-help", &flg); CHKERRQ(ierr);
155369957df2SSatish Balay   if (flg) {ierr = MatPrintHelp(B); CHKERRQ(ierr); }
155417ab2063SBarry Smith   return 0;
155517ab2063SBarry Smith }
155617ab2063SBarry Smith 
15573d1612f7SBarry Smith int MatConvertSameType_SeqAIJ(Mat A,Mat *B,int cpvalues)
155817ab2063SBarry Smith {
1559416022c9SBarry Smith   Mat        C;
1560416022c9SBarry Smith   Mat_SeqAIJ *c,*a = (Mat_SeqAIJ *) A->data;
156108480c60SBarry Smith   int        i,len, m = a->m,shift = a->indexshift;
156217ab2063SBarry Smith 
15634043dd9cSLois Curfman McInnes   *B = 0;
15640452661fSBarry Smith   PetscHeaderCreate(C,_Mat,MAT_COOKIE,MATSEQAIJ,A->comm);
1565416022c9SBarry Smith   PLogObjectCreate(C);
15660452661fSBarry Smith   C->data       = (void *) (c = PetscNew(Mat_SeqAIJ)); CHKPTRQ(c);
156741c01911SSatish Balay   PetscMemcpy(&C->ops,&A->ops,sizeof(struct _MatOps));
1568416022c9SBarry Smith   C->destroy    = MatDestroy_SeqAIJ;
1569416022c9SBarry Smith   C->view       = MatView_SeqAIJ;
1570416022c9SBarry Smith   C->factor     = A->factor;
1571416022c9SBarry Smith   c->row        = 0;
1572416022c9SBarry Smith   c->col        = 0;
1573416022c9SBarry Smith   c->indexshift = shift;
1574c456f294SBarry Smith   C->assembled  = PETSC_TRUE;
157517ab2063SBarry Smith 
157644cd7ae7SLois Curfman McInnes   c->m = C->m   = a->m;
157744cd7ae7SLois Curfman McInnes   c->n = C->n   = a->n;
157844cd7ae7SLois Curfman McInnes   C->M          = a->m;
157944cd7ae7SLois Curfman McInnes   C->N          = a->n;
158017ab2063SBarry Smith 
15810452661fSBarry Smith   c->imax       = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(c->imax);
15820452661fSBarry Smith   c->ilen       = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(c->ilen);
158317ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
1584416022c9SBarry Smith     c->imax[i] = a->imax[i];
1585416022c9SBarry Smith     c->ilen[i] = a->ilen[i];
158617ab2063SBarry Smith   }
158717ab2063SBarry Smith 
158817ab2063SBarry Smith   /* allocate the matrix space */
1589416022c9SBarry Smith   c->singlemalloc = 1;
1590416022c9SBarry Smith   len     = (m+1)*sizeof(int)+(a->i[m])*(sizeof(Scalar)+sizeof(int));
15910452661fSBarry Smith   c->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(c->a);
1592416022c9SBarry Smith   c->j  = (int *) (c->a + a->i[m] + shift);
1593416022c9SBarry Smith   c->i  = c->j + a->i[m] + shift;
1594416022c9SBarry Smith   PetscMemcpy(c->i,a->i,(m+1)*sizeof(int));
159517ab2063SBarry Smith   if (m > 0) {
1596416022c9SBarry Smith     PetscMemcpy(c->j,a->j,(a->i[m]+shift)*sizeof(int));
159708480c60SBarry Smith     if (cpvalues == COPY_VALUES) {
1598416022c9SBarry Smith       PetscMemcpy(c->a,a->a,(a->i[m]+shift)*sizeof(Scalar));
159917ab2063SBarry Smith     }
160008480c60SBarry Smith   }
160117ab2063SBarry Smith 
1602416022c9SBarry Smith   PLogObjectMemory(C,len+2*(m+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqAIJ));
1603416022c9SBarry Smith   c->sorted      = a->sorted;
1604416022c9SBarry Smith   c->roworiented = a->roworiented;
1605416022c9SBarry Smith   c->nonew       = a->nonew;
16067a743949SBarry Smith   c->ilu_preserve_row_sums = a->ilu_preserve_row_sums;
160717ab2063SBarry Smith 
1608416022c9SBarry Smith   if (a->diag) {
16090452661fSBarry Smith     c->diag = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(c->diag);
1610416022c9SBarry Smith     PLogObjectMemory(C,(m+1)*sizeof(int));
161117ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
1612416022c9SBarry Smith       c->diag[i] = a->diag[i];
161317ab2063SBarry Smith     }
161417ab2063SBarry Smith   }
1615416022c9SBarry Smith   else c->diag          = 0;
16166c7ebb05SLois Curfman McInnes   c->inode.limit        = a->inode.limit;
16176c7ebb05SLois Curfman McInnes   c->inode.max_limit    = a->inode.max_limit;
1618754ec7b1SSatish Balay   if (a->inode.size){
1619daed632aSSatish Balay     c->inode.size       = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(c->inode.size);
1620754ec7b1SSatish Balay     c->inode.node_count = a->inode.node_count;
1621daed632aSSatish Balay     PetscMemcpy( c->inode.size, a->inode.size, (m+1)*sizeof(int));
1622754ec7b1SSatish Balay   } else {
1623754ec7b1SSatish Balay     c->inode.size       = 0;
1624754ec7b1SSatish Balay     c->inode.node_count = 0;
1625754ec7b1SSatish Balay   }
1626416022c9SBarry Smith   c->nz                 = a->nz;
1627416022c9SBarry Smith   c->maxnz              = a->maxnz;
1628416022c9SBarry Smith   c->solve_work         = 0;
162976dd722bSSatish Balay   c->spptr              = 0;      /* Dangerous -I'm throwing away a->spptr */
1630754ec7b1SSatish Balay 
1631416022c9SBarry Smith   *B = C;
163217ab2063SBarry Smith   return 0;
163317ab2063SBarry Smith }
163417ab2063SBarry Smith 
163519bcc07fSBarry Smith int MatLoad_SeqAIJ(Viewer viewer,MatType type,Mat *A)
163617ab2063SBarry Smith {
1637416022c9SBarry Smith   Mat_SeqAIJ   *a;
1638416022c9SBarry Smith   Mat          B;
163917699dbbSLois Curfman McInnes   int          i, nz, ierr, fd, header[4],size,*rowlengths = 0,M,N,shift;
1640bcd2baecSBarry Smith   MPI_Comm     comm;
164117ab2063SBarry Smith 
164219bcc07fSBarry Smith   PetscObjectGetComm((PetscObject) viewer,&comm);
164317699dbbSLois Curfman McInnes   MPI_Comm_size(comm,&size);
164417699dbbSLois Curfman McInnes   if (size > 1) SETERRQ(1,"MatLoad_SeqAIJ:view must have one processor");
164590ace30eSBarry Smith   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
164677c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,header,4,BINARY_INT); CHKERRQ(ierr);
164748d91487SBarry Smith   if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_SeqAIJ:not matrix object in file");
164817ab2063SBarry Smith   M = header[1]; N = header[2]; nz = header[3];
164917ab2063SBarry Smith 
165017ab2063SBarry Smith   /* read in row lengths */
16510452661fSBarry Smith   rowlengths = (int*) PetscMalloc( M*sizeof(int) ); CHKPTRQ(rowlengths);
165277c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,rowlengths,M,BINARY_INT); CHKERRQ(ierr);
165317ab2063SBarry Smith 
165417ab2063SBarry Smith   /* create our matrix */
1655416022c9SBarry Smith   ierr = MatCreateSeqAIJ(comm,M,N,0,rowlengths,A); CHKERRQ(ierr);
1656416022c9SBarry Smith   B = *A;
1657416022c9SBarry Smith   a = (Mat_SeqAIJ *) B->data;
1658416022c9SBarry Smith   shift = a->indexshift;
165917ab2063SBarry Smith 
166017ab2063SBarry Smith   /* read in column indices and adjust for Fortran indexing*/
166177c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,a->j,nz,BINARY_INT); CHKERRQ(ierr);
166217ab2063SBarry Smith   if (shift) {
166317ab2063SBarry Smith     for ( i=0; i<nz; i++ ) {
1664416022c9SBarry Smith       a->j[i] += 1;
166517ab2063SBarry Smith     }
166617ab2063SBarry Smith   }
166717ab2063SBarry Smith 
166817ab2063SBarry Smith   /* read in nonzero values */
166977c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,a->a,nz,BINARY_SCALAR); CHKERRQ(ierr);
167017ab2063SBarry Smith 
167117ab2063SBarry Smith   /* set matrix "i" values */
1672416022c9SBarry Smith   a->i[0] = -shift;
167317ab2063SBarry Smith   for ( i=1; i<= M; i++ ) {
1674416022c9SBarry Smith     a->i[i]      = a->i[i-1] + rowlengths[i-1];
1675416022c9SBarry Smith     a->ilen[i-1] = rowlengths[i-1];
167617ab2063SBarry Smith   }
16770452661fSBarry Smith   PetscFree(rowlengths);
167817ab2063SBarry Smith 
16796d4a8577SBarry Smith   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
16806d4a8577SBarry Smith   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
168117ab2063SBarry Smith   return 0;
168217ab2063SBarry Smith }
168317ab2063SBarry Smith 
1684686e14cbSSatish Balay static int MatEqual_SeqAIJ(Mat A,Mat B, PetscTruth* flg)
16857264ac53SSatish Balay {
16867264ac53SSatish Balay   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data, *b = (Mat_SeqAIJ *)B->data;
16877264ac53SSatish Balay 
1688bcd2baecSBarry Smith   if (B->type !=MATSEQAIJ)SETERRQ(1,"MatEqual_SeqAIJ:Matrices must be same type");
16897264ac53SSatish Balay 
16907264ac53SSatish Balay   /* If the  matrix dimensions are not equal, or no of nonzeros or shift */
16917264ac53SSatish Balay   if ((a->m != b->m ) || (a->n !=b->n) ||( a->nz != b->nz)||
1692bcd2baecSBarry Smith       (a->indexshift != b->indexshift)) {
169377c4ece6SBarry Smith     *flg = PETSC_FALSE; return 0;
1694bcd2baecSBarry Smith   }
16957264ac53SSatish Balay 
16967264ac53SSatish Balay   /* if the a->i are the same */
1697bcd2baecSBarry Smith   if (PetscMemcmp(a->i,b->i, (a->n+1)*sizeof(int))) {
169877c4ece6SBarry Smith     *flg = PETSC_FALSE; return 0;
16997264ac53SSatish Balay   }
17007264ac53SSatish Balay 
17017264ac53SSatish Balay   /* if a->j are the same */
1702bcd2baecSBarry Smith   if (PetscMemcmp(a->j, b->j, (a->nz)*sizeof(int))) {
170377c4ece6SBarry Smith     *flg = PETSC_FALSE; return 0;
1704bcd2baecSBarry Smith   }
1705bcd2baecSBarry Smith 
1706bcd2baecSBarry Smith   /* if a->a are the same */
170719bcc07fSBarry Smith   if (PetscMemcmp(a->a, b->a, (a->nz)*sizeof(Scalar))) {
170877c4ece6SBarry Smith     *flg = PETSC_FALSE; return 0;
17097264ac53SSatish Balay   }
171077c4ece6SBarry Smith   *flg = PETSC_TRUE;
17117264ac53SSatish Balay   return 0;
17127264ac53SSatish Balay 
17137264ac53SSatish Balay }
1714