xref: /petsc/src/mat/impls/aij/seq/aij.c (revision f0b747eeaae1e20e56a94ed661b13a215d6d5a72)
117ab2063SBarry Smith #ifndef lint
2*f0b747eeSBarry Smith static char vcid[] = "$Id: aij.c,v 1.134 1996/01/12 21:36:32 balay Exp bsmith $";
317ab2063SBarry Smith #endif
417ab2063SBarry Smith 
5d5d45c9bSBarry Smith /*
6d5d45c9bSBarry Smith     Defines the basic matrix operations for the AIJ (compressed row)
7d5d45c9bSBarry Smith   matrix storage format.
8d5d45c9bSBarry Smith */
917ab2063SBarry Smith #include "aij.h"
1017ab2063SBarry Smith #include "vec/vecimpl.h"
1117ab2063SBarry Smith #include "inline/spops.h"
1217ab2063SBarry Smith 
1317ab2063SBarry Smith extern int MatToSymmetricIJ_SeqAIJ(Mat_SeqAIJ*,int**,int**);
1417ab2063SBarry Smith 
15416022c9SBarry Smith static int MatGetReordering_SeqAIJ(Mat A,MatOrdering type,IS *rperm, IS *cperm)
1617ab2063SBarry Smith {
17416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
18a2744918SBarry Smith   int        ierr, *ia, *ja,n,*idx,i;
193d54f168SSatish Balay   /*Viewer     V1, V2;*/
2017ab2063SBarry Smith 
21416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatGetReordering_SeqAIJ:Not for unassembled matrix");
2217ab2063SBarry Smith 
23a2744918SBarry Smith   /*
24a2744918SBarry Smith      this is tacky: In the future when we have written special factorization
25a2744918SBarry Smith      and solve routines for the identity permutation we should use a
26a2744918SBarry Smith      stride index set instead of the general one.
27a2744918SBarry Smith   */
28a2744918SBarry Smith   if (type  == ORDER_NATURAL) {
29a2744918SBarry Smith     n = a->n;
30a2744918SBarry Smith     idx = (int *) PetscMalloc( n*sizeof(int) ); CHKPTRQ(idx);
31a2744918SBarry Smith     for ( i=0; i<n; i++ ) idx[i] = i;
32a2744918SBarry Smith     ierr = ISCreateSeq(MPI_COMM_SELF,n,idx,rperm); CHKERRQ(ierr);
33a2744918SBarry Smith     ierr = ISCreateSeq(MPI_COMM_SELF,n,idx,cperm); CHKERRQ(ierr);
34a2744918SBarry Smith     PetscFree(idx);
35a2744918SBarry Smith     ISSetPermutation(*rperm);
36a2744918SBarry Smith     ISSetPermutation(*cperm);
37a2744918SBarry Smith     ISSetIdentity(*rperm);
38a2744918SBarry Smith     ISSetIdentity(*cperm);
39a2744918SBarry Smith     return 0;
40a2744918SBarry Smith   }
41a2744918SBarry Smith 
42416022c9SBarry Smith   ierr = MatToSymmetricIJ_SeqAIJ( a, &ia, &ja ); CHKERRQ(ierr);
43416022c9SBarry Smith   ierr = MatGetReordering_IJ(a->n,ia,ja,type,rperm,cperm); CHKERRQ(ierr);
4444f6d32bSSatish Balay /*  ISView(*rperm, STDOUT_VIEWER_SELF);*/
45f31bba2fSSatish Balay 
463d54f168SSatish Balay   /*ViewerFileOpenASCII(MPI_COMM_SELF,"row_is_orig", &V1);
47f31bba2fSSatish Balay   ViewerFileOpenASCII(MPI_COMM_SELF,"col_is_orig", &V2);
48f31bba2fSSatish Balay   ISView(*rperm,V1);
49f31bba2fSSatish Balay   ISView(*cperm,V2);
50f31bba2fSSatish Balay   ViewerDestroy(V1);
513d54f168SSatish Balay   ViewerDestroy(V2);*/
52f31bba2fSSatish Balay 
530452661fSBarry Smith   PetscFree(ia); PetscFree(ja);
5417ab2063SBarry Smith   return 0;
5517ab2063SBarry Smith }
5617ab2063SBarry Smith 
57416022c9SBarry Smith #define CHUNKSIZE   10
5817ab2063SBarry Smith 
5917ab2063SBarry Smith /* This version has row oriented v  */
60416022c9SBarry Smith static int MatSetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is)
6117ab2063SBarry Smith {
62416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
63416022c9SBarry Smith   int        *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax, N, sorted = a->sorted;
644b0e389bSBarry Smith   int        *imax = a->imax, *ai = a->i, *ailen = a->ilen,roworiented = a->roworiented;
65d5d45c9bSBarry Smith   int        *aj = a->j, nonew = a->nonew,shift = a->indexshift;
66416022c9SBarry Smith   Scalar     *ap,value, *aa = a->a;
6717ab2063SBarry Smith 
6817ab2063SBarry Smith   for ( k=0; k<m; k++ ) { /* loop over added rows */
69416022c9SBarry Smith     row  = im[k];
7017ab2063SBarry Smith     if (row < 0) SETERRQ(1,"MatSetValues_SeqAIJ:Negative row");
71416022c9SBarry Smith     if (row >= a->m) SETERRQ(1,"MatSetValues_SeqAIJ:Row too large");
7217ab2063SBarry Smith     rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
7317ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
74416022c9SBarry Smith     low = 0;
7517ab2063SBarry Smith     for ( l=0; l<n; l++ ) { /* loop over added columns */
76416022c9SBarry Smith       if (in[l] < 0) SETERRQ(1,"MatSetValues_SeqAIJ:Negative column");
77416022c9SBarry Smith       if (in[l] >= a->n) SETERRQ(1,"MatSetValues_SeqAIJ:Column too large");
784b0e389bSBarry Smith       col = in[l] - shift;
794b0e389bSBarry Smith       if (roworiented) {
804b0e389bSBarry Smith         value = *v++;
814b0e389bSBarry Smith       }
824b0e389bSBarry Smith       else {
834b0e389bSBarry Smith         value = v[k + l*m];
844b0e389bSBarry Smith       }
85416022c9SBarry Smith       if (!sorted) low = 0; high = nrow;
86416022c9SBarry Smith       while (high-low > 5) {
87416022c9SBarry Smith         t = (low+high)/2;
88416022c9SBarry Smith         if (rp[t] > col) high = t;
89416022c9SBarry Smith         else             low  = t;
9017ab2063SBarry Smith       }
91416022c9SBarry Smith       for ( i=low; i<high; i++ ) {
9217ab2063SBarry Smith         if (rp[i] > col) break;
9317ab2063SBarry Smith         if (rp[i] == col) {
94416022c9SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
9517ab2063SBarry Smith           else                  ap[i] = value;
9617ab2063SBarry Smith           goto noinsert;
9717ab2063SBarry Smith         }
9817ab2063SBarry Smith       }
9917ab2063SBarry Smith       if (nonew) goto noinsert;
10017ab2063SBarry Smith       if (nrow >= rmax) {
10117ab2063SBarry Smith         /* there is no extra room in row, therefore enlarge */
102416022c9SBarry Smith         int    new_nz = ai[a->m] + CHUNKSIZE,len,*new_i,*new_j;
10317ab2063SBarry Smith         Scalar *new_a;
10417ab2063SBarry Smith 
10517ab2063SBarry Smith         /* malloc new storage space */
106416022c9SBarry Smith         len     = new_nz*(sizeof(int)+sizeof(Scalar))+(a->m+1)*sizeof(int);
1070452661fSBarry Smith         new_a   = (Scalar *) PetscMalloc( len ); CHKPTRQ(new_a);
10817ab2063SBarry Smith         new_j   = (int *) (new_a + new_nz);
10917ab2063SBarry Smith         new_i   = new_j + new_nz;
11017ab2063SBarry Smith 
11117ab2063SBarry Smith         /* copy over old data into new slots */
11217ab2063SBarry Smith         for ( ii=0; ii<row+1; ii++ ) {new_i[ii] = ai[ii];}
113416022c9SBarry Smith         for ( ii=row+1; ii<a->m+1; ii++ ) {new_i[ii] = ai[ii]+CHUNKSIZE;}
114416022c9SBarry Smith         PetscMemcpy(new_j,aj,(ai[row]+nrow+shift)*sizeof(int));
115416022c9SBarry Smith         len = (new_nz - CHUNKSIZE - ai[row] - nrow - shift);
116416022c9SBarry Smith         PetscMemcpy(new_j+ai[row]+shift+nrow+CHUNKSIZE,aj+ai[row]+shift+nrow,
11717ab2063SBarry Smith                                                            len*sizeof(int));
118416022c9SBarry Smith         PetscMemcpy(new_a,aa,(ai[row]+nrow+shift)*sizeof(Scalar));
119416022c9SBarry Smith         PetscMemcpy(new_a+ai[row]+shift+nrow+CHUNKSIZE,aa+ai[row]+shift+nrow,
12017ab2063SBarry Smith                                                            len*sizeof(Scalar));
12117ab2063SBarry Smith         /* free up old matrix storage */
1220452661fSBarry Smith         PetscFree(a->a);
1230452661fSBarry Smith         if (!a->singlemalloc) {PetscFree(a->i);PetscFree(a->j);}
124416022c9SBarry Smith         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
125416022c9SBarry Smith         a->singlemalloc = 1;
12617ab2063SBarry Smith 
12717ab2063SBarry Smith         rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
128416022c9SBarry Smith         rmax = imax[row] = imax[row] + CHUNKSIZE;
129416022c9SBarry Smith         PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + sizeof(Scalar)));
130416022c9SBarry Smith         a->maxnz += CHUNKSIZE;
13117ab2063SBarry Smith       }
132416022c9SBarry Smith       N = nrow++ - 1; a->nz++;
133416022c9SBarry Smith       /* shift up all the later entries in this row */
134416022c9SBarry Smith       for ( ii=N; ii>=i; ii-- ) {
13517ab2063SBarry Smith         rp[ii+1] = rp[ii];
13617ab2063SBarry Smith         ap[ii+1] = ap[ii];
13717ab2063SBarry Smith       }
13817ab2063SBarry Smith       rp[i] = col;
13917ab2063SBarry Smith       ap[i] = value;
14017ab2063SBarry Smith       noinsert:;
141416022c9SBarry Smith       low = i + 1;
14217ab2063SBarry Smith     }
14317ab2063SBarry Smith     ailen[row] = nrow;
14417ab2063SBarry Smith   }
14517ab2063SBarry Smith   return 0;
14617ab2063SBarry Smith }
14717ab2063SBarry Smith 
1487eb43aa7SLois Curfman McInnes static int MatGetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v)
1497eb43aa7SLois Curfman McInnes {
1507eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
151b49de8d1SLois Curfman McInnes   int        *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
1527eb43aa7SLois Curfman McInnes   int        *ai = a->i, *ailen = a->ilen, shift = a->indexshift;
1537eb43aa7SLois Curfman McInnes   Scalar     *ap, *aa = a->a, zero = 0.0;
1547eb43aa7SLois Curfman McInnes 
1557eb43aa7SLois Curfman McInnes   if (!a->assembled) SETERRQ(1,"MatGetValues_SeqAIJ:Not for unassembled matrix");
1567eb43aa7SLois Curfman McInnes   for ( k=0; k<m; k++ ) { /* loop over rows */
1577eb43aa7SLois Curfman McInnes     row  = im[k];
1587eb43aa7SLois Curfman McInnes     if (row < 0) SETERRQ(1,"MatGetValues_SeqAIJ:Negative row");
1597eb43aa7SLois Curfman McInnes     if (row >= a->m) SETERRQ(1,"MatGetValues_SeqAIJ:Row too large");
1607eb43aa7SLois Curfman McInnes     rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
1617eb43aa7SLois Curfman McInnes     nrow = ailen[row];
1627eb43aa7SLois Curfman McInnes     for ( l=0; l<n; l++ ) { /* loop over columns */
1637eb43aa7SLois Curfman McInnes       if (in[l] < 0) SETERRQ(1,"MatGetValues_SeqAIJ:Negative column");
1647eb43aa7SLois Curfman McInnes       if (in[l] >= a->n) SETERRQ(1,"MatGetValues_SeqAIJ:Column too large");
1657eb43aa7SLois Curfman McInnes       col = in[l] - shift;
1667eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
1677eb43aa7SLois Curfman McInnes       while (high-low > 5) {
1687eb43aa7SLois Curfman McInnes         t = (low+high)/2;
1697eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
1707eb43aa7SLois Curfman McInnes         else             low  = t;
1717eb43aa7SLois Curfman McInnes       }
1727eb43aa7SLois Curfman McInnes       for ( i=low; i<high; i++ ) {
1737eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
1747eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
175b49de8d1SLois Curfman McInnes           *v++ = ap[i];
1767eb43aa7SLois Curfman McInnes           goto finished;
1777eb43aa7SLois Curfman McInnes         }
1787eb43aa7SLois Curfman McInnes       }
179b49de8d1SLois Curfman McInnes       *v++ = zero;
1807eb43aa7SLois Curfman McInnes       finished:;
1817eb43aa7SLois Curfman McInnes     }
1827eb43aa7SLois Curfman McInnes   }
1837eb43aa7SLois Curfman McInnes   return 0;
1847eb43aa7SLois Curfman McInnes }
1857eb43aa7SLois Curfman McInnes 
18617ab2063SBarry Smith #include "draw.h"
18717ab2063SBarry Smith #include "pinclude/pviewer.h"
188416022c9SBarry Smith #include "sysio.h"
18917ab2063SBarry Smith 
190416022c9SBarry Smith static int MatView_SeqAIJ_Binary(Mat A,Viewer viewer)
19117ab2063SBarry Smith {
192416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
193416022c9SBarry Smith   int        i, fd, *col_lens, ierr;
19417ab2063SBarry Smith 
195416022c9SBarry Smith   ierr = ViewerFileGetDescriptor_Private(viewer,&fd); CHKERRQ(ierr);
1960452661fSBarry Smith   col_lens = (int *) PetscMalloc( (4+a->m)*sizeof(int) ); CHKPTRQ(col_lens);
197416022c9SBarry Smith   col_lens[0] = MAT_COOKIE;
198416022c9SBarry Smith   col_lens[1] = a->m;
199416022c9SBarry Smith   col_lens[2] = a->n;
200416022c9SBarry Smith   col_lens[3] = a->nz;
201416022c9SBarry Smith 
202416022c9SBarry Smith   /* store lengths of each row and write (including header) to file */
203416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
204416022c9SBarry Smith     col_lens[4+i] = a->i[i+1] - a->i[i];
20517ab2063SBarry Smith   }
206416022c9SBarry Smith   ierr = SYWrite(fd,col_lens,4+a->m,SYINT,1); CHKERRQ(ierr);
2070452661fSBarry Smith   PetscFree(col_lens);
208416022c9SBarry Smith 
209416022c9SBarry Smith   /* store column indices (zero start index) */
210416022c9SBarry Smith   if (a->indexshift) {
211416022c9SBarry Smith     for ( i=0; i<a->nz; i++ ) a->j[i]--;
21217ab2063SBarry Smith   }
213416022c9SBarry Smith   ierr = SYWrite(fd,a->j,a->nz,SYINT,0); CHKERRQ(ierr);
214416022c9SBarry Smith   if (a->indexshift) {
215416022c9SBarry Smith     for ( i=0; i<a->nz; i++ ) a->j[i]++;
21617ab2063SBarry Smith   }
217416022c9SBarry Smith 
218416022c9SBarry Smith   /* store nonzero values */
219416022c9SBarry Smith   ierr = SYWrite(fd,a->a,a->nz,SYSCALAR,0); CHKERRQ(ierr);
22017ab2063SBarry Smith   return 0;
22117ab2063SBarry Smith }
222416022c9SBarry Smith 
223416022c9SBarry Smith static int MatView_SeqAIJ_ASCII(Mat A,Viewer viewer)
224416022c9SBarry Smith {
225416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ *) A->data;
226416022c9SBarry Smith   int         ierr, i,j, m = a->m, shift = a->indexshift,format;
22717ab2063SBarry Smith   FILE        *fd;
22817ab2063SBarry Smith   char        *outputname;
22917ab2063SBarry Smith 
230416022c9SBarry Smith   ierr = ViewerFileGetPointer_Private(viewer,&fd); CHKERRQ(ierr);
231416022c9SBarry Smith   ierr = ViewerFileGetOutputname_Private(viewer,&outputname); CHKERRQ(ierr);
232416022c9SBarry Smith   ierr = ViewerFileGetFormat_Private(viewer,&format);
23317ab2063SBarry Smith   if (format == FILE_FORMAT_INFO) {
23408480c60SBarry Smith     /* no need to print additional information */ ;
23517ab2063SBarry Smith   }
23617ab2063SBarry Smith   else if (format == FILE_FORMAT_MATLAB) {
23717ab2063SBarry Smith     int nz, nzalloc, mem;
238416022c9SBarry Smith     MatGetInfo(A,MAT_LOCAL,&nz,&nzalloc,&mem);
239416022c9SBarry Smith     fprintf(fd,"%% Size = %d %d \n",m,a->n);
24017ab2063SBarry Smith     fprintf(fd,"%% Nonzeros = %d \n",nz);
24117ab2063SBarry Smith     fprintf(fd,"zzz = zeros(%d,3);\n",nz);
24217ab2063SBarry Smith     fprintf(fd,"zzz = [\n");
24317ab2063SBarry Smith 
24417ab2063SBarry Smith     for (i=0; i<m; i++) {
245416022c9SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
24617ab2063SBarry Smith #if defined(PETSC_COMPLEX)
247416022c9SBarry Smith         fprintf(fd,"%d %d  %18.16e  %18.16e \n",i+1,a->j[j],real(a->a[j]),
248416022c9SBarry Smith                    imag(a->a[j]));
24917ab2063SBarry Smith #else
250416022c9SBarry Smith         fprintf(fd,"%d %d  %18.16e\n", i+1, a->j[j], a->a[j]);
25117ab2063SBarry Smith #endif
25217ab2063SBarry Smith       }
25317ab2063SBarry Smith     }
25417ab2063SBarry Smith     fprintf(fd,"];\n %s = spconvert(zzz);\n",outputname);
25517ab2063SBarry Smith   }
25617ab2063SBarry Smith   else {
25717ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
25817ab2063SBarry Smith       fprintf(fd,"row %d:",i);
259416022c9SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
26017ab2063SBarry Smith #if defined(PETSC_COMPLEX)
261416022c9SBarry Smith         if (imag(a->a[j]) != 0.0) {
262416022c9SBarry Smith           fprintf(fd," %d %g + %g i",a->j[j]+shift,real(a->a[j]),imag(a->a[j]));
26317ab2063SBarry Smith         }
26417ab2063SBarry Smith         else {
265416022c9SBarry Smith           fprintf(fd," %d %g ",a->j[j]+shift,real(a->a[j]));
26617ab2063SBarry Smith         }
26717ab2063SBarry Smith #else
268416022c9SBarry Smith         fprintf(fd," %d %g ",a->j[j]+shift,a->a[j]);
26917ab2063SBarry Smith #endif
27017ab2063SBarry Smith       }
27117ab2063SBarry Smith       fprintf(fd,"\n");
27217ab2063SBarry Smith     }
27317ab2063SBarry Smith   }
27417ab2063SBarry Smith   fflush(fd);
275416022c9SBarry Smith   return 0;
276416022c9SBarry Smith }
277416022c9SBarry Smith 
278416022c9SBarry Smith static int MatView_SeqAIJ_Draw(Mat A,Viewer viewer)
279416022c9SBarry Smith {
280416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ *) A->data;
281cddf8d76SBarry Smith   int         ierr, i,j, m = a->m, shift = a->indexshift,pause,color;
282cddf8d76SBarry Smith   double      xl,yl,xr,yr,w,h,xc,yc,scale = 1.0,x_l,x_r,y_l,y_r;
283d7e8b826SBarry Smith   Draw     draw = (Draw) viewer;
284cddf8d76SBarry Smith   DrawButton  button;
285cddf8d76SBarry Smith 
286416022c9SBarry Smith   xr  = a->n; yr = a->m; h = yr/10.0; w = xr/10.0;
287416022c9SBarry Smith   xr += w;    yr += h;  xl = -w;     yl = -h;
288416022c9SBarry Smith   ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
289416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
290cddf8d76SBarry Smith   color = DRAW_BLUE;
291416022c9SBarry Smith   for ( i=0; i<m; i++ ) {
292cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
293416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
294cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
295cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
296cddf8d76SBarry Smith       if (real(a->a[j]) >=  0.) continue;
297cddf8d76SBarry Smith #else
298cddf8d76SBarry Smith       if (a->a[j] >=  0.) continue;
299cddf8d76SBarry Smith #endif
300cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
301cddf8d76SBarry Smith     }
302cddf8d76SBarry Smith   }
303cddf8d76SBarry Smith   color = DRAW_CYAN;
304cddf8d76SBarry Smith   for ( i=0; i<m; i++ ) {
305cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
306cddf8d76SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
307cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
308cddf8d76SBarry Smith       if (a->a[j] !=  0.) continue;
309cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
310cddf8d76SBarry Smith     }
311cddf8d76SBarry Smith   }
312cddf8d76SBarry Smith   color = DRAW_RED;
313cddf8d76SBarry Smith   for ( i=0; i<m; i++ ) {
314cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
315cddf8d76SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
316cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
317cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
318cddf8d76SBarry Smith       if (real(a->a[j]) <=  0.) continue;
319cddf8d76SBarry Smith #else
320cddf8d76SBarry Smith       if (a->a[j] <=  0.) continue;
321cddf8d76SBarry Smith #endif
322cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
323416022c9SBarry Smith     }
324416022c9SBarry Smith   }
325416022c9SBarry Smith   DrawFlush(draw);
326cddf8d76SBarry Smith   DrawGetPause(draw,&pause);
327cddf8d76SBarry Smith   if (pause >= 0) { PetscSleep(pause); return 0;}
328cddf8d76SBarry Smith 
329cddf8d76SBarry Smith   /* allow the matrix to zoom or shrink */
330cddf8d76SBarry Smith   ierr = DrawGetMouseButton(draw,&button,&xc,&yc,0,0);
331cddf8d76SBarry Smith   while (button != BUTTON_RIGHT) {
332cddf8d76SBarry Smith     DrawClear(draw);
333cddf8d76SBarry Smith     if (button == BUTTON_LEFT) scale = .5;
334cddf8d76SBarry Smith     else if (button == BUTTON_CENTER) scale = 2.;
335cddf8d76SBarry Smith     xl = scale*(xl + w - xc) + xc - w*scale;
336cddf8d76SBarry Smith     xr = scale*(xr - w - xc) + xc + w*scale;
337cddf8d76SBarry Smith     yl = scale*(yl + h - yc) + yc - h*scale;
338cddf8d76SBarry Smith     yr = scale*(yr - h - yc) + yc + h*scale;
339cddf8d76SBarry Smith     w *= scale; h *= scale;
340cddf8d76SBarry Smith     ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
341cddf8d76SBarry Smith     color = DRAW_BLUE;
342cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
343cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
344cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
345cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
346cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
347cddf8d76SBarry Smith         if (real(a->a[j]) >=  0.) continue;
348cddf8d76SBarry Smith #else
349cddf8d76SBarry Smith         if (a->a[j] >=  0.) continue;
350cddf8d76SBarry Smith #endif
351cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
352cddf8d76SBarry Smith       }
353cddf8d76SBarry Smith     }
354cddf8d76SBarry Smith     color = DRAW_CYAN;
355cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
356cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
357cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
358cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
359cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
360cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
361cddf8d76SBarry Smith       }
362cddf8d76SBarry Smith     }
363cddf8d76SBarry Smith     color = DRAW_RED;
364cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
365cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
366cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
367cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
368cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
369cddf8d76SBarry Smith         if (real(a->a[j]) <=  0.) continue;
370cddf8d76SBarry Smith #else
371cddf8d76SBarry Smith         if (a->a[j] <=  0.) continue;
372cddf8d76SBarry Smith #endif
373cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
374cddf8d76SBarry Smith       }
375cddf8d76SBarry Smith     }
376cddf8d76SBarry Smith     ierr = DrawGetMouseButton(draw,&button,&xc,&yc,0,0);
377cddf8d76SBarry Smith   }
378416022c9SBarry Smith   return 0;
379416022c9SBarry Smith }
380416022c9SBarry Smith 
381416022c9SBarry Smith static int MatView_SeqAIJ(PetscObject obj,Viewer viewer)
382416022c9SBarry Smith {
383416022c9SBarry Smith   Mat         A = (Mat) obj;
384416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ*) A->data;
385416022c9SBarry Smith   PetscObject vobj = (PetscObject) viewer;
386416022c9SBarry Smith 
387416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatView_SeqAIJ:Not for unassembled matrix");
388416022c9SBarry Smith   if (!viewer) {
389416022c9SBarry Smith     viewer = STDOUT_VIEWER_SELF; vobj = (PetscObject) viewer;
390416022c9SBarry Smith   }
391416022c9SBarry Smith   if (vobj->cookie == VIEWER_COOKIE) {
392416022c9SBarry Smith     if (vobj->type == MATLAB_VIEWER) {
393416022c9SBarry Smith       return ViewerMatlabPutSparse_Private(viewer,a->m,a->n,a->nz,a->a,a->i,a->j);
394416022c9SBarry Smith     }
395416022c9SBarry Smith     else if (vobj->type == ASCII_FILE_VIEWER || vobj->type == ASCII_FILES_VIEWER){
396416022c9SBarry Smith       return MatView_SeqAIJ_ASCII(A,viewer);
397416022c9SBarry Smith     }
398416022c9SBarry Smith     else if (vobj->type == BINARY_FILE_VIEWER) {
399416022c9SBarry Smith       return MatView_SeqAIJ_Binary(A,viewer);
400416022c9SBarry Smith     }
401416022c9SBarry Smith   }
402416022c9SBarry Smith   else if (vobj->cookie == DRAW_COOKIE) {
403416022c9SBarry Smith     if (vobj->type == NULLWINDOW) return 0;
404416022c9SBarry Smith     else return MatView_SeqAIJ_Draw(A,viewer);
40517ab2063SBarry Smith   }
40617ab2063SBarry Smith   return 0;
40717ab2063SBarry Smith }
40841c01911SSatish Balay int Mat_AIJ_CheckInode(Mat);
409416022c9SBarry Smith static int MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
41017ab2063SBarry Smith {
411416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
41241c01911SSatish Balay   int        fshift = 0,i,j,*ai = a->i, *aj = a->j, *imax = a->imax,ierr;
413416022c9SBarry Smith   int        m = a->m, *ip, N, *ailen = a->ilen,shift = a->indexshift;
414416022c9SBarry Smith   Scalar     *aa = a->a, *ap;
41517ab2063SBarry Smith 
41617ab2063SBarry Smith   if (mode == FLUSH_ASSEMBLY) return 0;
41717ab2063SBarry Smith 
41817ab2063SBarry Smith   for ( i=1; i<m; i++ ) {
419416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
42017ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
42117ab2063SBarry Smith     if (fshift) {
422416022c9SBarry Smith       ip = aj + ai[i] + shift; ap = aa + ai[i] + shift;
42317ab2063SBarry Smith       N = ailen[i];
42417ab2063SBarry Smith       for ( j=0; j<N; j++ ) {
42517ab2063SBarry Smith         ip[j-fshift] = ip[j];
42617ab2063SBarry Smith         ap[j-fshift] = ap[j];
42717ab2063SBarry Smith       }
42817ab2063SBarry Smith     }
42917ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
43017ab2063SBarry Smith   }
43117ab2063SBarry Smith   if (m) {
43217ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
43317ab2063SBarry Smith     ai[m] = ai[m-1] + ailen[m-1];
43417ab2063SBarry Smith   }
43517ab2063SBarry Smith   /* reset ilen and imax for each row */
43617ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
43717ab2063SBarry Smith     ailen[i] = imax[i] = ai[i+1] - ai[i];
43817ab2063SBarry Smith   }
439416022c9SBarry Smith   a->nz = ai[m] + shift;
44017ab2063SBarry Smith 
44117ab2063SBarry Smith   /* diagonals may have moved, so kill the diagonal pointers */
442416022c9SBarry Smith   if (fshift && a->diag) {
4430452661fSBarry Smith     PetscFree(a->diag);
444416022c9SBarry Smith     PLogObjectMemory(A,-(m+1)*sizeof(int));
445416022c9SBarry Smith     a->diag = 0;
44617ab2063SBarry Smith   }
44776dd722bSSatish Balay   /* check out for identical nodes. If found, use inode functions */
44841c01911SSatish Balay   ierr = Mat_AIJ_CheckInode(A); CHKERRQ(ierr);
449416022c9SBarry Smith   a->assembled = 1;
45017ab2063SBarry Smith   return 0;
45117ab2063SBarry Smith }
45217ab2063SBarry Smith 
453416022c9SBarry Smith static int MatZeroEntries_SeqAIJ(Mat A)
45417ab2063SBarry Smith {
455416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
456cddf8d76SBarry Smith   PetscMemzero(a->a,(a->i[a->m]+a->indexshift)*sizeof(Scalar));
45717ab2063SBarry Smith   return 0;
45817ab2063SBarry Smith }
459416022c9SBarry Smith 
46017ab2063SBarry Smith int MatDestroy_SeqAIJ(PetscObject obj)
46117ab2063SBarry Smith {
462416022c9SBarry Smith   Mat        A  = (Mat) obj;
463416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
464d5d45c9bSBarry Smith 
46517ab2063SBarry Smith #if defined(PETSC_LOG)
466416022c9SBarry Smith   PLogObjectState(obj,"Rows=%d, Cols=%d, NZ=%d",a->m,a->n,a->nz);
46717ab2063SBarry Smith #endif
4680452661fSBarry Smith   PetscFree(a->a);
4690452661fSBarry Smith   if (!a->singlemalloc) { PetscFree(a->i); PetscFree(a->j);}
4700452661fSBarry Smith   if (a->diag) PetscFree(a->diag);
4710452661fSBarry Smith   if (a->ilen) PetscFree(a->ilen);
4720452661fSBarry Smith   if (a->imax) PetscFree(a->imax);
4730452661fSBarry Smith   if (a->solve_work) PetscFree(a->solve_work);
47476dd722bSSatish Balay   if (a->inode.size) PetscFree(a->inode.size);
4750452661fSBarry Smith   PetscFree(a);
476416022c9SBarry Smith   PLogObjectDestroy(A);
4770452661fSBarry Smith   PetscHeaderDestroy(A);
47817ab2063SBarry Smith   return 0;
47917ab2063SBarry Smith }
48017ab2063SBarry Smith 
481416022c9SBarry Smith static int MatCompress_SeqAIJ(Mat A)
48217ab2063SBarry Smith {
48317ab2063SBarry Smith   return 0;
48417ab2063SBarry Smith }
48517ab2063SBarry Smith 
486416022c9SBarry Smith static int MatSetOption_SeqAIJ(Mat A,MatOption op)
48717ab2063SBarry Smith {
488416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
489416022c9SBarry Smith   if      (op == ROW_ORIENTED)              a->roworiented = 1;
4904b0e389bSBarry Smith   else if (op == COLUMN_ORIENTED)           a->roworiented = 0;
491416022c9SBarry Smith   else if (op == COLUMNS_SORTED)            a->sorted      = 1;
492416022c9SBarry Smith   else if (op == NO_NEW_NONZERO_LOCATIONS)  a->nonew       = 1;
493416022c9SBarry Smith   else if (op == YES_NEW_NONZERO_LOCATIONS) a->nonew       = 0;
494e2f28af5SBarry Smith   else if (op == ROWS_SORTED ||
495e2f28af5SBarry Smith            op == SYMMETRIC_MATRIX ||
496e2f28af5SBarry Smith            op == STRUCTURALLY_SYMMETRIC_MATRIX ||
497e2f28af5SBarry Smith            op == YES_NEW_DIAGONALS)
498df719601SLois Curfman McInnes     PLogInfo((PetscObject)A,"Info:MatSetOption_SeqAIJ:Option ignored\n");
499df719601SLois Curfman McInnes   else if (op == NO_NEW_DIAGONALS)
5004d39ef84SLois Curfman McInnes     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqAIJ:NO_NEW_DIAGONALS");}
5016c7ebb05SLois Curfman McInnes   else if (op == INODE_LIMIT_1)            a->inode.limit  = 1;
5026c7ebb05SLois Curfman McInnes   else if (op == INODE_LIMIT_2)            a->inode.limit  = 2;
5036c7ebb05SLois Curfman McInnes   else if (op == INODE_LIMIT_3)            a->inode.limit  = 3;
5046c7ebb05SLois Curfman McInnes   else if (op == INODE_LIMIT_4)            a->inode.limit  = 4;
5056c7ebb05SLois Curfman McInnes   else if (op == INODE_LIMIT_5)            a->inode.limit  = 5;
506e2f28af5SBarry Smith   else
5074d39ef84SLois Curfman McInnes     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqAIJ:unknown option");}
50817ab2063SBarry Smith   return 0;
50917ab2063SBarry Smith }
51017ab2063SBarry Smith 
511416022c9SBarry Smith static int MatGetDiagonal_SeqAIJ(Mat A,Vec v)
51217ab2063SBarry Smith {
513416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
514416022c9SBarry Smith   int        i,j, n,shift = a->indexshift;
51517ab2063SBarry Smith   Scalar     *x, zero = 0.0;
51617ab2063SBarry Smith 
517416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatGetDiagonal_SeqAIJ:Not for unassembled matrix");
51817ab2063SBarry Smith   VecSet(&zero,v);
51917ab2063SBarry Smith   VecGetArray(v,&x); VecGetLocalSize(v,&n);
520416022c9SBarry Smith   if (n != a->m) SETERRQ(1,"MatGetDiagonal_SeqAIJ:Nonconforming matrix and vector");
521416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
522416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
523416022c9SBarry Smith       if (a->j[j]+shift == i) {
524416022c9SBarry Smith         x[i] = a->a[j];
52517ab2063SBarry Smith         break;
52617ab2063SBarry Smith       }
52717ab2063SBarry Smith     }
52817ab2063SBarry Smith   }
52917ab2063SBarry Smith   return 0;
53017ab2063SBarry Smith }
53117ab2063SBarry Smith 
53217ab2063SBarry Smith /* -------------------------------------------------------*/
53317ab2063SBarry Smith /* Should check that shapes of vectors and matrices match */
53417ab2063SBarry Smith /* -------------------------------------------------------*/
535416022c9SBarry Smith static int MatMultTrans_SeqAIJ(Mat A,Vec xx,Vec yy)
53617ab2063SBarry Smith {
537416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
53817ab2063SBarry Smith   Scalar     *x, *y, *v, alpha;
539416022c9SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift;
54017ab2063SBarry Smith 
541416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatMultTrans_SeqAIJ:Not for unassembled matrix");
54217ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
543cddf8d76SBarry Smith   PetscMemzero(y,a->n*sizeof(Scalar));
54417ab2063SBarry Smith   y = y + shift; /* shift for Fortran start by 1 indexing */
54517ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
546416022c9SBarry Smith     idx   = a->j + a->i[i] + shift;
547416022c9SBarry Smith     v     = a->a + a->i[i] + shift;
548416022c9SBarry Smith     n     = a->i[i+1] - a->i[i];
54917ab2063SBarry Smith     alpha = x[i];
55017ab2063SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
55117ab2063SBarry Smith   }
552416022c9SBarry Smith   PLogFlops(2*a->nz - a->n);
55317ab2063SBarry Smith   return 0;
55417ab2063SBarry Smith }
555d5d45c9bSBarry Smith 
556416022c9SBarry Smith static int MatMultTransAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
55717ab2063SBarry Smith {
558416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
55917ab2063SBarry Smith   Scalar     *x, *y, *v, alpha;
560416022c9SBarry Smith   int        m = a->m, n, i, *idx,shift = a->indexshift;
56117ab2063SBarry Smith 
562416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatMultTransAdd_SeqAIJ:Not for unassembled matrix");
56317ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
56417ab2063SBarry Smith   if (zz != yy) VecCopy(zz,yy);
56517ab2063SBarry Smith   y = y + shift; /* shift for Fortran start by 1 indexing */
56617ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
567416022c9SBarry Smith     idx   = a->j + a->i[i] + shift;
568416022c9SBarry Smith     v     = a->a + a->i[i] + shift;
569416022c9SBarry Smith     n     = a->i[i+1] - a->i[i];
57017ab2063SBarry Smith     alpha = x[i];
57117ab2063SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
57217ab2063SBarry Smith   }
57317ab2063SBarry Smith   return 0;
57417ab2063SBarry Smith }
57517ab2063SBarry Smith 
576416022c9SBarry Smith static int MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
57717ab2063SBarry Smith {
578416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
57917ab2063SBarry Smith   Scalar     *x, *y, *v, sum;
580416022c9SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift,*ii;
58117ab2063SBarry Smith 
582416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatMult_SeqAIJ:Not for unassembled matrix");
58317ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
58417ab2063SBarry Smith   x    = x + shift; /* shift for Fortran start by 1 indexing */
585416022c9SBarry Smith   idx  = a->j;
586416022c9SBarry Smith   v    = a->a;
587416022c9SBarry Smith   ii   = a->i;
58817ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
589416022c9SBarry Smith     n    = ii[1] - ii[0]; ii++;
59017ab2063SBarry Smith     sum  = 0.0;
59117ab2063SBarry Smith     /* SPARSEDENSEDOT(sum,x,v,idx,n);  */
59217ab2063SBarry Smith     /* for ( j=n-1; j>-1; j--) sum += v[j]*x[idx[j]]; */
593416022c9SBarry Smith     while (n--) sum += *v++ * x[*idx++];
59417ab2063SBarry Smith     y[i] = sum;
59517ab2063SBarry Smith   }
596416022c9SBarry Smith   PLogFlops(2*a->nz - m);
59717ab2063SBarry Smith   return 0;
59817ab2063SBarry Smith }
59917ab2063SBarry Smith 
600416022c9SBarry Smith static int MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
60117ab2063SBarry Smith {
602416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
60317ab2063SBarry Smith   Scalar     *x, *y, *z, *v, sum;
604cddf8d76SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift,*ii;
60517ab2063SBarry Smith 
60648d91487SBarry Smith   if (!a->assembled) SETERRQ(1,"MatMultAdd_SeqAIJ:Not for unassembled matrix");
60717ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z);
60817ab2063SBarry Smith   x    = x + shift; /* shift for Fortran start by 1 indexing */
609cddf8d76SBarry Smith   idx  = a->j;
610cddf8d76SBarry Smith   v    = a->a;
611cddf8d76SBarry Smith   ii   = a->i;
61217ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
613cddf8d76SBarry Smith     n    = ii[1] - ii[0]; ii++;
61417ab2063SBarry Smith     sum  = y[i];
615cddf8d76SBarry Smith     /* SPARSEDENSEDOT(sum,x,v,idx,n);  */
616cddf8d76SBarry Smith     while (n--) sum += *v++ * x[*idx++];
61717ab2063SBarry Smith     z[i] = sum;
61817ab2063SBarry Smith   }
619416022c9SBarry Smith   PLogFlops(2*a->nz);
62017ab2063SBarry Smith   return 0;
62117ab2063SBarry Smith }
62217ab2063SBarry Smith 
62317ab2063SBarry Smith /*
62417ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
62517ab2063SBarry Smith */
62617ab2063SBarry Smith 
627416022c9SBarry Smith int MatMarkDiag_SeqAIJ(Mat A)
62817ab2063SBarry Smith {
629416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
630416022c9SBarry Smith   int        i,j, *diag, m = a->m,shift = a->indexshift;
63117ab2063SBarry Smith 
632*f0b747eeSBarry Smith   if (!a->assembled) SETERRQ(1,"MatMarkDiag_SeqAIJ:Not for unassembled matrix");
6330452661fSBarry Smith   diag = (int *) PetscMalloc( (m+1)*sizeof(int)); CHKPTRQ(diag);
634416022c9SBarry Smith   PLogObjectMemory(A,(m+1)*sizeof(int));
635416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
636416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
637416022c9SBarry Smith       if (a->j[j]+shift == i) {
63817ab2063SBarry Smith         diag[i] = j - shift;
63917ab2063SBarry Smith         break;
64017ab2063SBarry Smith       }
64117ab2063SBarry Smith     }
64217ab2063SBarry Smith   }
643416022c9SBarry Smith   a->diag = diag;
64417ab2063SBarry Smith   return 0;
64517ab2063SBarry Smith }
64617ab2063SBarry Smith 
647416022c9SBarry Smith static int MatRelax_SeqAIJ(Mat A,Vec bb,double omega,MatSORType flag,
64817ab2063SBarry Smith                            double fshift,int its,Vec xx)
64917ab2063SBarry Smith {
650416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
651416022c9SBarry Smith   Scalar     *x, *b, *bs,  d, *xs, sum, *v = a->a,*t,scale,*ts, *xb;
652d5d45c9bSBarry Smith   int        ierr, *idx, *diag,n = a->n, m = a->m, i, shift = a->indexshift;
65317ab2063SBarry Smith 
65417ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(bb,&b);
655416022c9SBarry Smith   if (!a->diag) {if ((ierr = MatMarkDiag_SeqAIJ(A))) return ierr;}
656416022c9SBarry Smith   diag = a->diag;
657416022c9SBarry Smith   xs   = x + shift; /* shifted by one for index start of a or a->j*/
65817ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
65917ab2063SBarry Smith    /* apply ( U + D/omega) to the vector */
66017ab2063SBarry Smith     bs = b + shift;
66117ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
662416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
663416022c9SBarry Smith         n    = a->i[i+1] - diag[i] - 1;
664416022c9SBarry Smith         idx  = a->j + diag[i] + (!shift);
665416022c9SBarry Smith         v    = a->a + diag[i] + (!shift);
66617ab2063SBarry Smith         sum  = b[i]*d/omega;
66717ab2063SBarry Smith         SPARSEDENSEDOT(sum,bs,v,idx,n);
66817ab2063SBarry Smith         x[i] = sum;
66917ab2063SBarry Smith     }
67017ab2063SBarry Smith     return 0;
67117ab2063SBarry Smith   }
67217ab2063SBarry Smith   if (flag == SOR_APPLY_LOWER) {
67317ab2063SBarry Smith     SETERRQ(1,"MatRelax_SeqAIJ:SOR_APPLY_LOWER is not done");
67417ab2063SBarry Smith   }
675416022c9SBarry Smith   else if (flag & SOR_EISENSTAT) {
67617ab2063SBarry Smith     /* Let  A = L + U + D; where L is lower trianglar,
67717ab2063SBarry Smith     U is upper triangular, E is diagonal; This routine applies
67817ab2063SBarry Smith 
67917ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
68017ab2063SBarry Smith 
68117ab2063SBarry Smith     to a vector efficiently using Eisenstat's trick. This is for
68217ab2063SBarry Smith     the case of SSOR preconditioner, so E is D/omega where omega
68317ab2063SBarry Smith     is the relaxation factor.
68417ab2063SBarry Smith     */
6850452661fSBarry Smith     t = (Scalar *) PetscMalloc( m*sizeof(Scalar) ); CHKPTRQ(t);
68617ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
68717ab2063SBarry Smith 
68817ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
68917ab2063SBarry Smith     for ( i=m-1; i>=0; i-- ) {
690416022c9SBarry Smith       d    = fshift + a->a[diag[i] + shift];
691416022c9SBarry Smith       n    = a->i[i+1] - diag[i] - 1;
692416022c9SBarry Smith       idx  = a->j + diag[i] + (!shift);
693416022c9SBarry Smith       v    = a->a + diag[i] + (!shift);
69417ab2063SBarry Smith       sum  = b[i];
69517ab2063SBarry Smith       SPARSEDENSEMDOT(sum,xs,v,idx,n);
69617ab2063SBarry Smith       x[i] = omega*(sum/d);
69717ab2063SBarry Smith     }
69817ab2063SBarry Smith 
69917ab2063SBarry Smith     /*  t = b - (2*E - D)x */
700416022c9SBarry Smith     v = a->a;
70117ab2063SBarry Smith     for ( i=0; i<m; i++ ) { t[i] = b[i] - scale*(v[*diag++ + shift])*x[i]; }
70217ab2063SBarry Smith 
70317ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
704416022c9SBarry Smith     ts = t + shift; /* shifted by one for index start of a or a->j*/
705416022c9SBarry Smith     diag = a->diag;
70617ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
707416022c9SBarry Smith       d    = fshift + a->a[diag[i]+shift];
708416022c9SBarry Smith       n    = diag[i] - a->i[i];
709416022c9SBarry Smith       idx  = a->j + a->i[i] + shift;
710416022c9SBarry Smith       v    = a->a + a->i[i] + shift;
71117ab2063SBarry Smith       sum  = t[i];
71217ab2063SBarry Smith       SPARSEDENSEMDOT(sum,ts,v,idx,n);
71317ab2063SBarry Smith       t[i] = omega*(sum/d);
71417ab2063SBarry Smith     }
71517ab2063SBarry Smith 
71617ab2063SBarry Smith     /*  x = x + t */
71717ab2063SBarry Smith     for ( i=0; i<m; i++ ) { x[i] += t[i]; }
7180452661fSBarry Smith     PetscFree(t);
71917ab2063SBarry Smith     return 0;
72017ab2063SBarry Smith   }
72117ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
72217ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
72317ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
724416022c9SBarry Smith         d    = fshift + a->a[diag[i]+shift];
725416022c9SBarry Smith         n    = diag[i] - a->i[i];
726416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
727416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
72817ab2063SBarry Smith         sum  = b[i];
72917ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
73017ab2063SBarry Smith         x[i] = omega*(sum/d);
73117ab2063SBarry Smith       }
73217ab2063SBarry Smith       xb = x;
73317ab2063SBarry Smith     }
73417ab2063SBarry Smith     else xb = b;
73517ab2063SBarry Smith     if ((flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) &&
73617ab2063SBarry Smith         (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP)) {
73717ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
738416022c9SBarry Smith         x[i] *= a->a[diag[i]+shift];
73917ab2063SBarry Smith       }
74017ab2063SBarry Smith     }
74117ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
74217ab2063SBarry Smith       for ( i=m-1; i>=0; i-- ) {
743416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
744416022c9SBarry Smith         n    = a->i[i+1] - diag[i] - 1;
745416022c9SBarry Smith         idx  = a->j + diag[i] + (!shift);
746416022c9SBarry Smith         v    = a->a + diag[i] + (!shift);
74717ab2063SBarry Smith         sum  = xb[i];
74817ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
74917ab2063SBarry Smith         x[i] = omega*(sum/d);
75017ab2063SBarry Smith       }
75117ab2063SBarry Smith     }
75217ab2063SBarry Smith     its--;
75317ab2063SBarry Smith   }
75417ab2063SBarry Smith   while (its--) {
75517ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
75617ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
757416022c9SBarry Smith         d    = fshift + a->a[diag[i]+shift];
758416022c9SBarry Smith         n    = a->i[i+1] - a->i[i];
759416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
760416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
76117ab2063SBarry Smith         sum  = b[i];
76217ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
76317ab2063SBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum/d + x[i]);
76417ab2063SBarry Smith       }
76517ab2063SBarry Smith     }
76617ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
76717ab2063SBarry Smith       for ( i=m-1; i>=0; i-- ) {
768416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
769416022c9SBarry Smith         n    = a->i[i+1] - a->i[i];
770416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
771416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
77217ab2063SBarry Smith         sum  = b[i];
77317ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
77417ab2063SBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum/d + x[i]);
77517ab2063SBarry Smith       }
77617ab2063SBarry Smith     }
77717ab2063SBarry Smith   }
77817ab2063SBarry Smith   return 0;
77917ab2063SBarry Smith }
78017ab2063SBarry Smith 
781d5d45c9bSBarry Smith static int MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,int *nz,int *nzalloc,int *mem)
78217ab2063SBarry Smith {
783416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
784416022c9SBarry Smith   *nz      = a->nz;
785416022c9SBarry Smith   *nzalloc = a->maxnz;
786416022c9SBarry Smith   *mem     = (int)A->mem;
78717ab2063SBarry Smith   return 0;
78817ab2063SBarry Smith }
78917ab2063SBarry Smith 
79017ab2063SBarry Smith extern int MatLUFactorSymbolic_SeqAIJ(Mat,IS,IS,double,Mat*);
79117ab2063SBarry Smith extern int MatLUFactorNumeric_SeqAIJ(Mat,Mat*);
79217ab2063SBarry Smith extern int MatLUFactor_SeqAIJ(Mat,IS,IS,double);
79317ab2063SBarry Smith extern int MatSolve_SeqAIJ(Mat,Vec,Vec);
79417ab2063SBarry Smith extern int MatSolveAdd_SeqAIJ(Mat,Vec,Vec,Vec);
79517ab2063SBarry Smith extern int MatSolveTrans_SeqAIJ(Mat,Vec,Vec);
79617ab2063SBarry Smith extern int MatSolveTransAdd_SeqAIJ(Mat,Vec,Vec,Vec);
79717ab2063SBarry Smith 
79817ab2063SBarry Smith static int MatZeroRows_SeqAIJ(Mat A,IS is,Scalar *diag)
79917ab2063SBarry Smith {
800416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
801416022c9SBarry Smith   int         i,ierr,N, *rows,m = a->m - 1,shift = a->indexshift;
80217ab2063SBarry Smith 
80317ab2063SBarry Smith   ierr = ISGetLocalSize(is,&N); CHKERRQ(ierr);
80417ab2063SBarry Smith   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
80517ab2063SBarry Smith   if (diag) {
80617ab2063SBarry Smith     for ( i=0; i<N; i++ ) {
807416022c9SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ(1,"MatZeroRows_SeqAIJ:row out of range");
808416022c9SBarry Smith       if (a->ilen[rows[i]] > 0) { /* in case row was completely empty */
809416022c9SBarry Smith         a->ilen[rows[i]] = 1;
810416022c9SBarry Smith         a->a[a->i[rows[i]]+shift] = *diag;
811416022c9SBarry Smith         a->j[a->i[rows[i]]+shift] = rows[i]+shift;
81217ab2063SBarry Smith       }
81317ab2063SBarry Smith       else {
81417ab2063SBarry Smith         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],diag,INSERT_VALUES);
81517ab2063SBarry Smith         CHKERRQ(ierr);
81617ab2063SBarry Smith       }
81717ab2063SBarry Smith     }
81817ab2063SBarry Smith   }
81917ab2063SBarry Smith   else {
82017ab2063SBarry Smith     for ( i=0; i<N; i++ ) {
821416022c9SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ(1,"MatZeroRows_SeqAIJ:row out of range");
822416022c9SBarry Smith       a->ilen[rows[i]] = 0;
82317ab2063SBarry Smith     }
82417ab2063SBarry Smith   }
82517ab2063SBarry Smith   ISRestoreIndices(is,&rows);
82617ab2063SBarry Smith   ierr = MatAssemblyBegin(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
82717ab2063SBarry Smith   ierr = MatAssemblyEnd(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
82817ab2063SBarry Smith   return 0;
82917ab2063SBarry Smith }
83017ab2063SBarry Smith 
831416022c9SBarry Smith static int MatGetSize_SeqAIJ(Mat A,int *m,int *n)
83217ab2063SBarry Smith {
833416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
834416022c9SBarry Smith   *m = a->m; *n = a->n;
83517ab2063SBarry Smith   return 0;
83617ab2063SBarry Smith }
83717ab2063SBarry Smith 
838416022c9SBarry Smith static int MatGetOwnershipRange_SeqAIJ(Mat A,int *m,int *n)
83917ab2063SBarry Smith {
840416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
841416022c9SBarry Smith   *m = 0; *n = a->m;
84217ab2063SBarry Smith   return 0;
84317ab2063SBarry Smith }
844416022c9SBarry Smith static int MatGetRow_SeqAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
84517ab2063SBarry Smith {
846416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
847416022c9SBarry Smith   int        *itmp,i,ierr,shift = a->indexshift;
84817ab2063SBarry Smith 
849416022c9SBarry Smith   if (row < 0 || row >= a->m) SETERRQ(1,"MatGetRow_SeqAIJ:Row out of range");
85017ab2063SBarry Smith 
851416022c9SBarry Smith   if (!a->assembled) {
852416022c9SBarry Smith     ierr = MatAssemblyBegin(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
853416022c9SBarry Smith     ierr = MatAssemblyEnd(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
85417ab2063SBarry Smith   }
855416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
856416022c9SBarry Smith   if (v) *v = a->a + a->i[row] + shift;
85717ab2063SBarry Smith   if (idx) {
85817ab2063SBarry Smith     if (*nz) {
859416022c9SBarry Smith       itmp = a->j + a->i[row] + shift;
8600452661fSBarry Smith       *idx = (int *) PetscMalloc( (*nz)*sizeof(int) ); CHKPTRQ(*idx);
86117ab2063SBarry Smith       for ( i=0; i<(*nz); i++ ) {(*idx)[i] = itmp[i] + shift;}
86217ab2063SBarry Smith     }
86317ab2063SBarry Smith     else *idx = 0;
86417ab2063SBarry Smith   }
86517ab2063SBarry Smith   return 0;
86617ab2063SBarry Smith }
86717ab2063SBarry Smith 
868416022c9SBarry Smith static int MatRestoreRow_SeqAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
86917ab2063SBarry Smith {
8700452661fSBarry Smith   if (idx) {if (*idx) PetscFree(*idx);}
87117ab2063SBarry Smith   return 0;
87217ab2063SBarry Smith }
87317ab2063SBarry Smith 
874cddf8d76SBarry Smith static int MatNorm_SeqAIJ(Mat A,NormType type,double *norm)
87517ab2063SBarry Smith {
876416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
877416022c9SBarry Smith   Scalar     *v = a->a;
87817ab2063SBarry Smith   double     sum = 0.0;
879416022c9SBarry Smith   int        i, j,shift = a->indexshift;
88017ab2063SBarry Smith 
881416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatNorm_SeqAIJ:Not for unassembled matrix");
88217ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
883416022c9SBarry Smith     for (i=0; i<a->nz; i++ ) {
88417ab2063SBarry Smith #if defined(PETSC_COMPLEX)
88517ab2063SBarry Smith       sum += real(conj(*v)*(*v)); v++;
88617ab2063SBarry Smith #else
88717ab2063SBarry Smith       sum += (*v)*(*v); v++;
88817ab2063SBarry Smith #endif
88917ab2063SBarry Smith     }
89017ab2063SBarry Smith     *norm = sqrt(sum);
89117ab2063SBarry Smith   }
89217ab2063SBarry Smith   else if (type == NORM_1) {
89317ab2063SBarry Smith     double *tmp;
894416022c9SBarry Smith     int    *jj = a->j;
8950452661fSBarry Smith     tmp = (double *) PetscMalloc( a->n*sizeof(double) ); CHKPTRQ(tmp);
896cddf8d76SBarry Smith     PetscMemzero(tmp,a->n*sizeof(double));
89717ab2063SBarry Smith     *norm = 0.0;
898416022c9SBarry Smith     for ( j=0; j<a->nz; j++ ) {
899a2744918SBarry Smith         tmp[*jj++ + shift] += PetscAbsScalar(*v);  v++;
90017ab2063SBarry Smith     }
901416022c9SBarry Smith     for ( j=0; j<a->n; j++ ) {
90217ab2063SBarry Smith       if (tmp[j] > *norm) *norm = tmp[j];
90317ab2063SBarry Smith     }
9040452661fSBarry Smith     PetscFree(tmp);
90517ab2063SBarry Smith   }
90617ab2063SBarry Smith   else if (type == NORM_INFINITY) {
90717ab2063SBarry Smith     *norm = 0.0;
908416022c9SBarry Smith     for ( j=0; j<a->m; j++ ) {
909416022c9SBarry Smith       v = a->a + a->i[j] + shift;
91017ab2063SBarry Smith       sum = 0.0;
911416022c9SBarry Smith       for ( i=0; i<a->i[j+1]-a->i[j]; i++ ) {
912cddf8d76SBarry Smith         sum += PetscAbsScalar(*v); v++;
91317ab2063SBarry Smith       }
91417ab2063SBarry Smith       if (sum > *norm) *norm = sum;
91517ab2063SBarry Smith     }
91617ab2063SBarry Smith   }
91717ab2063SBarry Smith   else {
91848d91487SBarry Smith     SETERRQ(1,"MatNorm_SeqAIJ:No support for two norm yet");
91917ab2063SBarry Smith   }
92017ab2063SBarry Smith   return 0;
92117ab2063SBarry Smith }
92217ab2063SBarry Smith 
923416022c9SBarry Smith static int MatTranspose_SeqAIJ(Mat A,Mat *B)
92417ab2063SBarry Smith {
925416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
926416022c9SBarry Smith   Mat        C;
927416022c9SBarry Smith   int        i, ierr, *aj = a->j, *ai = a->i, m = a->m, len, *col;
928416022c9SBarry Smith   int        shift = a->indexshift;
929d5d45c9bSBarry Smith   Scalar     *array = a->a;
93017ab2063SBarry Smith 
931416022c9SBarry Smith   if (!B && m != a->n) SETERRQ(1,"MatTranspose_SeqAIJ:Not for rectangular mat in place");
9320452661fSBarry Smith   col = (int *) PetscMalloc((1+a->n)*sizeof(int)); CHKPTRQ(col);
933cddf8d76SBarry Smith   PetscMemzero(col,(1+a->n)*sizeof(int));
93417ab2063SBarry Smith   if (shift) {
93517ab2063SBarry Smith     for ( i=0; i<ai[m]-1; i++ ) aj[i] -= 1;
93617ab2063SBarry Smith   }
93717ab2063SBarry Smith   for ( i=0; i<ai[m]+shift; i++ ) col[aj[i]] += 1;
938416022c9SBarry Smith   ierr = MatCreateSeqAIJ(A->comm,a->n,m,0,col,&C); CHKERRQ(ierr);
9390452661fSBarry Smith   PetscFree(col);
94017ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
94117ab2063SBarry Smith     len = ai[i+1]-ai[i];
942416022c9SBarry Smith     ierr = MatSetValues(C,len,aj,1,&i,array,INSERT_VALUES); CHKERRQ(ierr);
94317ab2063SBarry Smith     array += len; aj += len;
94417ab2063SBarry Smith   }
94517ab2063SBarry Smith   if (shift) {
94617ab2063SBarry Smith     for ( i=0; i<ai[m]-1; i++ ) aj[i] += 1;
94717ab2063SBarry Smith   }
94817ab2063SBarry Smith 
949416022c9SBarry Smith   ierr = MatAssemblyBegin(C,FINAL_ASSEMBLY); CHKERRQ(ierr);
950416022c9SBarry Smith   ierr = MatAssemblyEnd(C,FINAL_ASSEMBLY); CHKERRQ(ierr);
95117ab2063SBarry Smith 
952416022c9SBarry Smith   if (B) {
953416022c9SBarry Smith     *B = C;
95417ab2063SBarry Smith   } else {
955416022c9SBarry Smith     /* This isn't really an in-place transpose */
9560452661fSBarry Smith     PetscFree(a->a);
9570452661fSBarry Smith     if (!a->singlemalloc) {PetscFree(a->i); PetscFree(a->j);}
9580452661fSBarry Smith     if (a->diag) PetscFree(a->diag);
9590452661fSBarry Smith     if (a->ilen) PetscFree(a->ilen);
9600452661fSBarry Smith     if (a->imax) PetscFree(a->imax);
9610452661fSBarry Smith     if (a->solve_work) PetscFree(a->solve_work);
9620452661fSBarry Smith     PetscFree(a);
963416022c9SBarry Smith     PetscMemcpy(A,C,sizeof(struct _Mat));
9640452661fSBarry Smith     PetscHeaderDestroy(C);
96517ab2063SBarry Smith   }
96617ab2063SBarry Smith   return 0;
96717ab2063SBarry Smith }
96817ab2063SBarry Smith 
969*f0b747eeSBarry Smith static int MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
97017ab2063SBarry Smith {
971416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
97217ab2063SBarry Smith   Scalar     *l,*r,x,*v;
973d5d45c9bSBarry Smith   int        i,j,m = a->m, n = a->n, M, nz = a->nz, *jj,shift = a->indexshift;
97417ab2063SBarry Smith 
975*f0b747eeSBarry Smith   if (!a->assembled) SETERRQ(1,"MatDiagonalScale_SeqAIJ:Not for unassembled matrix");
97617ab2063SBarry Smith   if (ll) {
97717ab2063SBarry Smith     VecGetArray(ll,&l); VecGetSize(ll,&m);
978*f0b747eeSBarry Smith     if (m != a->m) SETERRQ(1,"MatDiagonalScale_SeqAIJ:Left scaling vector wrong length");
979416022c9SBarry Smith     v = a->a;
98017ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
98117ab2063SBarry Smith       x = l[i];
982416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
98317ab2063SBarry Smith       for ( j=0; j<M; j++ ) { (*v++) *= x;}
98417ab2063SBarry Smith     }
98517ab2063SBarry Smith   }
98617ab2063SBarry Smith   if (rr) {
98717ab2063SBarry Smith     VecGetArray(rr,&r); VecGetSize(rr,&n);
988*f0b747eeSBarry Smith     if (n != a->n) SETERRQ(1,"MatDiagonalScale_SeqAIJ:Right scaling vector wrong length");
989416022c9SBarry Smith     v = a->a; jj = a->j;
99017ab2063SBarry Smith     for ( i=0; i<nz; i++ ) {
99117ab2063SBarry Smith       (*v++) *= r[*jj++ + shift];
99217ab2063SBarry Smith     }
99317ab2063SBarry Smith   }
99417ab2063SBarry Smith   return 0;
99517ab2063SBarry Smith }
99617ab2063SBarry Smith 
997cddf8d76SBarry Smith static int MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,MatGetSubMatrixCall scall,Mat *B)
99817ab2063SBarry Smith {
999db02288aSLois Curfman McInnes   Mat_SeqAIJ   *a = (Mat_SeqAIJ *) A->data,*c;
100002834360SBarry Smith   int          nznew, *smap, i, k, kstart, kend, ierr, oldcols = a->n,*lens;
1001a2744918SBarry Smith   register int sum,lensi;
100202834360SBarry Smith   int          *irow, *icol, nrows, ncols, *cwork, shift = a->indexshift,*ssmap;
1003a2744918SBarry Smith   int          first,step,*starts,*j_new,*i_new,*aj = a->j, *ai = a->i,ii,*ailen = a->ilen;
1004db02288aSLois Curfman McInnes   Scalar       *vwork,*a_new;
1005416022c9SBarry Smith   Mat          C;
100617ab2063SBarry Smith 
1007416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatGetSubMatrix_SeqAIJ:Not for unassembled matrix");
100817ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow); CHKERRQ(ierr);
100917ab2063SBarry Smith   ierr = ISGetSize(isrow,&nrows); CHKERRQ(ierr);
101017ab2063SBarry Smith   ierr = ISGetSize(iscol,&ncols); CHKERRQ(ierr);
101117ab2063SBarry Smith 
101202834360SBarry Smith   if (ISStrideGetInfo(iscol,&first,&step) && step == 1) {
101302834360SBarry Smith     /* special case of contiguous rows */
10140452661fSBarry Smith     lens   = (int *) PetscMalloc((2*ncols+1)*sizeof(int)); CHKPTRQ(lens);
101502834360SBarry Smith     starts = lens + ncols;
101602834360SBarry Smith     /* loop over new rows determining lens and starting points */
101702834360SBarry Smith     for (i=0; i<nrows; i++) {
1018a2744918SBarry Smith       kstart  = ai[irow[i]]+shift;
1019a2744918SBarry Smith       kend    = kstart + ailen[irow[i]];
102002834360SBarry Smith       for ( k=kstart; k<kend; k++ ) {
1021d8ced48eSBarry Smith         if (aj[k]+shift >= first) {
102202834360SBarry Smith           starts[i] = k;
102302834360SBarry Smith           break;
102402834360SBarry Smith 	}
102502834360SBarry Smith       }
1026a2744918SBarry Smith       sum = 0;
102702834360SBarry Smith       while (k < kend) {
1028d8ced48eSBarry Smith         if (aj[k++]+shift >= first+ncols) break;
1029a2744918SBarry Smith         sum++;
103002834360SBarry Smith       }
1031a2744918SBarry Smith       lens[i] = sum;
103202834360SBarry Smith     }
103302834360SBarry Smith     /* create submatrix */
1034cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
103508480c60SBarry Smith       int n_cols,n_rows;
103608480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols); CHKERRQ(ierr);
103708480c60SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(1,"MatGetSubMatrix_SeqAIJ:");
1038d8ced48eSBarry Smith       ierr = MatZeroEntries(*B); CHKERRQ(ierr);
103908480c60SBarry Smith       C = *B;
104008480c60SBarry Smith     }
104108480c60SBarry Smith     else {
104202834360SBarry Smith       ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr);
104308480c60SBarry Smith     }
1044db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*) C->data;
1045db02288aSLois Curfman McInnes 
104602834360SBarry Smith     /* loop over rows inserting into submatrix */
1047db02288aSLois Curfman McInnes     a_new    = c->a;
1048db02288aSLois Curfman McInnes     j_new    = c->j;
1049db02288aSLois Curfman McInnes     i_new    = c->i;
1050db02288aSLois Curfman McInnes     i_new[0] = -shift;
105102834360SBarry Smith     for (i=0; i<nrows; i++) {
1052a2744918SBarry Smith       ii    = starts[i];
1053a2744918SBarry Smith       lensi = lens[i];
1054a2744918SBarry Smith       for ( k=0; k<lensi; k++ ) {
1055a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
105602834360SBarry Smith       }
1057a2744918SBarry Smith       PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(Scalar));
1058a2744918SBarry Smith       a_new      += lensi;
1059a2744918SBarry Smith       i_new[i+1]  = i_new[i] + lensi;
1060a2744918SBarry Smith       c->ilen[i]  = lensi;
106102834360SBarry Smith     }
10620452661fSBarry Smith     PetscFree(lens);
106302834360SBarry Smith   }
106402834360SBarry Smith   else {
106502834360SBarry Smith     ierr = ISGetIndices(iscol,&icol); CHKERRQ(ierr);
10660452661fSBarry Smith     smap  = (int *) PetscMalloc((1+oldcols)*sizeof(int)); CHKPTRQ(smap);
106702834360SBarry Smith     ssmap = smap + shift;
10687eb43aa7SLois Curfman McInnes     cwork = (int *) PetscMalloc((1+nrows+ncols)*sizeof(int)); CHKPTRQ(cwork);
106902834360SBarry Smith     lens  = cwork + ncols;
10700452661fSBarry Smith     vwork = (Scalar *) PetscMalloc((1+ncols)*sizeof(Scalar)); CHKPTRQ(vwork);
1071cddf8d76SBarry Smith     PetscMemzero(smap,oldcols*sizeof(int));
107217ab2063SBarry Smith     for ( i=0; i<ncols; i++ ) smap[icol[i]] = i+1;
107302834360SBarry Smith     /* determine lens of each row */
107402834360SBarry Smith     for (i=0; i<nrows; i++) {
1075d8ced48eSBarry Smith       kstart  = ai[irow[i]]+shift;
107602834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
107702834360SBarry Smith       lens[i] = 0;
107802834360SBarry Smith       for ( k=kstart; k<kend; k++ ) {
1079d8ced48eSBarry Smith         if (ssmap[aj[k]]) {
108002834360SBarry Smith           lens[i]++;
108102834360SBarry Smith         }
108202834360SBarry Smith       }
108302834360SBarry Smith     }
108417ab2063SBarry Smith     /* Create and fill new matrix */
1085a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
108608480c60SBarry Smith       int n_cols,n_rows;
108708480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols); CHKERRQ(ierr);
108808480c60SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(1,"MatGetSubMatrix_SeqAIJ:");
1089d8ced48eSBarry Smith       ierr = MatZeroEntries(*B); CHKERRQ(ierr);
109008480c60SBarry Smith       C = *B;
109108480c60SBarry Smith     }
109208480c60SBarry Smith     else {
109302834360SBarry Smith       ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr);
109408480c60SBarry Smith     }
109517ab2063SBarry Smith     for (i=0; i<nrows; i++) {
109617ab2063SBarry Smith       nznew  = 0;
1097d8ced48eSBarry Smith       kstart = ai[irow[i]]+shift;
1098416022c9SBarry Smith       kend   = kstart + a->ilen[irow[i]];
109917ab2063SBarry Smith       for ( k=kstart; k<kend; k++ ) {
110002834360SBarry Smith         if (ssmap[a->j[k]]) {
110102834360SBarry Smith           cwork[nznew]   = ssmap[a->j[k]] - 1;
1102416022c9SBarry Smith           vwork[nznew++] = a->a[k];
110317ab2063SBarry Smith         }
110417ab2063SBarry Smith       }
1105416022c9SBarry Smith       ierr = MatSetValues(C,1,&i,nznew,cwork,vwork,INSERT_VALUES); CHKERRQ(ierr);
110617ab2063SBarry Smith     }
110702834360SBarry Smith     /* Free work space */
110802834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol); CHKERRQ(ierr);
11090452661fSBarry Smith     PetscFree(smap); PetscFree(cwork); PetscFree(vwork);
111002834360SBarry Smith   }
1111416022c9SBarry Smith   ierr = MatAssemblyBegin(C,FINAL_ASSEMBLY); CHKERRQ(ierr);
1112416022c9SBarry Smith   ierr = MatAssemblyEnd(C,FINAL_ASSEMBLY); CHKERRQ(ierr);
111317ab2063SBarry Smith 
111417ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow); CHKERRQ(ierr);
1115416022c9SBarry Smith   *B = C;
111617ab2063SBarry Smith   return 0;
111717ab2063SBarry Smith }
111817ab2063SBarry Smith 
1119a871dcd8SBarry Smith /*
112063b91edcSBarry Smith      note: This can only work for identity for row and col. It would
112163b91edcSBarry Smith    be good to check this and otherwise generate an error.
1122a871dcd8SBarry Smith */
112363b91edcSBarry Smith static int MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,double efill,int fill)
1124a871dcd8SBarry Smith {
112563b91edcSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) inA->data;
112608480c60SBarry Smith   int        ierr;
112763b91edcSBarry Smith   Mat        outA;
112863b91edcSBarry Smith 
1129a871dcd8SBarry Smith   if (fill != 0) SETERRQ(1,"MatILUFactor_SeqAIJ:Only fill=0 supported");
1130a871dcd8SBarry Smith 
113163b91edcSBarry Smith   outA          = inA;
113263b91edcSBarry Smith   inA->factor   = FACTOR_LU;
113363b91edcSBarry Smith   a->row        = row;
113463b91edcSBarry Smith   a->col        = col;
113563b91edcSBarry Smith 
11360452661fSBarry Smith   a->solve_work = (Scalar *) PetscMalloc( (a->m+1)*sizeof(Scalar)); CHKPTRQ(a->solve_work);
113763b91edcSBarry Smith 
113808480c60SBarry Smith   if (!a->diag) {
113908480c60SBarry Smith     ierr = MatMarkDiag_SeqAIJ(inA); CHKERRQ(ierr);
114063b91edcSBarry Smith   }
114163b91edcSBarry Smith   ierr = MatLUFactorNumeric_SeqAIJ(inA,&outA); CHKERRQ(ierr);
1142a871dcd8SBarry Smith   return 0;
1143a871dcd8SBarry Smith }
1144a871dcd8SBarry Smith 
1145*f0b747eeSBarry Smith #include "pinclude/plapack.h"
1146*f0b747eeSBarry Smith static int MatScale_SeqAIJ(Scalar *alpha,Mat inA)
1147*f0b747eeSBarry Smith {
1148*f0b747eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) inA->data;
1149*f0b747eeSBarry Smith   int        one = 1;
1150*f0b747eeSBarry Smith   if (!a->assembled) SETERRQ(1,"MatScale_SeqAIJ:Not for unassembled matrix");
1151*f0b747eeSBarry Smith   BLscal_( &a->nz, alpha, a->a, &one );
1152*f0b747eeSBarry Smith   PLogFlops(a->nz);
1153*f0b747eeSBarry Smith   return 0;
1154*f0b747eeSBarry Smith }
1155*f0b747eeSBarry Smith 
1156cddf8d76SBarry Smith static int MatGetSubMatrices_SeqAIJ(Mat A,int n, IS *irow,IS *icol,MatGetSubMatrixCall scall,
1157cddf8d76SBarry Smith                                     Mat **B)
1158cddf8d76SBarry Smith {
1159cddf8d76SBarry Smith   int ierr,i;
1160cddf8d76SBarry Smith 
1161cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
11620452661fSBarry Smith     *B = (Mat *) PetscMalloc( (n+1)*sizeof(Mat) ); CHKPTRQ(*B);
1163cddf8d76SBarry Smith   }
1164cddf8d76SBarry Smith 
1165cddf8d76SBarry Smith   for ( i=0; i<n; i++ ) {
1166cddf8d76SBarry Smith     ierr = MatGetSubMatrix(A,irow[i],icol[i],scall,&(*B)[i]); CHKERRQ(ierr);
1167cddf8d76SBarry Smith   }
1168cddf8d76SBarry Smith   return 0;
1169cddf8d76SBarry Smith }
1170cddf8d76SBarry Smith 
11714dcbc457SBarry Smith static int MatIncreaseOverlap_SeqAIJ(Mat A, int n, IS *is, int ov)
11724dcbc457SBarry Smith {
11734dcbc457SBarry Smith   int i,m,*idx,ierr;
11744dcbc457SBarry Smith 
11754dcbc457SBarry Smith   for ( i=0; i<n; i++ ) {
11764dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx); CHKERRQ(ierr);
11774dcbc457SBarry Smith     ISGetLocalSize(is[i],&m);
11784dcbc457SBarry Smith   }
11794dcbc457SBarry Smith   SETERRQ(1,"MatIncreaseOverlap_SeqAIJ:Not implemented");
11804dcbc457SBarry Smith }
118117ab2063SBarry Smith 
1182682d7d0cSBarry Smith int MatPrintHelp_SeqAIJ(Mat A)
1183682d7d0cSBarry Smith {
1184682d7d0cSBarry Smith   static int called = 0;
1185682d7d0cSBarry Smith   MPI_Comm   comm = A->comm;
1186682d7d0cSBarry Smith 
1187682d7d0cSBarry Smith   if (called) return 0; else called = 1;
11882a7368beSLois Curfman McInnes   MPIU_printf(comm," Options for MATSEQAIJ and MATMPIAIJ matrix formats (the defaults):\n");
1189682d7d0cSBarry Smith   MPIU_printf(comm,"  -mat_lu_pivotthreshold <threshold>\n");
11902a7368beSLois Curfman McInnes   MPIU_printf(comm,"  -mat_aij_oneindex - internal indices begin at 1 instead of the default 0.\n");
1191682d7d0cSBarry Smith   MPIU_printf(comm,"  -mat_aij_no_inode  - Do not use inodes\n");
1192682d7d0cSBarry Smith   MPIU_printf(comm,"  -mat_aij_inode_limit <limit> - Set inode limit (max limit=5)\n");
1193682d7d0cSBarry Smith #if defined(HAVE_ESSL)
1194682d7d0cSBarry Smith   MPIU_printf(comm,"  -mat_aij_essl  - Use IBM sparse LU factorization and solve.\n");
1195682d7d0cSBarry Smith #endif
1196682d7d0cSBarry Smith   return 0;
1197682d7d0cSBarry Smith }
1198682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
119917ab2063SBarry Smith static struct _MatOps MatOps = {MatSetValues_SeqAIJ,
120017ab2063SBarry Smith        MatGetRow_SeqAIJ,MatRestoreRow_SeqAIJ,
1201416022c9SBarry Smith        MatMult_SeqAIJ,MatMultAdd_SeqAIJ,
1202416022c9SBarry Smith        MatMultTrans_SeqAIJ,MatMultTransAdd_SeqAIJ,
120317ab2063SBarry Smith        MatSolve_SeqAIJ,MatSolveAdd_SeqAIJ,
120417ab2063SBarry Smith        MatSolveTrans_SeqAIJ,MatSolveTransAdd_SeqAIJ,
120517ab2063SBarry Smith        MatLUFactor_SeqAIJ,0,
120617ab2063SBarry Smith        MatRelax_SeqAIJ,
120717ab2063SBarry Smith        MatTranspose_SeqAIJ,
120817ab2063SBarry Smith        MatGetInfo_SeqAIJ,0,
1209*f0b747eeSBarry Smith        MatGetDiagonal_SeqAIJ,MatDiagonalScale_SeqAIJ,MatNorm_SeqAIJ,
121017ab2063SBarry Smith        0,MatAssemblyEnd_SeqAIJ,
121117ab2063SBarry Smith        MatCompress_SeqAIJ,
121217ab2063SBarry Smith        MatSetOption_SeqAIJ,MatZeroEntries_SeqAIJ,MatZeroRows_SeqAIJ,
121317ab2063SBarry Smith        MatGetReordering_SeqAIJ,
121417ab2063SBarry Smith        MatLUFactorSymbolic_SeqAIJ,MatLUFactorNumeric_SeqAIJ,0,0,
121517ab2063SBarry Smith        MatGetSize_SeqAIJ,MatGetSize_SeqAIJ,MatGetOwnershipRange_SeqAIJ,
121617ab2063SBarry Smith        MatILUFactorSymbolic_SeqAIJ,0,
121717ab2063SBarry Smith        0,0,MatConvert_SeqAIJ,
1218416022c9SBarry Smith        MatGetSubMatrix_SeqAIJ,0,
12193d1612f7SBarry Smith        MatConvertSameType_SeqAIJ,0,0,
1220cddf8d76SBarry Smith        MatILUFactor_SeqAIJ,0,0,
12217eb43aa7SLois Curfman McInnes        MatGetSubMatrices_SeqAIJ,MatIncreaseOverlap_SeqAIJ,
1222682d7d0cSBarry Smith        MatGetValues_SeqAIJ,0,
1223*f0b747eeSBarry Smith        MatPrintHelp_SeqAIJ,
1224*f0b747eeSBarry Smith        MatScale_SeqAIJ};
122517ab2063SBarry Smith 
122617ab2063SBarry Smith extern int MatUseSuperLU_SeqAIJ(Mat);
122717ab2063SBarry Smith extern int MatUseEssl_SeqAIJ(Mat);
122817ab2063SBarry Smith extern int MatUseDXML_SeqAIJ(Mat);
122917ab2063SBarry Smith 
123017ab2063SBarry Smith /*@C
1231682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
123217ab2063SBarry Smith                      (the default uniprocessor PETSc format).
123317ab2063SBarry Smith 
123417ab2063SBarry Smith    Input Parameters:
123517ab2063SBarry Smith .  comm - MPI communicator, set to MPI_COMM_SELF
123617ab2063SBarry Smith .  m - number of rows
123717ab2063SBarry Smith .  n - number of columns
123817ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
123917ab2063SBarry Smith .  nzz - number of nonzeros per row or null (possibly different for each row)
124017ab2063SBarry Smith 
124117ab2063SBarry Smith    Output Parameter:
1242416022c9SBarry Smith .  A - the matrix
124317ab2063SBarry Smith 
124417ab2063SBarry Smith    Notes:
124517ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
124617ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
12470002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
12480002213bSLois Curfman McInnes    either one (as in Fortran) or zero.  See the users manual for details.
124917ab2063SBarry Smith 
125017ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
1251a40aa06bSLois Curfman McInnes    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
125217ab2063SBarry Smith    allocation.
125317ab2063SBarry Smith 
1254682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
1255682d7d0cSBarry Smith    improve numerical efficiency of Matrix vector products and solves. We
1256682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
12576c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
12586c7ebb05SLois Curfman McInnes 
12596c7ebb05SLois Curfman McInnes    Options Database Keys:
12606c7ebb05SLois Curfman McInnes $    -mat_aij_no_inode  - Do not use inodes
12616c7ebb05SLois Curfman McInnes $    -mat_aij_inode_limit <limit> - Set inode limit (max limit=5)
12624b0e389bSBarry Smith $    -mat_aij_oneindex - Internally using indexing starting at 1 rather then zero.
12634b0e389bSBarry Smith .                        Note: You still index entries starting at 0!
126417ab2063SBarry Smith 
126517ab2063SBarry Smith .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues()
126617ab2063SBarry Smith @*/
1267416022c9SBarry Smith int MatCreateSeqAIJ(MPI_Comm comm,int m,int n,int nz,int *nnz, Mat *A)
126817ab2063SBarry Smith {
1269416022c9SBarry Smith   Mat        B;
1270416022c9SBarry Smith   Mat_SeqAIJ *b;
127169957df2SSatish Balay   int        i,len,ierr, flg;
1272d5d45c9bSBarry Smith 
1273416022c9SBarry Smith   *A      = 0;
12740452661fSBarry Smith   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSEQAIJ,comm);
1275416022c9SBarry Smith   PLogObjectCreate(B);
12760452661fSBarry Smith   B->data             = (void *) (b = PetscNew(Mat_SeqAIJ)); CHKPTRQ(b);
1277416022c9SBarry Smith   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
1278416022c9SBarry Smith   B->destroy          = MatDestroy_SeqAIJ;
1279416022c9SBarry Smith   B->view             = MatView_SeqAIJ;
1280416022c9SBarry Smith   B->factor           = 0;
1281416022c9SBarry Smith   B->lupivotthreshold = 1.0;
128269957df2SSatish Balay   ierr = OptionsGetDouble(PETSC_NULL,"-mat_lu_pivotthreshold",&B->lupivotthreshold, \
128369957df2SSatish Balay                           &flg); CHKERRQ(ierr);
1284416022c9SBarry Smith   b->row              = 0;
1285416022c9SBarry Smith   b->col              = 0;
1286416022c9SBarry Smith   b->indexshift       = 0;
128769957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_oneindex", &flg); CHKERRQ(ierr);
128869957df2SSatish Balay   if (flg) b->indexshift = -1;
128917ab2063SBarry Smith 
1290416022c9SBarry Smith   b->m       = m;
1291416022c9SBarry Smith   b->n       = n;
12920452661fSBarry Smith   b->imax    = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(b->imax);
1293b4fd4287SBarry Smith   if (nnz == PETSC_NULL) {
12947b8455f0SLois Curfman McInnes     if (nz == PETSC_DEFAULT) nz = 10;
12957b8455f0SLois Curfman McInnes     else if (nz <= 0)        nz = 1;
1296416022c9SBarry Smith     for ( i=0; i<m; i++ ) b->imax[i] = nz;
129717ab2063SBarry Smith     nz = nz*m;
129817ab2063SBarry Smith   }
129917ab2063SBarry Smith   else {
130017ab2063SBarry Smith     nz = 0;
1301416022c9SBarry Smith     for ( i=0; i<m; i++ ) {b->imax[i] = nnz[i]; nz += nnz[i];}
130217ab2063SBarry Smith   }
130317ab2063SBarry Smith 
130417ab2063SBarry Smith   /* allocate the matrix space */
1305416022c9SBarry Smith   len     = nz*(sizeof(int) + sizeof(Scalar)) + (b->m+1)*sizeof(int);
13060452661fSBarry Smith   b->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(b->a);
1307416022c9SBarry Smith   b->j  = (int *) (b->a + nz);
1308cddf8d76SBarry Smith   PetscMemzero(b->j,nz*sizeof(int));
1309416022c9SBarry Smith   b->i  = b->j + nz;
1310416022c9SBarry Smith   b->singlemalloc = 1;
131117ab2063SBarry Smith 
1312416022c9SBarry Smith   b->i[0] = -b->indexshift;
131317ab2063SBarry Smith   for (i=1; i<m+1; i++) {
1314416022c9SBarry Smith     b->i[i] = b->i[i-1] + b->imax[i-1];
131517ab2063SBarry Smith   }
131617ab2063SBarry Smith 
1317416022c9SBarry Smith   /* b->ilen will count nonzeros in each row so far. */
13180452661fSBarry Smith   b->ilen = (int *) PetscMalloc((m+1)*sizeof(int));
1319416022c9SBarry Smith   PLogObjectMemory(B,len+2*(m+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqAIJ));
1320416022c9SBarry Smith   for ( i=0; i<b->m; i++ ) { b->ilen[i] = 0;}
132117ab2063SBarry Smith 
1322416022c9SBarry Smith   b->nz               = 0;
1323416022c9SBarry Smith   b->maxnz            = nz;
1324416022c9SBarry Smith   b->sorted           = 0;
1325416022c9SBarry Smith   b->roworiented      = 1;
1326416022c9SBarry Smith   b->nonew            = 0;
1327416022c9SBarry Smith   b->diag             = 0;
1328416022c9SBarry Smith   b->assembled        = 0;
1329416022c9SBarry Smith   b->solve_work       = 0;
133071bd300dSLois Curfman McInnes   b->spptr            = 0;
1331754ec7b1SSatish Balay   b->inode.node_count = 0;
1332754ec7b1SSatish Balay   b->inode.size       = 0;
13336c7ebb05SLois Curfman McInnes   b->inode.limit      = 5;
13346c7ebb05SLois Curfman McInnes   b->inode.max_limit  = 5;
133517ab2063SBarry Smith 
1336416022c9SBarry Smith   *A = B;
133769957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_superlu", &flg); CHKERRQ(ierr);
133869957df2SSatish Balay   if (flg) { ierr = MatUseSuperLU_SeqAIJ(B); CHKERRQ(ierr); }
133969957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_essl", &flg); CHKERRQ(ierr);
134069957df2SSatish Balay   if (flg) { ierr = MatUseEssl_SeqAIJ(B); CHKERRQ(ierr); }
134169957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_aij_dxml", &flg); CHKERRQ(ierr);
134269957df2SSatish Balay   if (flg) {
1343416022c9SBarry Smith     if (!b->indexshift) SETERRQ(1,"MatCreateSeqAIJ:need -mat_aij_oneindex with -mat_aij_dxml");
1344416022c9SBarry Smith     ierr = MatUseDXML_SeqAIJ(B); CHKERRQ(ierr);
134517ab2063SBarry Smith   }
134669957df2SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-help", &flg); CHKERRQ(ierr);
134769957df2SSatish Balay   if (flg) {ierr = MatPrintHelp(B); CHKERRQ(ierr); }
134817ab2063SBarry Smith   return 0;
134917ab2063SBarry Smith }
135017ab2063SBarry Smith 
13513d1612f7SBarry Smith int MatConvertSameType_SeqAIJ(Mat A,Mat *B,int cpvalues)
135217ab2063SBarry Smith {
1353416022c9SBarry Smith   Mat        C;
1354416022c9SBarry Smith   Mat_SeqAIJ *c,*a = (Mat_SeqAIJ *) A->data;
135508480c60SBarry Smith   int        i,len, m = a->m,shift = a->indexshift;
135617ab2063SBarry Smith 
13574043dd9cSLois Curfman McInnes   *B = 0;
1358*f0b747eeSBarry Smith   if (!a->assembled) SETERRQ(1,"MatConvertSameType_SeqAIJ:Not for unassembled matrix");
13590452661fSBarry Smith   PetscHeaderCreate(C,_Mat,MAT_COOKIE,MATSEQAIJ,A->comm);
1360416022c9SBarry Smith   PLogObjectCreate(C);
13610452661fSBarry Smith   C->data       = (void *) (c = PetscNew(Mat_SeqAIJ)); CHKPTRQ(c);
136241c01911SSatish Balay   PetscMemcpy(&C->ops,&A->ops,sizeof(struct _MatOps));
1363416022c9SBarry Smith   C->destroy    = MatDestroy_SeqAIJ;
1364416022c9SBarry Smith   C->view       = MatView_SeqAIJ;
1365416022c9SBarry Smith   C->factor     = A->factor;
1366416022c9SBarry Smith   c->row        = 0;
1367416022c9SBarry Smith   c->col        = 0;
1368416022c9SBarry Smith   c->indexshift = shift;
136917ab2063SBarry Smith 
1370416022c9SBarry Smith   c->m          = a->m;
1371416022c9SBarry Smith   c->n          = a->n;
137217ab2063SBarry Smith 
13730452661fSBarry Smith   c->imax       = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(c->imax);
13740452661fSBarry Smith   c->ilen       = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(c->ilen);
137517ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
1376416022c9SBarry Smith     c->imax[i] = a->imax[i];
1377416022c9SBarry Smith     c->ilen[i] = a->ilen[i];
137817ab2063SBarry Smith   }
137917ab2063SBarry Smith 
138017ab2063SBarry Smith   /* allocate the matrix space */
1381416022c9SBarry Smith   c->singlemalloc = 1;
1382416022c9SBarry Smith   len     = (m+1)*sizeof(int)+(a->i[m])*(sizeof(Scalar)+sizeof(int));
13830452661fSBarry Smith   c->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(c->a);
1384416022c9SBarry Smith   c->j  = (int *) (c->a + a->i[m] + shift);
1385416022c9SBarry Smith   c->i  = c->j + a->i[m] + shift;
1386416022c9SBarry Smith   PetscMemcpy(c->i,a->i,(m+1)*sizeof(int));
138717ab2063SBarry Smith   if (m > 0) {
1388416022c9SBarry Smith     PetscMemcpy(c->j,a->j,(a->i[m]+shift)*sizeof(int));
138908480c60SBarry Smith     if (cpvalues == COPY_VALUES) {
1390416022c9SBarry Smith       PetscMemcpy(c->a,a->a,(a->i[m]+shift)*sizeof(Scalar));
139117ab2063SBarry Smith     }
139208480c60SBarry Smith   }
139317ab2063SBarry Smith 
1394416022c9SBarry Smith   PLogObjectMemory(C,len+2*(m+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqAIJ));
1395416022c9SBarry Smith   c->sorted      = a->sorted;
1396416022c9SBarry Smith   c->roworiented = a->roworiented;
1397416022c9SBarry Smith   c->nonew       = a->nonew;
139817ab2063SBarry Smith 
1399416022c9SBarry Smith   if (a->diag) {
14000452661fSBarry Smith     c->diag = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(c->diag);
1401416022c9SBarry Smith     PLogObjectMemory(C,(m+1)*sizeof(int));
140217ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
1403416022c9SBarry Smith       c->diag[i] = a->diag[i];
140417ab2063SBarry Smith     }
140517ab2063SBarry Smith   }
1406416022c9SBarry Smith   else c->diag          = 0;
14076c7ebb05SLois Curfman McInnes   c->inode.limit        = a->inode.limit;
14086c7ebb05SLois Curfman McInnes   c->inode.max_limit    = a->inode.max_limit;
1409754ec7b1SSatish Balay   if (a->inode.size){
1410754ec7b1SSatish Balay     c->inode.size       = (int *) PetscMalloc( m *sizeof(int) ); CHKPTRQ(c->inode.size);
1411754ec7b1SSatish Balay     c->inode.node_count = a->inode.node_count;
1412754ec7b1SSatish Balay     PetscMemcpy( c->inode.size, a->inode.size, m*sizeof(int));
1413754ec7b1SSatish Balay   } else {
1414754ec7b1SSatish Balay     c->inode.size       = 0;
1415754ec7b1SSatish Balay     c->inode.node_count = 0;
1416754ec7b1SSatish Balay   }
1417416022c9SBarry Smith   c->assembled          = 1;
1418416022c9SBarry Smith   c->nz                 = a->nz;
1419416022c9SBarry Smith   c->maxnz              = a->maxnz;
1420416022c9SBarry Smith   c->solve_work         = 0;
142176dd722bSSatish Balay   c->spptr              = 0;      /* Dangerous -I'm throwing away a->spptr */
1422754ec7b1SSatish Balay 
1423416022c9SBarry Smith   *B = C;
142417ab2063SBarry Smith   return 0;
142517ab2063SBarry Smith }
142617ab2063SBarry Smith 
1427416022c9SBarry Smith int MatLoad_SeqAIJ(Viewer bview,MatType type,Mat *A)
142817ab2063SBarry Smith {
1429416022c9SBarry Smith   Mat_SeqAIJ   *a;
1430416022c9SBarry Smith   Mat          B;
143117699dbbSLois Curfman McInnes   int          i, nz, ierr, fd, header[4],size,*rowlengths = 0,M,N,shift;
143217ab2063SBarry Smith   PetscObject  vobj = (PetscObject) bview;
143317ab2063SBarry Smith   MPI_Comm     comm = vobj->comm;
143417ab2063SBarry Smith 
143517699dbbSLois Curfman McInnes   MPI_Comm_size(comm,&size);
143617699dbbSLois Curfman McInnes   if (size > 1) SETERRQ(1,"MatLoad_SeqAIJ:view must have one processor");
143717ab2063SBarry Smith   ierr = ViewerFileGetDescriptor_Private(bview,&fd); CHKERRQ(ierr);
1438416022c9SBarry Smith   ierr = SYRead(fd,header,4,SYINT); CHKERRQ(ierr);
143948d91487SBarry Smith   if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_SeqAIJ:not matrix object in file");
144017ab2063SBarry Smith   M = header[1]; N = header[2]; nz = header[3];
144117ab2063SBarry Smith 
144217ab2063SBarry Smith   /* read in row lengths */
14430452661fSBarry Smith   rowlengths = (int*) PetscMalloc( M*sizeof(int) ); CHKPTRQ(rowlengths);
1444416022c9SBarry Smith   ierr = SYRead(fd,rowlengths,M,SYINT); CHKERRQ(ierr);
144517ab2063SBarry Smith 
144617ab2063SBarry Smith   /* create our matrix */
1447416022c9SBarry Smith   ierr = MatCreateSeqAIJ(comm,M,N,0,rowlengths,A); CHKERRQ(ierr);
1448416022c9SBarry Smith   B = *A;
1449416022c9SBarry Smith   a = (Mat_SeqAIJ *) B->data;
1450416022c9SBarry Smith   shift = a->indexshift;
145117ab2063SBarry Smith 
145217ab2063SBarry Smith   /* read in column indices and adjust for Fortran indexing*/
1453416022c9SBarry Smith   ierr = SYRead(fd,a->j,nz,SYINT); CHKERRQ(ierr);
145417ab2063SBarry Smith   if (shift) {
145517ab2063SBarry Smith     for ( i=0; i<nz; i++ ) {
1456416022c9SBarry Smith       a->j[i] += 1;
145717ab2063SBarry Smith     }
145817ab2063SBarry Smith   }
145917ab2063SBarry Smith 
146017ab2063SBarry Smith   /* read in nonzero values */
1461416022c9SBarry Smith   ierr = SYRead(fd,a->a,nz,SYSCALAR); CHKERRQ(ierr);
146217ab2063SBarry Smith 
146317ab2063SBarry Smith   /* set matrix "i" values */
1464416022c9SBarry Smith   a->i[0] = -shift;
146517ab2063SBarry Smith   for ( i=1; i<= M; i++ ) {
1466416022c9SBarry Smith     a->i[i]      = a->i[i-1] + rowlengths[i-1];
1467416022c9SBarry Smith     a->ilen[i-1] = rowlengths[i-1];
146817ab2063SBarry Smith   }
14690452661fSBarry Smith   PetscFree(rowlengths);
147017ab2063SBarry Smith 
1471416022c9SBarry Smith   ierr = MatAssemblyBegin(B,FINAL_ASSEMBLY); CHKERRQ(ierr);
1472416022c9SBarry Smith   ierr = MatAssemblyEnd(B,FINAL_ASSEMBLY); CHKERRQ(ierr);
147317ab2063SBarry Smith   return 0;
147417ab2063SBarry Smith }
147517ab2063SBarry Smith 
147617ab2063SBarry Smith 
147717ab2063SBarry Smith 
1478