xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 76dd722b9f5340f7d2cb207df73dc90d5e00a5a5)
117ab2063SBarry Smith #ifndef lint
2*76dd722bSSatish Balay static char vcid[] = "$Id: aij.c,v 1.111 1995/11/06 19:49:26 balay Exp balay $";
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;
1917ab2063SBarry Smith 
20416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatGetReordering_SeqAIJ:Not for unassembled matrix");
2117ab2063SBarry Smith 
22a2744918SBarry Smith   /*
23a2744918SBarry Smith      this is tacky: In the future when we have written special factorization
24a2744918SBarry Smith      and solve routines for the identity permutation we should use a
25a2744918SBarry Smith      stride index set instead of the general one.
26a2744918SBarry Smith   */
27a2744918SBarry Smith   if (type  == ORDER_NATURAL) {
28a2744918SBarry Smith     n = a->n;
29a2744918SBarry Smith     idx = (int *) PetscMalloc( n*sizeof(int) ); CHKPTRQ(idx);
30a2744918SBarry Smith     for ( i=0; i<n; i++ ) idx[i] = i;
31a2744918SBarry Smith     ierr = ISCreateSeq(MPI_COMM_SELF,n,idx,rperm); CHKERRQ(ierr);
32a2744918SBarry Smith     ierr = ISCreateSeq(MPI_COMM_SELF,n,idx,cperm); CHKERRQ(ierr);
33a2744918SBarry Smith     PetscFree(idx);
34a2744918SBarry Smith     ISSetPermutation(*rperm);
35a2744918SBarry Smith     ISSetPermutation(*cperm);
36a2744918SBarry Smith     ISSetIdentity(*rperm);
37a2744918SBarry Smith     ISSetIdentity(*cperm);
38a2744918SBarry Smith     return 0;
39a2744918SBarry Smith   }
40a2744918SBarry Smith 
41416022c9SBarry Smith   ierr = MatToSymmetricIJ_SeqAIJ( a, &ia, &ja ); CHKERRQ(ierr);
42416022c9SBarry Smith   ierr = MatGetReordering_IJ(a->n,ia,ja,type,rperm,cperm); CHKERRQ(ierr);
430452661fSBarry Smith   PetscFree(ia); PetscFree(ja);
4417ab2063SBarry Smith   return 0;
4517ab2063SBarry Smith }
4617ab2063SBarry Smith 
47416022c9SBarry Smith #define CHUNKSIZE   10
4817ab2063SBarry Smith 
4917ab2063SBarry Smith /* This version has row oriented v  */
50416022c9SBarry Smith static int MatSetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is)
5117ab2063SBarry Smith {
52416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
53416022c9SBarry Smith   int        *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax, N, sorted = a->sorted;
54416022c9SBarry Smith   int        *imax = a->imax, *ai = a->i, *ailen = a->ilen;
55d5d45c9bSBarry Smith   int        *aj = a->j, nonew = a->nonew,shift = a->indexshift;
56416022c9SBarry Smith   Scalar     *ap,value, *aa = a->a;
5717ab2063SBarry Smith 
5817ab2063SBarry Smith   for ( k=0; k<m; k++ ) { /* loop over added rows */
59416022c9SBarry Smith     row  = im[k];
6017ab2063SBarry Smith     if (row < 0) SETERRQ(1,"MatSetValues_SeqAIJ:Negative row");
61416022c9SBarry Smith     if (row >= a->m) SETERRQ(1,"MatSetValues_SeqAIJ:Row too large");
6217ab2063SBarry Smith     rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
6317ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
64416022c9SBarry Smith     low = 0;
6517ab2063SBarry Smith     for ( l=0; l<n; l++ ) { /* loop over added columns */
66416022c9SBarry Smith       if (in[l] < 0) SETERRQ(1,"MatSetValues_SeqAIJ:Negative column");
67416022c9SBarry Smith       if (in[l] >= a->n) SETERRQ(1,"MatSetValues_SeqAIJ:Column too large");
68416022c9SBarry Smith       col = in[l] - shift; value = *v++;
69416022c9SBarry Smith       if (!sorted) low = 0; high = nrow;
70416022c9SBarry Smith       while (high-low > 5) {
71416022c9SBarry Smith         t = (low+high)/2;
72416022c9SBarry Smith         if (rp[t] > col) high = t;
73416022c9SBarry Smith         else             low  = t;
7417ab2063SBarry Smith       }
75416022c9SBarry Smith       for ( i=low; i<high; i++ ) {
7617ab2063SBarry Smith         if (rp[i] > col) break;
7717ab2063SBarry Smith         if (rp[i] == col) {
78416022c9SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
7917ab2063SBarry Smith           else                  ap[i] = value;
8017ab2063SBarry Smith           goto noinsert;
8117ab2063SBarry Smith         }
8217ab2063SBarry Smith       }
8317ab2063SBarry Smith       if (nonew) goto noinsert;
8417ab2063SBarry Smith       if (nrow >= rmax) {
8517ab2063SBarry Smith         /* there is no extra room in row, therefore enlarge */
86416022c9SBarry Smith         int    new_nz = ai[a->m] + CHUNKSIZE,len,*new_i,*new_j;
8717ab2063SBarry Smith         Scalar *new_a;
8817ab2063SBarry Smith 
8917ab2063SBarry Smith         /* malloc new storage space */
90416022c9SBarry Smith         len     = new_nz*(sizeof(int)+sizeof(Scalar))+(a->m+1)*sizeof(int);
910452661fSBarry Smith         new_a   = (Scalar *) PetscMalloc( len ); CHKPTRQ(new_a);
9217ab2063SBarry Smith         new_j   = (int *) (new_a + new_nz);
9317ab2063SBarry Smith         new_i   = new_j + new_nz;
9417ab2063SBarry Smith 
9517ab2063SBarry Smith         /* copy over old data into new slots */
9617ab2063SBarry Smith         for ( ii=0; ii<row+1; ii++ ) {new_i[ii] = ai[ii];}
97416022c9SBarry Smith         for ( ii=row+1; ii<a->m+1; ii++ ) {new_i[ii] = ai[ii]+CHUNKSIZE;}
98416022c9SBarry Smith         PetscMemcpy(new_j,aj,(ai[row]+nrow+shift)*sizeof(int));
99416022c9SBarry Smith         len = (new_nz - CHUNKSIZE - ai[row] - nrow - shift);
100416022c9SBarry Smith         PetscMemcpy(new_j+ai[row]+shift+nrow+CHUNKSIZE,aj+ai[row]+shift+nrow,
10117ab2063SBarry Smith                                                            len*sizeof(int));
102416022c9SBarry Smith         PetscMemcpy(new_a,aa,(ai[row]+nrow+shift)*sizeof(Scalar));
103416022c9SBarry Smith         PetscMemcpy(new_a+ai[row]+shift+nrow+CHUNKSIZE,aa+ai[row]+shift+nrow,
10417ab2063SBarry Smith                                                            len*sizeof(Scalar));
10517ab2063SBarry Smith         /* free up old matrix storage */
1060452661fSBarry Smith         PetscFree(a->a);
1070452661fSBarry Smith         if (!a->singlemalloc) {PetscFree(a->i);PetscFree(a->j);}
108416022c9SBarry Smith         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
109416022c9SBarry Smith         a->singlemalloc = 1;
11017ab2063SBarry Smith 
11117ab2063SBarry Smith         rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
112416022c9SBarry Smith         rmax = imax[row] = imax[row] + CHUNKSIZE;
113416022c9SBarry Smith         PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + sizeof(Scalar)));
114416022c9SBarry Smith         a->maxnz += CHUNKSIZE;
11517ab2063SBarry Smith       }
116416022c9SBarry Smith       N = nrow++ - 1; a->nz++;
117416022c9SBarry Smith       /* shift up all the later entries in this row */
118416022c9SBarry Smith       for ( ii=N; ii>=i; ii-- ) {
11917ab2063SBarry Smith         rp[ii+1] = rp[ii];
12017ab2063SBarry Smith         ap[ii+1] = ap[ii];
12117ab2063SBarry Smith       }
12217ab2063SBarry Smith       rp[i] = col;
12317ab2063SBarry Smith       ap[i] = value;
12417ab2063SBarry Smith       noinsert:;
125416022c9SBarry Smith       low = i + 1;
12617ab2063SBarry Smith     }
12717ab2063SBarry Smith     ailen[row] = nrow;
12817ab2063SBarry Smith   }
12917ab2063SBarry Smith   return 0;
13017ab2063SBarry Smith }
13117ab2063SBarry Smith 
13217ab2063SBarry Smith #include "draw.h"
13317ab2063SBarry Smith #include "pinclude/pviewer.h"
134416022c9SBarry Smith #include "sysio.h"
13517ab2063SBarry Smith 
136416022c9SBarry Smith static int MatView_SeqAIJ_Binary(Mat A,Viewer viewer)
13717ab2063SBarry Smith {
138416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
139416022c9SBarry Smith   int        i, fd, *col_lens, ierr;
14017ab2063SBarry Smith 
141416022c9SBarry Smith   ierr = ViewerFileGetDescriptor_Private(viewer,&fd); CHKERRQ(ierr);
1420452661fSBarry Smith   col_lens = (int *) PetscMalloc( (4+a->m)*sizeof(int) ); CHKPTRQ(col_lens);
143416022c9SBarry Smith   col_lens[0] = MAT_COOKIE;
144416022c9SBarry Smith   col_lens[1] = a->m;
145416022c9SBarry Smith   col_lens[2] = a->n;
146416022c9SBarry Smith   col_lens[3] = a->nz;
147416022c9SBarry Smith 
148416022c9SBarry Smith   /* store lengths of each row and write (including header) to file */
149416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
150416022c9SBarry Smith     col_lens[4+i] = a->i[i+1] - a->i[i];
15117ab2063SBarry Smith   }
152416022c9SBarry Smith   ierr = SYWrite(fd,col_lens,4+a->m,SYINT,1); CHKERRQ(ierr);
1530452661fSBarry Smith   PetscFree(col_lens);
154416022c9SBarry Smith 
155416022c9SBarry Smith   /* store column indices (zero start index) */
156416022c9SBarry Smith   if (a->indexshift) {
157416022c9SBarry Smith     for ( i=0; i<a->nz; i++ ) a->j[i]--;
15817ab2063SBarry Smith   }
159416022c9SBarry Smith   ierr = SYWrite(fd,a->j,a->nz,SYINT,0); CHKERRQ(ierr);
160416022c9SBarry Smith   if (a->indexshift) {
161416022c9SBarry Smith     for ( i=0; i<a->nz; i++ ) a->j[i]++;
16217ab2063SBarry Smith   }
163416022c9SBarry Smith 
164416022c9SBarry Smith   /* store nonzero values */
165416022c9SBarry Smith   ierr = SYWrite(fd,a->a,a->nz,SYSCALAR,0); CHKERRQ(ierr);
16617ab2063SBarry Smith   return 0;
16717ab2063SBarry Smith }
168416022c9SBarry Smith 
169416022c9SBarry Smith static int MatView_SeqAIJ_ASCII(Mat A,Viewer viewer)
170416022c9SBarry Smith {
171416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ *) A->data;
172416022c9SBarry Smith   int         ierr, i,j, m = a->m, shift = a->indexshift,format;
17317ab2063SBarry Smith   FILE        *fd;
17417ab2063SBarry Smith   char        *outputname;
17517ab2063SBarry Smith 
176416022c9SBarry Smith   ierr = ViewerFileGetPointer_Private(viewer,&fd); CHKERRQ(ierr);
177416022c9SBarry Smith   ierr = ViewerFileGetOutputname_Private(viewer,&outputname); CHKERRQ(ierr);
178416022c9SBarry Smith   ierr = ViewerFileGetFormat_Private(viewer,&format);
17917ab2063SBarry Smith   if (format == FILE_FORMAT_INFO) {
18008480c60SBarry Smith     /* no need to print additional information */ ;
18117ab2063SBarry Smith   }
18217ab2063SBarry Smith   else if (format == FILE_FORMAT_MATLAB) {
18317ab2063SBarry Smith     int nz, nzalloc, mem;
184416022c9SBarry Smith     MatGetInfo(A,MAT_LOCAL,&nz,&nzalloc,&mem);
185416022c9SBarry Smith     fprintf(fd,"%% Size = %d %d \n",m,a->n);
18617ab2063SBarry Smith     fprintf(fd,"%% Nonzeros = %d \n",nz);
18717ab2063SBarry Smith     fprintf(fd,"zzz = zeros(%d,3);\n",nz);
18817ab2063SBarry Smith     fprintf(fd,"zzz = [\n");
18917ab2063SBarry Smith 
19017ab2063SBarry Smith     for (i=0; i<m; i++) {
191416022c9SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
19217ab2063SBarry Smith #if defined(PETSC_COMPLEX)
193416022c9SBarry Smith         fprintf(fd,"%d %d  %18.16e  %18.16e \n",i+1,a->j[j],real(a->a[j]),
194416022c9SBarry Smith                    imag(a->a[j]));
19517ab2063SBarry Smith #else
196416022c9SBarry Smith         fprintf(fd,"%d %d  %18.16e\n", i+1, a->j[j], a->a[j]);
19717ab2063SBarry Smith #endif
19817ab2063SBarry Smith       }
19917ab2063SBarry Smith     }
20017ab2063SBarry Smith     fprintf(fd,"];\n %s = spconvert(zzz);\n",outputname);
20117ab2063SBarry Smith   }
20217ab2063SBarry Smith   else {
20317ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
20417ab2063SBarry Smith       fprintf(fd,"row %d:",i);
205416022c9SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
20617ab2063SBarry Smith #if defined(PETSC_COMPLEX)
207416022c9SBarry Smith         if (imag(a->a[j]) != 0.0) {
208416022c9SBarry Smith           fprintf(fd," %d %g + %g i",a->j[j]+shift,real(a->a[j]),imag(a->a[j]));
20917ab2063SBarry Smith         }
21017ab2063SBarry Smith         else {
211416022c9SBarry Smith           fprintf(fd," %d %g ",a->j[j]+shift,real(a->a[j]));
21217ab2063SBarry Smith         }
21317ab2063SBarry Smith #else
214416022c9SBarry Smith         fprintf(fd," %d %g ",a->j[j]+shift,a->a[j]);
21517ab2063SBarry Smith #endif
21617ab2063SBarry Smith       }
21717ab2063SBarry Smith       fprintf(fd,"\n");
21817ab2063SBarry Smith     }
21917ab2063SBarry Smith   }
22017ab2063SBarry Smith   fflush(fd);
221416022c9SBarry Smith   return 0;
222416022c9SBarry Smith }
223416022c9SBarry Smith 
224416022c9SBarry Smith static int MatView_SeqAIJ_Draw(Mat A,Viewer viewer)
225416022c9SBarry Smith {
226416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ *) A->data;
227cddf8d76SBarry Smith   int         ierr, i,j, m = a->m, shift = a->indexshift,pause,color;
228cddf8d76SBarry Smith   double      xl,yl,xr,yr,w,h,xc,yc,scale = 1.0,x_l,x_r,y_l,y_r;
229416022c9SBarry Smith   DrawCtx     draw = (DrawCtx) viewer;
230cddf8d76SBarry Smith   DrawButton  button;
231cddf8d76SBarry Smith 
232416022c9SBarry Smith   xr  = a->n; yr = a->m; h = yr/10.0; w = xr/10.0;
233416022c9SBarry Smith   xr += w;    yr += h;  xl = -w;     yl = -h;
234416022c9SBarry Smith   ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
235416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
236cddf8d76SBarry Smith   color = DRAW_BLUE;
237416022c9SBarry Smith   for ( i=0; i<m; i++ ) {
238cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
239416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
240cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
241cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
242cddf8d76SBarry Smith       if (real(a->a[j]) >=  0.) continue;
243cddf8d76SBarry Smith #else
244cddf8d76SBarry Smith       if (a->a[j] >=  0.) continue;
245cddf8d76SBarry Smith #endif
246cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
247cddf8d76SBarry Smith     }
248cddf8d76SBarry Smith   }
249cddf8d76SBarry Smith   color = DRAW_CYAN;
250cddf8d76SBarry Smith   for ( i=0; i<m; i++ ) {
251cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
252cddf8d76SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
253cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
254cddf8d76SBarry Smith       if (a->a[j] !=  0.) continue;
255cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
256cddf8d76SBarry Smith     }
257cddf8d76SBarry Smith   }
258cddf8d76SBarry Smith   color = DRAW_RED;
259cddf8d76SBarry Smith   for ( i=0; i<m; i++ ) {
260cddf8d76SBarry Smith     y_l = m - i - 1.0; y_r = y_l + 1.0;
261cddf8d76SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
262cddf8d76SBarry Smith       x_l = a->j[j] + shift; x_r = x_l + 1.0;
263cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
264cddf8d76SBarry Smith       if (real(a->a[j]) <=  0.) continue;
265cddf8d76SBarry Smith #else
266cddf8d76SBarry Smith       if (a->a[j] <=  0.) continue;
267cddf8d76SBarry Smith #endif
268cddf8d76SBarry Smith       DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
269416022c9SBarry Smith     }
270416022c9SBarry Smith   }
271416022c9SBarry Smith   DrawFlush(draw);
272cddf8d76SBarry Smith   DrawGetPause(draw,&pause);
273cddf8d76SBarry Smith   if (pause >= 0) { PetscSleep(pause); return 0;}
274cddf8d76SBarry Smith 
275cddf8d76SBarry Smith   /* allow the matrix to zoom or shrink */
276cddf8d76SBarry Smith   ierr = DrawGetMouseButton(draw,&button,&xc,&yc,0,0);
277cddf8d76SBarry Smith   while (button != BUTTON_RIGHT) {
278cddf8d76SBarry Smith     DrawClear(draw);
279cddf8d76SBarry Smith     if (button == BUTTON_LEFT) scale = .5;
280cddf8d76SBarry Smith     else if (button == BUTTON_CENTER) scale = 2.;
281cddf8d76SBarry Smith     xl = scale*(xl + w - xc) + xc - w*scale;
282cddf8d76SBarry Smith     xr = scale*(xr - w - xc) + xc + w*scale;
283cddf8d76SBarry Smith     yl = scale*(yl + h - yc) + yc - h*scale;
284cddf8d76SBarry Smith     yr = scale*(yr - h - yc) + yc + h*scale;
285cddf8d76SBarry Smith     w *= scale; h *= scale;
286cddf8d76SBarry Smith     ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
287cddf8d76SBarry Smith     color = DRAW_BLUE;
288cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
289cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
290cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
291cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
292cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
293cddf8d76SBarry Smith         if (real(a->a[j]) >=  0.) continue;
294cddf8d76SBarry Smith #else
295cddf8d76SBarry Smith         if (a->a[j] >=  0.) continue;
296cddf8d76SBarry Smith #endif
297cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
298cddf8d76SBarry Smith       }
299cddf8d76SBarry Smith     }
300cddf8d76SBarry Smith     color = DRAW_CYAN;
301cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
302cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
303cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
304cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
305cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
306cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
307cddf8d76SBarry Smith       }
308cddf8d76SBarry Smith     }
309cddf8d76SBarry Smith     color = DRAW_RED;
310cddf8d76SBarry Smith     for ( i=0; i<m; i++ ) {
311cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
312cddf8d76SBarry Smith       for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
313cddf8d76SBarry Smith         x_l = a->j[j] + shift; x_r = x_l + 1.0;
314cddf8d76SBarry Smith #if defined(PETSC_COMPLEX)
315cddf8d76SBarry Smith         if (real(a->a[j]) <=  0.) continue;
316cddf8d76SBarry Smith #else
317cddf8d76SBarry Smith         if (a->a[j] <=  0.) continue;
318cddf8d76SBarry Smith #endif
319cddf8d76SBarry Smith         DrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);
320cddf8d76SBarry Smith       }
321cddf8d76SBarry Smith     }
322cddf8d76SBarry Smith     ierr = DrawGetMouseButton(draw,&button,&xc,&yc,0,0);
323cddf8d76SBarry Smith   }
324416022c9SBarry Smith   return 0;
325416022c9SBarry Smith }
326416022c9SBarry Smith 
327416022c9SBarry Smith static int MatView_SeqAIJ(PetscObject obj,Viewer viewer)
328416022c9SBarry Smith {
329416022c9SBarry Smith   Mat         A = (Mat) obj;
330416022c9SBarry Smith   Mat_SeqAIJ  *a = (Mat_SeqAIJ*) A->data;
331416022c9SBarry Smith   PetscObject vobj = (PetscObject) viewer;
332416022c9SBarry Smith 
333416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatView_SeqAIJ:Not for unassembled matrix");
334416022c9SBarry Smith   if (!viewer) {
335416022c9SBarry Smith     viewer = STDOUT_VIEWER_SELF; vobj = (PetscObject) viewer;
336416022c9SBarry Smith   }
337416022c9SBarry Smith   if (vobj->cookie == VIEWER_COOKIE) {
338416022c9SBarry Smith     if (vobj->type == MATLAB_VIEWER) {
339416022c9SBarry Smith       return ViewerMatlabPutSparse_Private(viewer,a->m,a->n,a->nz,a->a,a->i,a->j);
340416022c9SBarry Smith     }
341416022c9SBarry Smith     else if (vobj->type == ASCII_FILE_VIEWER || vobj->type == ASCII_FILES_VIEWER){
342416022c9SBarry Smith       return MatView_SeqAIJ_ASCII(A,viewer);
343416022c9SBarry Smith     }
344416022c9SBarry Smith     else if (vobj->type == BINARY_FILE_VIEWER) {
345416022c9SBarry Smith       return MatView_SeqAIJ_Binary(A,viewer);
346416022c9SBarry Smith     }
347416022c9SBarry Smith   }
348416022c9SBarry Smith   else if (vobj->cookie == DRAW_COOKIE) {
349416022c9SBarry Smith     if (vobj->type == NULLWINDOW) return 0;
350416022c9SBarry Smith     else return MatView_SeqAIJ_Draw(A,viewer);
35117ab2063SBarry Smith   }
35217ab2063SBarry Smith   return 0;
35317ab2063SBarry Smith }
35417ab2063SBarry Smith 
355416022c9SBarry Smith static int MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
35617ab2063SBarry Smith {
357416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
358416022c9SBarry Smith   int        fshift = 0,i,j,*ai = a->i, *aj = a->j, *imax = a->imax;
359416022c9SBarry Smith   int        m = a->m, *ip, N, *ailen = a->ilen,shift = a->indexshift;
360416022c9SBarry Smith   Scalar     *aa = a->a, *ap;
36117ab2063SBarry Smith 
36217ab2063SBarry Smith   if (mode == FLUSH_ASSEMBLY) return 0;
36317ab2063SBarry Smith 
36417ab2063SBarry Smith   for ( i=1; i<m; i++ ) {
365416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
36617ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
36717ab2063SBarry Smith     if (fshift) {
368416022c9SBarry Smith       ip = aj + ai[i] + shift; ap = aa + ai[i] + shift;
36917ab2063SBarry Smith       N = ailen[i];
37017ab2063SBarry Smith       for ( j=0; j<N; j++ ) {
37117ab2063SBarry Smith         ip[j-fshift] = ip[j];
37217ab2063SBarry Smith         ap[j-fshift] = ap[j];
37317ab2063SBarry Smith       }
37417ab2063SBarry Smith     }
37517ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
37617ab2063SBarry Smith   }
37717ab2063SBarry Smith   if (m) {
37817ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
37917ab2063SBarry Smith     ai[m] = ai[m-1] + ailen[m-1];
38017ab2063SBarry Smith   }
38117ab2063SBarry Smith   /* reset ilen and imax for each row */
38217ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
38317ab2063SBarry Smith     ailen[i] = imax[i] = ai[i+1] - ai[i];
38417ab2063SBarry Smith   }
385416022c9SBarry Smith   a->nz = ai[m] + shift;
38617ab2063SBarry Smith 
38717ab2063SBarry Smith   /* diagonals may have moved, so kill the diagonal pointers */
388416022c9SBarry Smith   if (fshift && a->diag) {
3890452661fSBarry Smith     PetscFree(a->diag);
390416022c9SBarry Smith     PLogObjectMemory(A,-(m+1)*sizeof(int));
391416022c9SBarry Smith     a->diag = 0;
39217ab2063SBarry Smith   }
393*76dd722bSSatish Balay   /* check out for identical nodes. If found,use inode functions*/
394*76dd722bSSatish Balay   ierr = Mat_SeqAIJ_CheckInode(A); CHKERRQ(ierr);
395416022c9SBarry Smith   a->assembled = 1;
39617ab2063SBarry Smith   return 0;
39717ab2063SBarry Smith }
39817ab2063SBarry Smith 
399416022c9SBarry Smith static int MatZeroEntries_SeqAIJ(Mat A)
40017ab2063SBarry Smith {
401416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
402cddf8d76SBarry Smith   PetscMemzero(a->a,(a->i[a->m]+a->indexshift)*sizeof(Scalar));
40317ab2063SBarry Smith   return 0;
40417ab2063SBarry Smith }
405416022c9SBarry Smith 
40617ab2063SBarry Smith int MatDestroy_SeqAIJ(PetscObject obj)
40717ab2063SBarry Smith {
408416022c9SBarry Smith   Mat        A  = (Mat) obj;
409416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
410d5d45c9bSBarry Smith 
41117ab2063SBarry Smith #if defined(PETSC_LOG)
412416022c9SBarry Smith   PLogObjectState(obj,"Rows=%d, Cols=%d, NZ=%d",a->m,a->n,a->nz);
41317ab2063SBarry Smith #endif
4140452661fSBarry Smith   PetscFree(a->a);
4150452661fSBarry Smith   if (!a->singlemalloc) { PetscFree(a->i); PetscFree(a->j);}
4160452661fSBarry Smith   if (a->diag) PetscFree(a->diag);
4170452661fSBarry Smith   if (a->ilen) PetscFree(a->ilen);
4180452661fSBarry Smith   if (a->imax) PetscFree(a->imax);
4190452661fSBarry Smith   if (a->solve_work) PetscFree(a->solve_work);
420*76dd722bSSatish Balay   if (a->inode.size) PetscFree(a->inode.size);
4210452661fSBarry Smith   PetscFree(a);
422416022c9SBarry Smith   PLogObjectDestroy(A);
4230452661fSBarry Smith   PetscHeaderDestroy(A);
42417ab2063SBarry Smith   return 0;
42517ab2063SBarry Smith }
42617ab2063SBarry Smith 
427416022c9SBarry Smith static int MatCompress_SeqAIJ(Mat A)
42817ab2063SBarry Smith {
42917ab2063SBarry Smith   return 0;
43017ab2063SBarry Smith }
43117ab2063SBarry Smith 
432416022c9SBarry Smith static int MatSetOption_SeqAIJ(Mat A,MatOption op)
43317ab2063SBarry Smith {
434416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
435416022c9SBarry Smith   if      (op == ROW_ORIENTED)              a->roworiented = 1;
436416022c9SBarry Smith   else if (op == COLUMNS_SORTED)            a->sorted      = 1;
437416022c9SBarry Smith   else if (op == NO_NEW_NONZERO_LOCATIONS)  a->nonew       = 1;
438416022c9SBarry Smith   else if (op == YES_NEW_NONZERO_LOCATIONS) a->nonew       = 0;
439e2f28af5SBarry Smith   else if (op == ROWS_SORTED ||
440e2f28af5SBarry Smith            op == SYMMETRIC_MATRIX ||
441e2f28af5SBarry Smith            op == STRUCTURALLY_SYMMETRIC_MATRIX ||
442e2f28af5SBarry Smith            op == YES_NEW_DIAGONALS)
443df719601SLois Curfman McInnes     PLogInfo((PetscObject)A,"Info:MatSetOption_SeqAIJ:Option ignored\n");
444df719601SLois Curfman McInnes   else if (op == COLUMN_ORIENTED)
4454d39ef84SLois Curfman McInnes     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqAIJ:COLUMN_ORIENTED");}
446df719601SLois Curfman McInnes   else if (op == NO_NEW_DIAGONALS)
4474d39ef84SLois Curfman McInnes     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqAIJ:NO_NEW_DIAGONALS");}
448e2f28af5SBarry Smith   else
4494d39ef84SLois Curfman McInnes     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqAIJ:unknown option");}
45017ab2063SBarry Smith   return 0;
45117ab2063SBarry Smith }
45217ab2063SBarry Smith 
453416022c9SBarry Smith static int MatGetDiagonal_SeqAIJ(Mat A,Vec v)
45417ab2063SBarry Smith {
455416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
456416022c9SBarry Smith   int        i,j, n,shift = a->indexshift;
45717ab2063SBarry Smith   Scalar     *x, zero = 0.0;
45817ab2063SBarry Smith 
459416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatGetDiagonal_SeqAIJ:Not for unassembled matrix");
46017ab2063SBarry Smith   VecSet(&zero,v);
46117ab2063SBarry Smith   VecGetArray(v,&x); VecGetLocalSize(v,&n);
462416022c9SBarry Smith   if (n != a->m) SETERRQ(1,"MatGetDiagonal_SeqAIJ:Nonconforming matrix and vector");
463416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
464416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
465416022c9SBarry Smith       if (a->j[j]+shift == i) {
466416022c9SBarry Smith         x[i] = a->a[j];
46717ab2063SBarry Smith         break;
46817ab2063SBarry Smith       }
46917ab2063SBarry Smith     }
47017ab2063SBarry Smith   }
47117ab2063SBarry Smith   return 0;
47217ab2063SBarry Smith }
47317ab2063SBarry Smith 
47417ab2063SBarry Smith /* -------------------------------------------------------*/
47517ab2063SBarry Smith /* Should check that shapes of vectors and matrices match */
47617ab2063SBarry Smith /* -------------------------------------------------------*/
477416022c9SBarry Smith static int MatMultTrans_SeqAIJ(Mat A,Vec xx,Vec yy)
47817ab2063SBarry Smith {
479416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
48017ab2063SBarry Smith   Scalar     *x, *y, *v, alpha;
481416022c9SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift;
48217ab2063SBarry Smith 
483416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatMultTrans_SeqAIJ:Not for unassembled matrix");
48417ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
485cddf8d76SBarry Smith   PetscMemzero(y,a->n*sizeof(Scalar));
48617ab2063SBarry Smith   y = y + shift; /* shift for Fortran start by 1 indexing */
48717ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
488416022c9SBarry Smith     idx   = a->j + a->i[i] + shift;
489416022c9SBarry Smith     v     = a->a + a->i[i] + shift;
490416022c9SBarry Smith     n     = a->i[i+1] - a->i[i];
49117ab2063SBarry Smith     alpha = x[i];
49217ab2063SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
49317ab2063SBarry Smith   }
494416022c9SBarry Smith   PLogFlops(2*a->nz - a->n);
49517ab2063SBarry Smith   return 0;
49617ab2063SBarry Smith }
497d5d45c9bSBarry Smith 
498416022c9SBarry Smith static int MatMultTransAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
49917ab2063SBarry Smith {
500416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
50117ab2063SBarry Smith   Scalar     *x, *y, *v, alpha;
502416022c9SBarry Smith   int        m = a->m, n, i, *idx,shift = a->indexshift;
50317ab2063SBarry Smith 
504416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatMultTransAdd_SeqAIJ:Not for unassembled matrix");
50517ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
50617ab2063SBarry Smith   if (zz != yy) VecCopy(zz,yy);
50717ab2063SBarry Smith   y = y + shift; /* shift for Fortran start by 1 indexing */
50817ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
509416022c9SBarry Smith     idx   = a->j + a->i[i] + shift;
510416022c9SBarry Smith     v     = a->a + a->i[i] + shift;
511416022c9SBarry Smith     n     = a->i[i+1] - a->i[i];
51217ab2063SBarry Smith     alpha = x[i];
51317ab2063SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
51417ab2063SBarry Smith   }
51517ab2063SBarry Smith   return 0;
51617ab2063SBarry Smith }
51717ab2063SBarry Smith 
518416022c9SBarry Smith static int MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
51917ab2063SBarry Smith {
520416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
52117ab2063SBarry Smith   Scalar     *x, *y, *v, sum;
522416022c9SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift,*ii;
52317ab2063SBarry Smith 
524416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatMult_SeqAIJ:Not for unassembled matrix");
52517ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
52617ab2063SBarry Smith   x    = x + shift; /* shift for Fortran start by 1 indexing */
527416022c9SBarry Smith   idx  = a->j;
528416022c9SBarry Smith   v    = a->a;
529416022c9SBarry Smith   ii   = a->i;
53017ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
531416022c9SBarry Smith     n    = ii[1] - ii[0]; ii++;
53217ab2063SBarry Smith     sum  = 0.0;
53317ab2063SBarry Smith     /* SPARSEDENSEDOT(sum,x,v,idx,n);  */
53417ab2063SBarry Smith     /* for ( j=n-1; j>-1; j--) sum += v[j]*x[idx[j]]; */
535416022c9SBarry Smith     while (n--) sum += *v++ * x[*idx++];
53617ab2063SBarry Smith     y[i] = sum;
53717ab2063SBarry Smith   }
538416022c9SBarry Smith   PLogFlops(2*a->nz - m);
53917ab2063SBarry Smith   return 0;
54017ab2063SBarry Smith }
54117ab2063SBarry Smith 
542416022c9SBarry Smith static int MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
54317ab2063SBarry Smith {
544416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
54517ab2063SBarry Smith   Scalar     *x, *y, *z, *v, sum;
546cddf8d76SBarry Smith   int        m = a->m, n, i, *idx, shift = a->indexshift,*ii;
54717ab2063SBarry Smith 
54848d91487SBarry Smith   if (!a->assembled) SETERRQ(1,"MatMultAdd_SeqAIJ:Not for unassembled matrix");
54917ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z);
55017ab2063SBarry Smith   x    = x + shift; /* shift for Fortran start by 1 indexing */
551cddf8d76SBarry Smith   idx  = a->j;
552cddf8d76SBarry Smith   v    = a->a;
553cddf8d76SBarry Smith   ii   = a->i;
55417ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
555cddf8d76SBarry Smith     n    = ii[1] - ii[0]; ii++;
55617ab2063SBarry Smith     sum  = y[i];
557cddf8d76SBarry Smith     /* SPARSEDENSEDOT(sum,x,v,idx,n);  */
558cddf8d76SBarry Smith     while (n--) sum += *v++ * x[*idx++];
55917ab2063SBarry Smith     z[i] = sum;
56017ab2063SBarry Smith   }
561416022c9SBarry Smith   PLogFlops(2*a->nz);
56217ab2063SBarry Smith   return 0;
56317ab2063SBarry Smith }
56417ab2063SBarry Smith 
56517ab2063SBarry Smith /*
56617ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
56717ab2063SBarry Smith */
56817ab2063SBarry Smith 
569416022c9SBarry Smith int MatMarkDiag_SeqAIJ(Mat A)
57017ab2063SBarry Smith {
571416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
572416022c9SBarry Smith   int        i,j, *diag, m = a->m,shift = a->indexshift;
57317ab2063SBarry Smith 
574416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatMarkDiag_SeqAIJ:unassembled matrix");
5750452661fSBarry Smith   diag = (int *) PetscMalloc( (m+1)*sizeof(int)); CHKPTRQ(diag);
576416022c9SBarry Smith   PLogObjectMemory(A,(m+1)*sizeof(int));
577416022c9SBarry Smith   for ( i=0; i<a->m; i++ ) {
578416022c9SBarry Smith     for ( j=a->i[i]+shift; j<a->i[i+1]+shift; j++ ) {
579416022c9SBarry Smith       if (a->j[j]+shift == i) {
58017ab2063SBarry Smith         diag[i] = j - shift;
58117ab2063SBarry Smith         break;
58217ab2063SBarry Smith       }
58317ab2063SBarry Smith     }
58417ab2063SBarry Smith   }
585416022c9SBarry Smith   a->diag = diag;
58617ab2063SBarry Smith   return 0;
58717ab2063SBarry Smith }
58817ab2063SBarry Smith 
589416022c9SBarry Smith static int MatRelax_SeqAIJ(Mat A,Vec bb,double omega,MatSORType flag,
59017ab2063SBarry Smith                            double fshift,int its,Vec xx)
59117ab2063SBarry Smith {
592416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
593416022c9SBarry Smith   Scalar     *x, *b, *bs,  d, *xs, sum, *v = a->a,*t,scale,*ts, *xb;
594d5d45c9bSBarry Smith   int        ierr, *idx, *diag,n = a->n, m = a->m, i, shift = a->indexshift;
59517ab2063SBarry Smith 
59617ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(bb,&b);
597416022c9SBarry Smith   if (!a->diag) {if ((ierr = MatMarkDiag_SeqAIJ(A))) return ierr;}
598416022c9SBarry Smith   diag = a->diag;
599416022c9SBarry Smith   xs   = x + shift; /* shifted by one for index start of a or a->j*/
60017ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
60117ab2063SBarry Smith    /* apply ( U + D/omega) to the vector */
60217ab2063SBarry Smith     bs = b + shift;
60317ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
604416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
605416022c9SBarry Smith         n    = a->i[i+1] - diag[i] - 1;
606416022c9SBarry Smith         idx  = a->j + diag[i] + (!shift);
607416022c9SBarry Smith         v    = a->a + diag[i] + (!shift);
60817ab2063SBarry Smith         sum  = b[i]*d/omega;
60917ab2063SBarry Smith         SPARSEDENSEDOT(sum,bs,v,idx,n);
61017ab2063SBarry Smith         x[i] = sum;
61117ab2063SBarry Smith     }
61217ab2063SBarry Smith     return 0;
61317ab2063SBarry Smith   }
61417ab2063SBarry Smith   if (flag == SOR_APPLY_LOWER) {
61517ab2063SBarry Smith     SETERRQ(1,"MatRelax_SeqAIJ:SOR_APPLY_LOWER is not done");
61617ab2063SBarry Smith   }
617416022c9SBarry Smith   else if (flag & SOR_EISENSTAT) {
61817ab2063SBarry Smith     /* Let  A = L + U + D; where L is lower trianglar,
61917ab2063SBarry Smith     U is upper triangular, E is diagonal; This routine applies
62017ab2063SBarry Smith 
62117ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
62217ab2063SBarry Smith 
62317ab2063SBarry Smith     to a vector efficiently using Eisenstat's trick. This is for
62417ab2063SBarry Smith     the case of SSOR preconditioner, so E is D/omega where omega
62517ab2063SBarry Smith     is the relaxation factor.
62617ab2063SBarry Smith     */
6270452661fSBarry Smith     t = (Scalar *) PetscMalloc( m*sizeof(Scalar) ); CHKPTRQ(t);
62817ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
62917ab2063SBarry Smith 
63017ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
63117ab2063SBarry Smith     for ( i=m-1; i>=0; i-- ) {
632416022c9SBarry Smith       d    = fshift + a->a[diag[i] + shift];
633416022c9SBarry Smith       n    = a->i[i+1] - diag[i] - 1;
634416022c9SBarry Smith       idx  = a->j + diag[i] + (!shift);
635416022c9SBarry Smith       v    = a->a + diag[i] + (!shift);
63617ab2063SBarry Smith       sum  = b[i];
63717ab2063SBarry Smith       SPARSEDENSEMDOT(sum,xs,v,idx,n);
63817ab2063SBarry Smith       x[i] = omega*(sum/d);
63917ab2063SBarry Smith     }
64017ab2063SBarry Smith 
64117ab2063SBarry Smith     /*  t = b - (2*E - D)x */
642416022c9SBarry Smith     v = a->a;
64317ab2063SBarry Smith     for ( i=0; i<m; i++ ) { t[i] = b[i] - scale*(v[*diag++ + shift])*x[i]; }
64417ab2063SBarry Smith 
64517ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
646416022c9SBarry Smith     ts = t + shift; /* shifted by one for index start of a or a->j*/
647416022c9SBarry Smith     diag = a->diag;
64817ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
649416022c9SBarry Smith       d    = fshift + a->a[diag[i]+shift];
650416022c9SBarry Smith       n    = diag[i] - a->i[i];
651416022c9SBarry Smith       idx  = a->j + a->i[i] + shift;
652416022c9SBarry Smith       v    = a->a + a->i[i] + shift;
65317ab2063SBarry Smith       sum  = t[i];
65417ab2063SBarry Smith       SPARSEDENSEMDOT(sum,ts,v,idx,n);
65517ab2063SBarry Smith       t[i] = omega*(sum/d);
65617ab2063SBarry Smith     }
65717ab2063SBarry Smith 
65817ab2063SBarry Smith     /*  x = x + t */
65917ab2063SBarry Smith     for ( i=0; i<m; i++ ) { x[i] += t[i]; }
6600452661fSBarry Smith     PetscFree(t);
66117ab2063SBarry Smith     return 0;
66217ab2063SBarry Smith   }
66317ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
66417ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
66517ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
666416022c9SBarry Smith         d    = fshift + a->a[diag[i]+shift];
667416022c9SBarry Smith         n    = diag[i] - a->i[i];
668416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
669416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
67017ab2063SBarry Smith         sum  = b[i];
67117ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
67217ab2063SBarry Smith         x[i] = omega*(sum/d);
67317ab2063SBarry Smith       }
67417ab2063SBarry Smith       xb = x;
67517ab2063SBarry Smith     }
67617ab2063SBarry Smith     else xb = b;
67717ab2063SBarry Smith     if ((flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) &&
67817ab2063SBarry Smith         (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP)) {
67917ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
680416022c9SBarry Smith         x[i] *= a->a[diag[i]+shift];
68117ab2063SBarry Smith       }
68217ab2063SBarry Smith     }
68317ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
68417ab2063SBarry Smith       for ( i=m-1; i>=0; i-- ) {
685416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
686416022c9SBarry Smith         n    = a->i[i+1] - diag[i] - 1;
687416022c9SBarry Smith         idx  = a->j + diag[i] + (!shift);
688416022c9SBarry Smith         v    = a->a + diag[i] + (!shift);
68917ab2063SBarry Smith         sum  = xb[i];
69017ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
69117ab2063SBarry Smith         x[i] = omega*(sum/d);
69217ab2063SBarry Smith       }
69317ab2063SBarry Smith     }
69417ab2063SBarry Smith     its--;
69517ab2063SBarry Smith   }
69617ab2063SBarry Smith   while (its--) {
69717ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
69817ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
699416022c9SBarry Smith         d    = fshift + a->a[diag[i]+shift];
700416022c9SBarry Smith         n    = a->i[i+1] - a->i[i];
701416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
702416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
70317ab2063SBarry Smith         sum  = b[i];
70417ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
70517ab2063SBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum/d + x[i]);
70617ab2063SBarry Smith       }
70717ab2063SBarry Smith     }
70817ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
70917ab2063SBarry Smith       for ( i=m-1; i>=0; i-- ) {
710416022c9SBarry Smith         d    = fshift + a->a[diag[i] + shift];
711416022c9SBarry Smith         n    = a->i[i+1] - a->i[i];
712416022c9SBarry Smith         idx  = a->j + a->i[i] + shift;
713416022c9SBarry Smith         v    = a->a + a->i[i] + shift;
71417ab2063SBarry Smith         sum  = b[i];
71517ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
71617ab2063SBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum/d + x[i]);
71717ab2063SBarry Smith       }
71817ab2063SBarry Smith     }
71917ab2063SBarry Smith   }
72017ab2063SBarry Smith   return 0;
72117ab2063SBarry Smith }
72217ab2063SBarry Smith 
723d5d45c9bSBarry Smith static int MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,int *nz,int *nzalloc,int *mem)
72417ab2063SBarry Smith {
725416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
726416022c9SBarry Smith   *nz      = a->nz;
727416022c9SBarry Smith   *nzalloc = a->maxnz;
728416022c9SBarry Smith   *mem     = (int)A->mem;
72917ab2063SBarry Smith   return 0;
73017ab2063SBarry Smith }
73117ab2063SBarry Smith 
73217ab2063SBarry Smith extern int MatLUFactorSymbolic_SeqAIJ(Mat,IS,IS,double,Mat*);
73317ab2063SBarry Smith extern int MatLUFactorNumeric_SeqAIJ(Mat,Mat*);
73417ab2063SBarry Smith extern int MatLUFactor_SeqAIJ(Mat,IS,IS,double);
73517ab2063SBarry Smith extern int MatSolve_SeqAIJ(Mat,Vec,Vec);
73617ab2063SBarry Smith extern int MatSolveAdd_SeqAIJ(Mat,Vec,Vec,Vec);
73717ab2063SBarry Smith extern int MatSolveTrans_SeqAIJ(Mat,Vec,Vec);
73817ab2063SBarry Smith extern int MatSolveTransAdd_SeqAIJ(Mat,Vec,Vec,Vec);
73917ab2063SBarry Smith 
74017ab2063SBarry Smith static int MatZeroRows_SeqAIJ(Mat A,IS is,Scalar *diag)
74117ab2063SBarry Smith {
742416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
743416022c9SBarry Smith   int         i,ierr,N, *rows,m = a->m - 1,shift = a->indexshift;
74417ab2063SBarry Smith 
74517ab2063SBarry Smith   ierr = ISGetLocalSize(is,&N); CHKERRQ(ierr);
74617ab2063SBarry Smith   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
74717ab2063SBarry Smith   if (diag) {
74817ab2063SBarry Smith     for ( i=0; i<N; i++ ) {
749416022c9SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ(1,"MatZeroRows_SeqAIJ:row out of range");
750416022c9SBarry Smith       if (a->ilen[rows[i]] > 0) { /* in case row was completely empty */
751416022c9SBarry Smith         a->ilen[rows[i]] = 1;
752416022c9SBarry Smith         a->a[a->i[rows[i]]+shift] = *diag;
753416022c9SBarry Smith         a->j[a->i[rows[i]]+shift] = rows[i]+shift;
75417ab2063SBarry Smith       }
75517ab2063SBarry Smith       else {
75617ab2063SBarry Smith         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],diag,INSERT_VALUES);
75717ab2063SBarry Smith         CHKERRQ(ierr);
75817ab2063SBarry Smith       }
75917ab2063SBarry Smith     }
76017ab2063SBarry Smith   }
76117ab2063SBarry Smith   else {
76217ab2063SBarry Smith     for ( i=0; i<N; i++ ) {
763416022c9SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ(1,"MatZeroRows_SeqAIJ:row out of range");
764416022c9SBarry Smith       a->ilen[rows[i]] = 0;
76517ab2063SBarry Smith     }
76617ab2063SBarry Smith   }
76717ab2063SBarry Smith   ISRestoreIndices(is,&rows);
76817ab2063SBarry Smith   ierr = MatAssemblyBegin(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
76917ab2063SBarry Smith   ierr = MatAssemblyEnd(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
77017ab2063SBarry Smith   return 0;
77117ab2063SBarry Smith }
77217ab2063SBarry Smith 
773416022c9SBarry Smith static int MatGetSize_SeqAIJ(Mat A,int *m,int *n)
77417ab2063SBarry Smith {
775416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
776416022c9SBarry Smith   *m = a->m; *n = a->n;
77717ab2063SBarry Smith   return 0;
77817ab2063SBarry Smith }
77917ab2063SBarry Smith 
780416022c9SBarry Smith static int MatGetOwnershipRange_SeqAIJ(Mat A,int *m,int *n)
78117ab2063SBarry Smith {
782416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
783416022c9SBarry Smith   *m = 0; *n = a->m;
78417ab2063SBarry Smith   return 0;
78517ab2063SBarry Smith }
786416022c9SBarry Smith static int MatGetRow_SeqAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
78717ab2063SBarry Smith {
788416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
789416022c9SBarry Smith   int        *itmp,i,ierr,shift = a->indexshift;
79017ab2063SBarry Smith 
791416022c9SBarry Smith   if (row < 0 || row >= a->m) SETERRQ(1,"MatGetRow_SeqAIJ:Row out of range");
79217ab2063SBarry Smith 
793416022c9SBarry Smith   if (!a->assembled) {
794416022c9SBarry Smith     ierr = MatAssemblyBegin(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
795416022c9SBarry Smith     ierr = MatAssemblyEnd(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
79617ab2063SBarry Smith   }
797416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
798416022c9SBarry Smith   if (v) *v = a->a + a->i[row] + shift;
79917ab2063SBarry Smith   if (idx) {
80017ab2063SBarry Smith     if (*nz) {
801416022c9SBarry Smith       itmp = a->j + a->i[row] + shift;
8020452661fSBarry Smith       *idx = (int *) PetscMalloc( (*nz)*sizeof(int) ); CHKPTRQ(*idx);
80317ab2063SBarry Smith       for ( i=0; i<(*nz); i++ ) {(*idx)[i] = itmp[i] + shift;}
80417ab2063SBarry Smith     }
80517ab2063SBarry Smith     else *idx = 0;
80617ab2063SBarry Smith   }
80717ab2063SBarry Smith   return 0;
80817ab2063SBarry Smith }
80917ab2063SBarry Smith 
810416022c9SBarry Smith static int MatRestoreRow_SeqAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
81117ab2063SBarry Smith {
8120452661fSBarry Smith   if (idx) {if (*idx) PetscFree(*idx);}
81317ab2063SBarry Smith   return 0;
81417ab2063SBarry Smith }
81517ab2063SBarry Smith 
816cddf8d76SBarry Smith static int MatNorm_SeqAIJ(Mat A,NormType type,double *norm)
81717ab2063SBarry Smith {
818416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
819416022c9SBarry Smith   Scalar     *v = a->a;
82017ab2063SBarry Smith   double     sum = 0.0;
821416022c9SBarry Smith   int        i, j,shift = a->indexshift;
82217ab2063SBarry Smith 
823416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatNorm_SeqAIJ:Not for unassembled matrix");
82417ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
825416022c9SBarry Smith     for (i=0; i<a->nz; i++ ) {
82617ab2063SBarry Smith #if defined(PETSC_COMPLEX)
82717ab2063SBarry Smith       sum += real(conj(*v)*(*v)); v++;
82817ab2063SBarry Smith #else
82917ab2063SBarry Smith       sum += (*v)*(*v); v++;
83017ab2063SBarry Smith #endif
83117ab2063SBarry Smith     }
83217ab2063SBarry Smith     *norm = sqrt(sum);
83317ab2063SBarry Smith   }
83417ab2063SBarry Smith   else if (type == NORM_1) {
83517ab2063SBarry Smith     double *tmp;
836416022c9SBarry Smith     int    *jj = a->j;
8370452661fSBarry Smith     tmp = (double *) PetscMalloc( a->n*sizeof(double) ); CHKPTRQ(tmp);
838cddf8d76SBarry Smith     PetscMemzero(tmp,a->n*sizeof(double));
83917ab2063SBarry Smith     *norm = 0.0;
840416022c9SBarry Smith     for ( j=0; j<a->nz; j++ ) {
841a2744918SBarry Smith         tmp[*jj++ + shift] += PetscAbsScalar(*v);  v++;
84217ab2063SBarry Smith     }
843416022c9SBarry Smith     for ( j=0; j<a->n; j++ ) {
84417ab2063SBarry Smith       if (tmp[j] > *norm) *norm = tmp[j];
84517ab2063SBarry Smith     }
8460452661fSBarry Smith     PetscFree(tmp);
84717ab2063SBarry Smith   }
84817ab2063SBarry Smith   else if (type == NORM_INFINITY) {
84917ab2063SBarry Smith     *norm = 0.0;
850416022c9SBarry Smith     for ( j=0; j<a->m; j++ ) {
851416022c9SBarry Smith       v = a->a + a->i[j] + shift;
85217ab2063SBarry Smith       sum = 0.0;
853416022c9SBarry Smith       for ( i=0; i<a->i[j+1]-a->i[j]; i++ ) {
854cddf8d76SBarry Smith         sum += PetscAbsScalar(*v); v++;
85517ab2063SBarry Smith       }
85617ab2063SBarry Smith       if (sum > *norm) *norm = sum;
85717ab2063SBarry Smith     }
85817ab2063SBarry Smith   }
85917ab2063SBarry Smith   else {
86048d91487SBarry Smith     SETERRQ(1,"MatNorm_SeqAIJ:No support for two norm yet");
86117ab2063SBarry Smith   }
86217ab2063SBarry Smith   return 0;
86317ab2063SBarry Smith }
86417ab2063SBarry Smith 
865416022c9SBarry Smith static int MatTranspose_SeqAIJ(Mat A,Mat *B)
86617ab2063SBarry Smith {
867416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
868416022c9SBarry Smith   Mat        C;
869416022c9SBarry Smith   int        i, ierr, *aj = a->j, *ai = a->i, m = a->m, len, *col;
870416022c9SBarry Smith   int        shift = a->indexshift;
871d5d45c9bSBarry Smith   Scalar     *array = a->a;
87217ab2063SBarry Smith 
873416022c9SBarry Smith   if (!B && m != a->n) SETERRQ(1,"MatTranspose_SeqAIJ:Not for rectangular mat in place");
8740452661fSBarry Smith   col = (int *) PetscMalloc((1+a->n)*sizeof(int)); CHKPTRQ(col);
875cddf8d76SBarry Smith   PetscMemzero(col,(1+a->n)*sizeof(int));
87617ab2063SBarry Smith   if (shift) {
87717ab2063SBarry Smith     for ( i=0; i<ai[m]-1; i++ ) aj[i] -= 1;
87817ab2063SBarry Smith   }
87917ab2063SBarry Smith   for ( i=0; i<ai[m]+shift; i++ ) col[aj[i]] += 1;
880416022c9SBarry Smith   ierr = MatCreateSeqAIJ(A->comm,a->n,m,0,col,&C); CHKERRQ(ierr);
8810452661fSBarry Smith   PetscFree(col);
88217ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
88317ab2063SBarry Smith     len = ai[i+1]-ai[i];
884416022c9SBarry Smith     ierr = MatSetValues(C,len,aj,1,&i,array,INSERT_VALUES); CHKERRQ(ierr);
88517ab2063SBarry Smith     array += len; aj += len;
88617ab2063SBarry Smith   }
88717ab2063SBarry Smith   if (shift) {
88817ab2063SBarry Smith     for ( i=0; i<ai[m]-1; i++ ) aj[i] += 1;
88917ab2063SBarry Smith   }
89017ab2063SBarry Smith 
891416022c9SBarry Smith   ierr = MatAssemblyBegin(C,FINAL_ASSEMBLY); CHKERRQ(ierr);
892416022c9SBarry Smith   ierr = MatAssemblyEnd(C,FINAL_ASSEMBLY); CHKERRQ(ierr);
89317ab2063SBarry Smith 
894416022c9SBarry Smith   if (B) {
895416022c9SBarry Smith     *B = C;
89617ab2063SBarry Smith   } else {
897416022c9SBarry Smith     /* This isn't really an in-place transpose */
8980452661fSBarry Smith     PetscFree(a->a);
8990452661fSBarry Smith     if (!a->singlemalloc) {PetscFree(a->i); PetscFree(a->j);}
9000452661fSBarry Smith     if (a->diag) PetscFree(a->diag);
9010452661fSBarry Smith     if (a->ilen) PetscFree(a->ilen);
9020452661fSBarry Smith     if (a->imax) PetscFree(a->imax);
9030452661fSBarry Smith     if (a->solve_work) PetscFree(a->solve_work);
9040452661fSBarry Smith     PetscFree(a);
905416022c9SBarry Smith     PetscMemcpy(A,C,sizeof(struct _Mat));
9060452661fSBarry Smith     PetscHeaderDestroy(C);
90717ab2063SBarry Smith   }
90817ab2063SBarry Smith   return 0;
90917ab2063SBarry Smith }
91017ab2063SBarry Smith 
911416022c9SBarry Smith static int MatScale_SeqAIJ(Mat A,Vec ll,Vec rr)
91217ab2063SBarry Smith {
913416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
91417ab2063SBarry Smith   Scalar     *l,*r,x,*v;
915d5d45c9bSBarry Smith   int        i,j,m = a->m, n = a->n, M, nz = a->nz, *jj,shift = a->indexshift;
91617ab2063SBarry Smith 
91748d91487SBarry Smith   if (!a->assembled) SETERRQ(1,"MatScale_SeqAIJ:Not for unassembled matrix");
91817ab2063SBarry Smith   if (ll) {
91917ab2063SBarry Smith     VecGetArray(ll,&l); VecGetSize(ll,&m);
920416022c9SBarry Smith     if (m != a->m) SETERRQ(1,"MatScale_SeqAIJ:Left scaling vector wrong length");
921416022c9SBarry Smith     v = a->a;
92217ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
92317ab2063SBarry Smith       x = l[i];
924416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
92517ab2063SBarry Smith       for ( j=0; j<M; j++ ) { (*v++) *= x;}
92617ab2063SBarry Smith     }
92717ab2063SBarry Smith   }
92817ab2063SBarry Smith   if (rr) {
92917ab2063SBarry Smith     VecGetArray(rr,&r); VecGetSize(rr,&n);
930416022c9SBarry Smith     if (n != a->n) SETERRQ(1,"MatScale_SeqAIJ:Right scaling vector wrong length");
931416022c9SBarry Smith     v = a->a; jj = a->j;
93217ab2063SBarry Smith     for ( i=0; i<nz; i++ ) {
93317ab2063SBarry Smith       (*v++) *= r[*jj++ + shift];
93417ab2063SBarry Smith     }
93517ab2063SBarry Smith   }
93617ab2063SBarry Smith   return 0;
93717ab2063SBarry Smith }
93817ab2063SBarry Smith 
939cddf8d76SBarry Smith static int MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,MatGetSubMatrixCall scall,Mat *B)
94017ab2063SBarry Smith {
941db02288aSLois Curfman McInnes   Mat_SeqAIJ   *a = (Mat_SeqAIJ *) A->data,*c;
94202834360SBarry Smith   int          nznew, *smap, i, k, kstart, kend, ierr, oldcols = a->n,*lens;
943a2744918SBarry Smith   register int sum,lensi;
94402834360SBarry Smith   int          *irow, *icol, nrows, ncols, *cwork, shift = a->indexshift,*ssmap;
945a2744918SBarry Smith   int          first,step,*starts,*j_new,*i_new,*aj = a->j, *ai = a->i,ii,*ailen = a->ilen;
946db02288aSLois Curfman McInnes   Scalar       *vwork,*a_new;
947416022c9SBarry Smith   Mat          C;
94817ab2063SBarry Smith 
949416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatGetSubMatrix_SeqAIJ:Not for unassembled matrix");
95017ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow); CHKERRQ(ierr);
95117ab2063SBarry Smith   ierr = ISGetSize(isrow,&nrows); CHKERRQ(ierr);
95217ab2063SBarry Smith   ierr = ISGetSize(iscol,&ncols); CHKERRQ(ierr);
95317ab2063SBarry Smith 
95402834360SBarry Smith   if (ISStrideGetInfo(iscol,&first,&step) && step == 1) {
95502834360SBarry Smith     /* special case of contiguous rows */
9560452661fSBarry Smith     lens   = (int *) PetscMalloc((2*ncols+1)*sizeof(int)); CHKPTRQ(lens);
95702834360SBarry Smith     starts = lens + ncols;
95802834360SBarry Smith     /* loop over new rows determining lens and starting points */
95902834360SBarry Smith     for (i=0; i<nrows; i++) {
960a2744918SBarry Smith       kstart  = ai[irow[i]]+shift;
961a2744918SBarry Smith       kend    = kstart + ailen[irow[i]];
96202834360SBarry Smith       for ( k=kstart; k<kend; k++ ) {
963a2744918SBarry Smith         if (aj[k] >= first) {
96402834360SBarry Smith           starts[i] = k;
96502834360SBarry Smith           break;
96602834360SBarry Smith 	}
96702834360SBarry Smith       }
968a2744918SBarry Smith       sum = 0;
96902834360SBarry Smith       while (k < kend) {
970a2744918SBarry Smith         if (aj[k++] >= first+ncols) break;
971a2744918SBarry Smith         sum++;
97202834360SBarry Smith       }
973a2744918SBarry Smith       lens[i] = sum;
97402834360SBarry Smith     }
97502834360SBarry Smith     /* create submatrix */
976cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
97708480c60SBarry Smith       int n_cols,n_rows;
97808480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols); CHKERRQ(ierr);
97908480c60SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(1,"MatGetSubMatrix_SeqAIJ:");
98008480c60SBarry Smith       MatZeroEntries(*B);
98108480c60SBarry Smith       C = *B;
98208480c60SBarry Smith     }
98308480c60SBarry Smith     else {
98402834360SBarry Smith       ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr);
98508480c60SBarry Smith     }
986db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*) C->data;
987db02288aSLois Curfman McInnes 
98802834360SBarry Smith     /* loop over rows inserting into submatrix */
989db02288aSLois Curfman McInnes     a_new    = c->a;
990db02288aSLois Curfman McInnes     j_new    = c->j;
991db02288aSLois Curfman McInnes     i_new    = c->i;
992db02288aSLois Curfman McInnes     i_new[0] = -shift;
99302834360SBarry Smith     for (i=0; i<nrows; i++) {
994a2744918SBarry Smith       ii    = starts[i];
995a2744918SBarry Smith       lensi = lens[i];
996a2744918SBarry Smith       for ( k=0; k<lensi; k++ ) {
997a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
99802834360SBarry Smith       }
999a2744918SBarry Smith       PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(Scalar));
1000a2744918SBarry Smith       a_new      += lensi;
1001a2744918SBarry Smith       i_new[i+1]  = i_new[i] + lensi;
1002a2744918SBarry Smith       c->ilen[i]  = lensi;
100302834360SBarry Smith     }
10040452661fSBarry Smith     PetscFree(lens);
100502834360SBarry Smith   }
100602834360SBarry Smith   else {
100702834360SBarry Smith     ierr = ISGetIndices(iscol,&icol); CHKERRQ(ierr);
10080452661fSBarry Smith     smap  = (int *) PetscMalloc((1+oldcols)*sizeof(int)); CHKPTRQ(smap);
100902834360SBarry Smith     ssmap = smap + shift;
10100452661fSBarry Smith     cwork = (int *) PetscMalloc((1+2*ncols)*sizeof(int)); CHKPTRQ(cwork);
101102834360SBarry Smith     lens  = cwork + ncols;
10120452661fSBarry Smith     vwork = (Scalar *) PetscMalloc((1+ncols)*sizeof(Scalar)); CHKPTRQ(vwork);
1013cddf8d76SBarry Smith     PetscMemzero(smap,oldcols*sizeof(int));
101417ab2063SBarry Smith     for ( i=0; i<ncols; i++ ) smap[icol[i]] = i+1;
101502834360SBarry Smith     /* determine lens of each row */
101602834360SBarry Smith     for (i=0; i<nrows; i++) {
101702834360SBarry Smith       kstart  = a->i[irow[i]]+shift;
101802834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
101902834360SBarry Smith       lens[i] = 0;
102002834360SBarry Smith       for ( k=kstart; k<kend; k++ ) {
102102834360SBarry Smith         if (ssmap[a->j[k]]) {
102202834360SBarry Smith           lens[i]++;
102302834360SBarry Smith         }
102402834360SBarry Smith       }
102502834360SBarry Smith     }
102617ab2063SBarry Smith     /* Create and fill new matrix */
1027a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
102808480c60SBarry Smith       int n_cols,n_rows;
102908480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols); CHKERRQ(ierr);
103008480c60SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(1,"MatGetSubMatrix_SeqAIJ:");
103108480c60SBarry Smith       MatZeroEntries(*B);
103208480c60SBarry Smith       C = *B;
103308480c60SBarry Smith     }
103408480c60SBarry Smith     else {
103502834360SBarry Smith       ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr);
103608480c60SBarry Smith     }
103717ab2063SBarry Smith     for (i=0; i<nrows; i++) {
103817ab2063SBarry Smith       nznew  = 0;
1039416022c9SBarry Smith       kstart = a->i[irow[i]]+shift;
1040416022c9SBarry Smith       kend   = kstart + a->ilen[irow[i]];
104117ab2063SBarry Smith       for ( k=kstart; k<kend; k++ ) {
104202834360SBarry Smith         if (ssmap[a->j[k]]) {
104302834360SBarry Smith           cwork[nznew]   = ssmap[a->j[k]] - 1;
1044416022c9SBarry Smith           vwork[nznew++] = a->a[k];
104517ab2063SBarry Smith         }
104617ab2063SBarry Smith       }
1047416022c9SBarry Smith       ierr = MatSetValues(C,1,&i,nznew,cwork,vwork,INSERT_VALUES); CHKERRQ(ierr);
104817ab2063SBarry Smith     }
104902834360SBarry Smith     /* Free work space */
105002834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol); CHKERRQ(ierr);
10510452661fSBarry Smith     PetscFree(smap); PetscFree(cwork); PetscFree(vwork);
105202834360SBarry Smith   }
1053416022c9SBarry Smith   ierr = MatAssemblyBegin(C,FINAL_ASSEMBLY); CHKERRQ(ierr);
1054416022c9SBarry Smith   ierr = MatAssemblyEnd(C,FINAL_ASSEMBLY); CHKERRQ(ierr);
105517ab2063SBarry Smith 
105617ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow); CHKERRQ(ierr);
1057416022c9SBarry Smith   *B = C;
105817ab2063SBarry Smith   return 0;
105917ab2063SBarry Smith }
106017ab2063SBarry Smith 
1061a871dcd8SBarry Smith /*
106263b91edcSBarry Smith      note: This can only work for identity for row and col. It would
106363b91edcSBarry Smith    be good to check this and otherwise generate an error.
1064a871dcd8SBarry Smith */
106563b91edcSBarry Smith static int MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,double efill,int fill)
1066a871dcd8SBarry Smith {
106763b91edcSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ *) inA->data;
106808480c60SBarry Smith   int        ierr;
106963b91edcSBarry Smith   Mat        outA;
107063b91edcSBarry Smith 
1071a871dcd8SBarry Smith   if (fill != 0) SETERRQ(1,"MatILUFactor_SeqAIJ:Only fill=0 supported");
1072a871dcd8SBarry Smith 
107363b91edcSBarry Smith   outA          = inA;
107463b91edcSBarry Smith   inA->factor   = FACTOR_LU;
107563b91edcSBarry Smith   a->row        = row;
107663b91edcSBarry Smith   a->col        = col;
107763b91edcSBarry Smith 
10780452661fSBarry Smith   a->solve_work = (Scalar *) PetscMalloc( (a->m+1)*sizeof(Scalar)); CHKPTRQ(a->solve_work);
107963b91edcSBarry Smith 
108008480c60SBarry Smith   if (!a->diag) {
108108480c60SBarry Smith     ierr = MatMarkDiag_SeqAIJ(inA); CHKERRQ(ierr);
108263b91edcSBarry Smith   }
108363b91edcSBarry Smith   ierr = MatLUFactorNumeric_SeqAIJ(inA,&outA); CHKERRQ(ierr);
1084a871dcd8SBarry Smith   return 0;
1085a871dcd8SBarry Smith }
1086a871dcd8SBarry Smith 
1087cddf8d76SBarry Smith static int MatGetSubMatrices_SeqAIJ(Mat A,int n, IS *irow,IS *icol,MatGetSubMatrixCall scall,
1088cddf8d76SBarry Smith                                     Mat **B)
1089cddf8d76SBarry Smith {
1090cddf8d76SBarry Smith   int ierr,i;
1091cddf8d76SBarry Smith 
1092cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
10930452661fSBarry Smith     *B = (Mat *) PetscMalloc( (n+1)*sizeof(Mat) ); CHKPTRQ(*B);
1094cddf8d76SBarry Smith   }
1095cddf8d76SBarry Smith 
1096cddf8d76SBarry Smith   for ( i=0; i<n; i++ ) {
1097cddf8d76SBarry Smith     ierr = MatGetSubMatrix(A,irow[i],icol[i],scall,&(*B)[i]); CHKERRQ(ierr);
1098cddf8d76SBarry Smith   }
1099cddf8d76SBarry Smith   return 0;
1100cddf8d76SBarry Smith }
1101cddf8d76SBarry Smith 
110217ab2063SBarry Smith /* -------------------------------------------------------------------*/
110317ab2063SBarry Smith 
110417ab2063SBarry Smith static struct _MatOps MatOps = {MatSetValues_SeqAIJ,
110517ab2063SBarry Smith        MatGetRow_SeqAIJ,MatRestoreRow_SeqAIJ,
1106416022c9SBarry Smith        MatMult_SeqAIJ,MatMultAdd_SeqAIJ,
1107416022c9SBarry Smith        MatMultTrans_SeqAIJ,MatMultTransAdd_SeqAIJ,
110817ab2063SBarry Smith        MatSolve_SeqAIJ,MatSolveAdd_SeqAIJ,
110917ab2063SBarry Smith        MatSolveTrans_SeqAIJ,MatSolveTransAdd_SeqAIJ,
111017ab2063SBarry Smith        MatLUFactor_SeqAIJ,0,
111117ab2063SBarry Smith        MatRelax_SeqAIJ,
111217ab2063SBarry Smith        MatTranspose_SeqAIJ,
111317ab2063SBarry Smith        MatGetInfo_SeqAIJ,0,
111417ab2063SBarry Smith        MatGetDiagonal_SeqAIJ,MatScale_SeqAIJ,MatNorm_SeqAIJ,
111517ab2063SBarry Smith        0,MatAssemblyEnd_SeqAIJ,
111617ab2063SBarry Smith        MatCompress_SeqAIJ,
111717ab2063SBarry Smith        MatSetOption_SeqAIJ,MatZeroEntries_SeqAIJ,MatZeroRows_SeqAIJ,
111817ab2063SBarry Smith        MatGetReordering_SeqAIJ,
111917ab2063SBarry Smith        MatLUFactorSymbolic_SeqAIJ,MatLUFactorNumeric_SeqAIJ,0,0,
112017ab2063SBarry Smith        MatGetSize_SeqAIJ,MatGetSize_SeqAIJ,MatGetOwnershipRange_SeqAIJ,
112117ab2063SBarry Smith        MatILUFactorSymbolic_SeqAIJ,0,
112217ab2063SBarry Smith        0,0,MatConvert_SeqAIJ,
1123416022c9SBarry Smith        MatGetSubMatrix_SeqAIJ,0,
1124a871dcd8SBarry Smith        MatCopyPrivate_SeqAIJ,0,0,
1125cddf8d76SBarry Smith        MatILUFactor_SeqAIJ,0,0,
1126cddf8d76SBarry Smith        MatGetSubMatrices_SeqAIJ};
112717ab2063SBarry Smith 
112817ab2063SBarry Smith extern int MatUseSuperLU_SeqAIJ(Mat);
112917ab2063SBarry Smith extern int MatUseEssl_SeqAIJ(Mat);
113017ab2063SBarry Smith extern int MatUseDXML_SeqAIJ(Mat);
113117ab2063SBarry Smith 
113217ab2063SBarry Smith /*@C
113317ab2063SBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ format
113417ab2063SBarry Smith    (the default uniprocessor PETSc format).
113517ab2063SBarry Smith 
113617ab2063SBarry Smith    Input Parameters:
113717ab2063SBarry Smith .  comm - MPI communicator, set to MPI_COMM_SELF
113817ab2063SBarry Smith .  m - number of rows
113917ab2063SBarry Smith .  n - number of columns
114017ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
114117ab2063SBarry Smith .  nzz - number of nonzeros per row or null (possibly different for each row)
114217ab2063SBarry Smith 
114317ab2063SBarry Smith    Output Parameter:
1144416022c9SBarry Smith .  A - the matrix
114517ab2063SBarry Smith 
114617ab2063SBarry Smith    Notes:
114717ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
114817ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
11490002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
11500002213bSLois Curfman McInnes    either one (as in Fortran) or zero.  See the users manual for details.
115117ab2063SBarry Smith 
115217ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
115317ab2063SBarry Smith    Set both nz and nnz to zero for PETSc to control dynamic memory
115417ab2063SBarry Smith    allocation.
115517ab2063SBarry Smith 
115617ab2063SBarry Smith .keywords: matrix, aij, compressed row, sparse
115717ab2063SBarry Smith 
115817ab2063SBarry Smith .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues()
115917ab2063SBarry Smith @*/
1160416022c9SBarry Smith int MatCreateSeqAIJ(MPI_Comm comm,int m,int n,int nz,int *nnz, Mat *A)
116117ab2063SBarry Smith {
1162416022c9SBarry Smith   Mat        B;
1163416022c9SBarry Smith   Mat_SeqAIJ *b;
116417ab2063SBarry Smith   int        i,len,ierr;
1165d5d45c9bSBarry Smith 
1166416022c9SBarry Smith   *A      = 0;
11670452661fSBarry Smith   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSEQAIJ,comm);
1168416022c9SBarry Smith   PLogObjectCreate(B);
11690452661fSBarry Smith   B->data               = (void *) (b = PetscNew(Mat_SeqAIJ)); CHKPTRQ(b);
1170416022c9SBarry Smith   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
1171416022c9SBarry Smith   B->destroy          = MatDestroy_SeqAIJ;
1172416022c9SBarry Smith   B->view             = MatView_SeqAIJ;
1173416022c9SBarry Smith   B->factor           = 0;
1174416022c9SBarry Smith   B->lupivotthreshold = 1.0;
1175416022c9SBarry Smith   OptionsGetDouble(0,"-mat_lu_pivotthreshold",&B->lupivotthreshold);
1176416022c9SBarry Smith   b->row              = 0;
1177416022c9SBarry Smith   b->col              = 0;
1178416022c9SBarry Smith   b->indexshift       = 0;
1179416022c9SBarry Smith   if (OptionsHasName(0,"-mat_aij_oneindex")) b->indexshift = -1;
118017ab2063SBarry Smith 
1181416022c9SBarry Smith   b->m       = m;
1182416022c9SBarry Smith   b->n       = n;
11830452661fSBarry Smith   b->imax    = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(b->imax);
118417ab2063SBarry Smith   if (!nnz) {
118517ab2063SBarry Smith     if (nz <= 0) nz = 1;
1186416022c9SBarry Smith     for ( i=0; i<m; i++ ) b->imax[i] = nz;
118717ab2063SBarry Smith     nz = nz*m;
118817ab2063SBarry Smith   }
118917ab2063SBarry Smith   else {
119017ab2063SBarry Smith     nz = 0;
1191416022c9SBarry Smith     for ( i=0; i<m; i++ ) {b->imax[i] = nnz[i]; nz += nnz[i];}
119217ab2063SBarry Smith   }
119317ab2063SBarry Smith 
119417ab2063SBarry Smith   /* allocate the matrix space */
1195416022c9SBarry Smith   len     = nz*(sizeof(int) + sizeof(Scalar)) + (b->m+1)*sizeof(int);
11960452661fSBarry Smith   b->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(b->a);
1197416022c9SBarry Smith   b->j  = (int *) (b->a + nz);
1198cddf8d76SBarry Smith   PetscMemzero(b->j,nz*sizeof(int));
1199416022c9SBarry Smith   b->i  = b->j + nz;
1200416022c9SBarry Smith   b->singlemalloc = 1;
120117ab2063SBarry Smith 
1202416022c9SBarry Smith   b->i[0] = -b->indexshift;
120317ab2063SBarry Smith   for (i=1; i<m+1; i++) {
1204416022c9SBarry Smith     b->i[i] = b->i[i-1] + b->imax[i-1];
120517ab2063SBarry Smith   }
120617ab2063SBarry Smith 
1207416022c9SBarry Smith   /* b->ilen will count nonzeros in each row so far. */
12080452661fSBarry Smith   b->ilen = (int *) PetscMalloc((m+1)*sizeof(int));
1209416022c9SBarry Smith   PLogObjectMemory(B,len+2*(m+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqAIJ));
1210416022c9SBarry Smith   for ( i=0; i<b->m; i++ ) { b->ilen[i] = 0;}
121117ab2063SBarry Smith 
1212416022c9SBarry Smith   b->nz               = 0;
1213416022c9SBarry Smith   b->maxnz            = nz;
1214416022c9SBarry Smith   b->sorted           = 0;
1215416022c9SBarry Smith   b->roworiented      = 1;
1216416022c9SBarry Smith   b->nonew            = 0;
1217416022c9SBarry Smith   b->diag             = 0;
1218416022c9SBarry Smith   b->assembled        = 0;
1219416022c9SBarry Smith   b->solve_work       = 0;
122071bd300dSLois Curfman McInnes   b->spptr            = 0;
1221754ec7b1SSatish Balay   b->inode.node_count = 0;
1222754ec7b1SSatish Balay   b->inode.size       = 0;
122317ab2063SBarry Smith 
1224416022c9SBarry Smith   *A = B;
122517ab2063SBarry Smith   if (OptionsHasName(0,"-mat_aij_superlu")) {
1226416022c9SBarry Smith     ierr = MatUseSuperLU_SeqAIJ(B); CHKERRQ(ierr);
122717ab2063SBarry Smith   }
122817ab2063SBarry Smith   if (OptionsHasName(0,"-mat_aij_essl")) {
1229416022c9SBarry Smith     ierr = MatUseEssl_SeqAIJ(B); CHKERRQ(ierr);
123017ab2063SBarry Smith   }
123117ab2063SBarry Smith   if (OptionsHasName(0,"-mat_aij_dxml")) {
1232416022c9SBarry Smith     if (!b->indexshift) SETERRQ(1,"MatCreateSeqAIJ:need -mat_aij_oneindex with -mat_aij_dxml");
1233416022c9SBarry Smith     ierr = MatUseDXML_SeqAIJ(B); CHKERRQ(ierr);
123417ab2063SBarry Smith   }
123517ab2063SBarry Smith 
123617ab2063SBarry Smith   return 0;
123717ab2063SBarry Smith }
123817ab2063SBarry Smith 
123908480c60SBarry Smith int MatCopyPrivate_SeqAIJ(Mat A,Mat *B,int cpvalues)
124017ab2063SBarry Smith {
1241416022c9SBarry Smith   Mat        C;
1242416022c9SBarry Smith   Mat_SeqAIJ *c,*a = (Mat_SeqAIJ *) A->data;
124308480c60SBarry Smith   int        i,len, m = a->m,shift = a->indexshift;
124417ab2063SBarry Smith 
12454043dd9cSLois Curfman McInnes   *B = 0;
1246416022c9SBarry Smith   if (!a->assembled) SETERRQ(1,"MatCopyPrivate_SeqAIJ:Cannot copy unassembled matrix");
12470452661fSBarry Smith   PetscHeaderCreate(C,_Mat,MAT_COOKIE,MATSEQAIJ,A->comm);
1248416022c9SBarry Smith   PLogObjectCreate(C);
12490452661fSBarry Smith   C->data       = (void *) (c = PetscNew(Mat_SeqAIJ)); CHKPTRQ(c);
1250416022c9SBarry Smith   PetscMemcpy(&C->ops,&MatOps,sizeof(struct _MatOps));
1251416022c9SBarry Smith   C->destroy    = MatDestroy_SeqAIJ;
1252416022c9SBarry Smith   C->view       = MatView_SeqAIJ;
1253416022c9SBarry Smith   C->factor     = A->factor;
1254416022c9SBarry Smith   c->row        = 0;
1255416022c9SBarry Smith   c->col        = 0;
1256416022c9SBarry Smith   c->indexshift = shift;
125717ab2063SBarry Smith 
1258416022c9SBarry Smith   c->m          = a->m;
1259416022c9SBarry Smith   c->n          = a->n;
126017ab2063SBarry Smith 
12610452661fSBarry Smith   c->imax       = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(c->imax);
12620452661fSBarry Smith   c->ilen       = (int *) PetscMalloc((m+1)*sizeof(int)); CHKPTRQ(c->ilen);
126317ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
1264416022c9SBarry Smith     c->imax[i] = a->imax[i];
1265416022c9SBarry Smith     c->ilen[i] = a->ilen[i];
126617ab2063SBarry Smith   }
126717ab2063SBarry Smith 
126817ab2063SBarry Smith   /* allocate the matrix space */
1269416022c9SBarry Smith   c->singlemalloc = 1;
1270416022c9SBarry Smith   len     = (m+1)*sizeof(int)+(a->i[m])*(sizeof(Scalar)+sizeof(int));
12710452661fSBarry Smith   c->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(c->a);
1272416022c9SBarry Smith   c->j  = (int *) (c->a + a->i[m] + shift);
1273416022c9SBarry Smith   c->i  = c->j + a->i[m] + shift;
1274416022c9SBarry Smith   PetscMemcpy(c->i,a->i,(m+1)*sizeof(int));
127517ab2063SBarry Smith   if (m > 0) {
1276416022c9SBarry Smith     PetscMemcpy(c->j,a->j,(a->i[m]+shift)*sizeof(int));
127708480c60SBarry Smith     if (cpvalues == COPY_VALUES) {
1278416022c9SBarry Smith       PetscMemcpy(c->a,a->a,(a->i[m]+shift)*sizeof(Scalar));
127917ab2063SBarry Smith     }
128008480c60SBarry Smith   }
128117ab2063SBarry Smith 
1282416022c9SBarry Smith   PLogObjectMemory(C,len+2*(m+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqAIJ));
1283416022c9SBarry Smith   c->sorted      = a->sorted;
1284416022c9SBarry Smith   c->roworiented = a->roworiented;
1285416022c9SBarry Smith   c->nonew       = a->nonew;
128617ab2063SBarry Smith 
1287416022c9SBarry Smith   if (a->diag) {
12880452661fSBarry Smith     c->diag = (int *) PetscMalloc( (m+1)*sizeof(int) ); CHKPTRQ(c->diag);
1289416022c9SBarry Smith     PLogObjectMemory(C,(m+1)*sizeof(int));
129017ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
1291416022c9SBarry Smith       c->diag[i] = a->diag[i];
129217ab2063SBarry Smith     }
129317ab2063SBarry Smith   }
1294416022c9SBarry Smith   else c->diag        = 0;
1295754ec7b1SSatish Balay   if( a->inode.size){
1296754ec7b1SSatish Balay     c->inode.size       = (int *) PetscMalloc( m *sizeof(int) ); CHKPTRQ(c->inode.size);
1297754ec7b1SSatish Balay     c->inode.node_count = a->inode.node_count;
1298754ec7b1SSatish Balay     PetscMemcpy( c->inode.size, a->inode.size, m*sizeof(int));
1299754ec7b1SSatish Balay   } else {
1300754ec7b1SSatish Balay     c->inode.size       = 0;
1301754ec7b1SSatish Balay     c->inode.node_count = 0;
1302754ec7b1SSatish Balay   }
1303416022c9SBarry Smith   c->assembled        = 1;
1304416022c9SBarry Smith   c->nz               = a->nz;
1305416022c9SBarry Smith   c->maxnz            = a->maxnz;
1306416022c9SBarry Smith   c->solve_work       = 0;
1307*76dd722bSSatish Balay   c->spptr            = 0;      /* Dangerous -I'm throwing away a->spptr */
1308754ec7b1SSatish Balay   b->inode.node_count = 0;
1309754ec7b1SSatish Balay   b->inode.size       = 0;
1310754ec7b1SSatish Balay 
1311416022c9SBarry Smith   *B = C;
131217ab2063SBarry Smith   return 0;
131317ab2063SBarry Smith }
131417ab2063SBarry Smith 
1315416022c9SBarry Smith int MatLoad_SeqAIJ(Viewer bview,MatType type,Mat *A)
131617ab2063SBarry Smith {
1317416022c9SBarry Smith   Mat_SeqAIJ   *a;
1318416022c9SBarry Smith   Mat          B;
131917699dbbSLois Curfman McInnes   int          i, nz, ierr, fd, header[4],size,*rowlengths = 0,M,N,shift;
132017ab2063SBarry Smith   PetscObject  vobj = (PetscObject) bview;
132117ab2063SBarry Smith   MPI_Comm     comm = vobj->comm;
132217ab2063SBarry Smith 
132317699dbbSLois Curfman McInnes   MPI_Comm_size(comm,&size);
132417699dbbSLois Curfman McInnes   if (size > 1) SETERRQ(1,"MatLoad_SeqAIJ:view must have one processor");
132517ab2063SBarry Smith   ierr = ViewerFileGetDescriptor_Private(bview,&fd); CHKERRQ(ierr);
1326416022c9SBarry Smith   ierr = SYRead(fd,header,4,SYINT); CHKERRQ(ierr);
132748d91487SBarry Smith   if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_SeqAIJ:not matrix object in file");
132817ab2063SBarry Smith   M = header[1]; N = header[2]; nz = header[3];
132917ab2063SBarry Smith 
133017ab2063SBarry Smith   /* read in row lengths */
13310452661fSBarry Smith   rowlengths = (int*) PetscMalloc( M*sizeof(int) ); CHKPTRQ(rowlengths);
1332416022c9SBarry Smith   ierr = SYRead(fd,rowlengths,M,SYINT); CHKERRQ(ierr);
133317ab2063SBarry Smith 
133417ab2063SBarry Smith   /* create our matrix */
1335416022c9SBarry Smith   ierr = MatCreateSeqAIJ(comm,M,N,0,rowlengths,A); CHKERRQ(ierr);
1336416022c9SBarry Smith   B = *A;
1337416022c9SBarry Smith   a = (Mat_SeqAIJ *) B->data;
1338416022c9SBarry Smith   shift = a->indexshift;
133917ab2063SBarry Smith 
134017ab2063SBarry Smith   /* read in column indices and adjust for Fortran indexing*/
1341416022c9SBarry Smith   ierr = SYRead(fd,a->j,nz,SYINT); CHKERRQ(ierr);
134217ab2063SBarry Smith   if (shift) {
134317ab2063SBarry Smith     for ( i=0; i<nz; i++ ) {
1344416022c9SBarry Smith       a->j[i] += 1;
134517ab2063SBarry Smith     }
134617ab2063SBarry Smith   }
134717ab2063SBarry Smith 
134817ab2063SBarry Smith   /* read in nonzero values */
1349416022c9SBarry Smith   ierr = SYRead(fd,a->a,nz,SYSCALAR); CHKERRQ(ierr);
135017ab2063SBarry Smith 
135117ab2063SBarry Smith   /* set matrix "i" values */
1352416022c9SBarry Smith   a->i[0] = -shift;
135317ab2063SBarry Smith   for ( i=1; i<= M; i++ ) {
1354416022c9SBarry Smith     a->i[i]      = a->i[i-1] + rowlengths[i-1];
1355416022c9SBarry Smith     a->ilen[i-1] = rowlengths[i-1];
135617ab2063SBarry Smith   }
13570452661fSBarry Smith   PetscFree(rowlengths);
135817ab2063SBarry Smith 
1359416022c9SBarry Smith   ierr = MatAssemblyBegin(B,FINAL_ASSEMBLY); CHKERRQ(ierr);
1360416022c9SBarry Smith   ierr = MatAssemblyEnd(B,FINAL_ASSEMBLY); CHKERRQ(ierr);
136117ab2063SBarry Smith   return 0;
136217ab2063SBarry Smith }
136317ab2063SBarry Smith 
136417ab2063SBarry Smith 
136517ab2063SBarry Smith 
1366