xref: /petsc/src/mat/impls/aij/seq/aij.c (revision fe93831d8621ea09444c826aabfbddd03dd6bc35)
1 /*$Id: aij.c,v 1.385 2001/09/07 20:09:22 bsmith Exp $*/
2 /*
3     Defines the basic matrix operations for the AIJ (compressed row)
4   matrix storage format.
5 */
6 
7 #include "src/mat/impls/aij/seq/aij.h"          /*I "petscmat.h" I*/
8 #include "src/inline/spops.h"
9 #include "src/inline/dot.h"
10 #include "petscbt.h"
11 
12 #undef __FUNCT__
13 #define __FUNCT__ "MatGetRowIJ_SeqAIJ"
14 int MatGetRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *m,int *ia[],int *ja[],PetscTruth *done)
15 {
16   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
17   int        ierr,i,ishift;
18 
19   PetscFunctionBegin;
20   *m     = A->m;
21   if (!ia) PetscFunctionReturn(0);
22   ishift = 0;
23   if (symmetric && !A->structurally_symmetric) {
24     ierr = MatToSymmetricIJ_SeqAIJ(A->m,a->i,a->j,ishift,oshift,ia,ja);CHKERRQ(ierr);
25   } else if (oshift == 1) {
26     int nz = a->i[A->m];
27     /* malloc space and  add 1 to i and j indices */
28     ierr = PetscMalloc((A->m+1)*sizeof(int),ia);CHKERRQ(ierr);
29     ierr = PetscMalloc((nz+1)*sizeof(int),ja);CHKERRQ(ierr);
30     for (i=0; i<nz; i++) (*ja)[i] = a->j[i] + 1;
31     for (i=0; i<A->m+1; i++) (*ia)[i] = a->i[i] + 1;
32   } else {
33     *ia = a->i; *ja = a->j;
34   }
35   PetscFunctionReturn(0);
36 }
37 
38 #undef __FUNCT__
39 #define __FUNCT__ "MatRestoreRowIJ_SeqAIJ"
40 int MatRestoreRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int *ia[],int *ja[],PetscTruth *done)
41 {
42   int ierr;
43 
44   PetscFunctionBegin;
45   if (!ia) PetscFunctionReturn(0);
46   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
47     ierr = PetscFree(*ia);CHKERRQ(ierr);
48     ierr = PetscFree(*ja);CHKERRQ(ierr);
49   }
50   PetscFunctionReturn(0);
51 }
52 
53 #undef __FUNCT__
54 #define __FUNCT__ "MatGetColumnIJ_SeqAIJ"
55 int MatGetColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int *ia[],int *ja[],PetscTruth *done)
56 {
57   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
58   int        ierr,i,*collengths,*cia,*cja,n = A->n,m = A->m;
59   int        nz = a->i[m],row,*jj,mr,col;
60 
61   PetscFunctionBegin;
62   *nn     = A->n;
63   if (!ia) PetscFunctionReturn(0);
64   if (symmetric) {
65     ierr = MatToSymmetricIJ_SeqAIJ(A->m,a->i,a->j,0,oshift,ia,ja);CHKERRQ(ierr);
66   } else {
67     ierr = PetscMalloc((n+1)*sizeof(int),&collengths);CHKERRQ(ierr);
68     ierr = PetscMemzero(collengths,n*sizeof(int));CHKERRQ(ierr);
69     ierr = PetscMalloc((n+1)*sizeof(int),&cia);CHKERRQ(ierr);
70     ierr = PetscMalloc((nz+1)*sizeof(int),&cja);CHKERRQ(ierr);
71     jj = a->j;
72     for (i=0; i<nz; i++) {
73       collengths[jj[i]]++;
74     }
75     cia[0] = oshift;
76     for (i=0; i<n; i++) {
77       cia[i+1] = cia[i] + collengths[i];
78     }
79     ierr = PetscMemzero(collengths,n*sizeof(int));CHKERRQ(ierr);
80     jj   = a->j;
81     for (row=0; row<m; row++) {
82       mr = a->i[row+1] - a->i[row];
83       for (i=0; i<mr; i++) {
84         col = *jj++;
85         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
86       }
87     }
88     ierr = PetscFree(collengths);CHKERRQ(ierr);
89     *ia = cia; *ja = cja;
90   }
91   PetscFunctionReturn(0);
92 }
93 
94 #undef __FUNCT__
95 #define __FUNCT__ "MatRestoreColumnIJ_SeqAIJ"
96 int MatRestoreColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int *ia[],int *ja[],PetscTruth *done)
97 {
98   int ierr;
99 
100   PetscFunctionBegin;
101   if (!ia) PetscFunctionReturn(0);
102 
103   ierr = PetscFree(*ia);CHKERRQ(ierr);
104   ierr = PetscFree(*ja);CHKERRQ(ierr);
105 
106   PetscFunctionReturn(0);
107 }
108 
109 #define CHUNKSIZE   15
110 
111 #undef __FUNCT__
112 #define __FUNCT__ "MatSetValues_SeqAIJ"
113 int MatSetValues_SeqAIJ(Mat A,int m,const int im[],int n,const int in[],const PetscScalar v[],InsertMode is)
114 {
115   Mat_SeqAIJ  *a = (Mat_SeqAIJ*)A->data;
116   int         *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,sorted = a->sorted;
117   int         *imax = a->imax,*ai = a->i,*ailen = a->ilen;
118   int         *aj = a->j,nonew = a->nonew,ierr;
119   PetscScalar *ap,value,*aa = a->a;
120   PetscTruth  ignorezeroentries = ((a->ignorezeroentries && is == ADD_VALUES) ? PETSC_TRUE:PETSC_FALSE);
121   PetscTruth  roworiented = a->roworiented;
122 
123   PetscFunctionBegin;
124   for (k=0; k<m; k++) { /* loop over added rows */
125     row  = im[k];
126     if (row < 0) continue;
127 #if defined(PETSC_USE_BOPT_g)
128     if (row >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %d max %d",row,A->m-1);
129 #endif
130     rp   = aj + ai[row]; ap = aa + ai[row];
131     rmax = imax[row]; nrow = ailen[row];
132     low = 0;
133     for (l=0; l<n; l++) { /* loop over added columns */
134       if (in[l] < 0) continue;
135 #if defined(PETSC_USE_BOPT_g)
136       if (in[l] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %d max %d",in[l],A->n-1);
137 #endif
138       col = in[l];
139       if (roworiented) {
140         value = v[l + k*n];
141       } else {
142         value = v[k + l*m];
143       }
144       if (value == 0.0 && ignorezeroentries) continue;
145 
146       if (!sorted) low = 0; high = nrow;
147       while (high-low > 5) {
148         t = (low+high)/2;
149         if (rp[t] > col) high = t;
150         else             low  = t;
151       }
152       for (i=low; i<high; i++) {
153         if (rp[i] > col) break;
154         if (rp[i] == col) {
155           if (is == ADD_VALUES) ap[i] += value;
156           else                  ap[i] = value;
157           goto noinsert;
158         }
159       }
160       if (nonew == 1) goto noinsert;
161       else if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%d,%d) in the matrix",row,col);
162       if (nrow >= rmax) {
163         /* there is no extra room in row, therefore enlarge */
164         int         new_nz = ai[A->m] + CHUNKSIZE,*new_i,*new_j;
165         size_t      len;
166         PetscScalar *new_a;
167 
168         if (nonew == -2) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%d,%d) in the matrix requiring new malloc()",row,col);
169 
170         /* malloc new storage space */
171         len     = ((size_t) new_nz)*(sizeof(int)+sizeof(PetscScalar))+(A->m+1)*sizeof(int);
172 	ierr    = PetscMalloc(len,&new_a);CHKERRQ(ierr);
173         new_j   = (int*)(new_a + new_nz);
174         new_i   = new_j + new_nz;
175 
176         /* copy over old data into new slots */
177         for (ii=0; ii<row+1; ii++) {new_i[ii] = ai[ii];}
178         for (ii=row+1; ii<A->m+1; ii++) {new_i[ii] = ai[ii]+CHUNKSIZE;}
179         ierr = PetscMemcpy(new_j,aj,(ai[row]+nrow)*sizeof(int));CHKERRQ(ierr);
180         len  = (((size_t) new_nz) - CHUNKSIZE - ai[row] - nrow );
181         ierr = PetscMemcpy(new_j+ai[row]+nrow+CHUNKSIZE,aj+ai[row]+nrow,len*sizeof(int));CHKERRQ(ierr);
182         ierr = PetscMemcpy(new_a,aa,(((size_t) ai[row])+nrow)*sizeof(PetscScalar));CHKERRQ(ierr);
183         ierr = PetscMemcpy(new_a+ai[row]+nrow+CHUNKSIZE,aa+ai[row]+nrow,len*sizeof(PetscScalar));CHKERRQ(ierr);
184         /* free up old matrix storage */
185         ierr = PetscFree(a->a);CHKERRQ(ierr);
186         if (!a->singlemalloc) {
187           ierr = PetscFree(a->i);CHKERRQ(ierr);
188           ierr = PetscFree(a->j);CHKERRQ(ierr);
189         }
190         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
191         a->singlemalloc = PETSC_TRUE;
192 
193         rp   = aj + ai[row]; ap = aa + ai[row] ;
194         rmax = imax[row] = imax[row] + CHUNKSIZE;
195         PetscLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + sizeof(PetscScalar)));
196         a->maxnz += CHUNKSIZE;
197         a->reallocs++;
198       }
199       N = nrow++ - 1; a->nz++;
200       /* shift up all the later entries in this row */
201       for (ii=N; ii>=i; ii--) {
202         rp[ii+1] = rp[ii];
203         ap[ii+1] = ap[ii];
204       }
205       rp[i] = col;
206       ap[i] = value;
207       noinsert:;
208       low = i + 1;
209     }
210     ailen[row] = nrow;
211   }
212   PetscFunctionReturn(0);
213 }
214 
215 #undef __FUNCT__
216 #define __FUNCT__ "MatGetValues_SeqAIJ"
217 int MatGetValues_SeqAIJ(Mat A,int m,const int im[],int n,const int in[],PetscScalar v[])
218 {
219   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
220   int          *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
221   int          *ai = a->i,*ailen = a->ilen;
222   PetscScalar  *ap,*aa = a->a,zero = 0.0;
223 
224   PetscFunctionBegin;
225   for (k=0; k<m; k++) { /* loop over rows */
226     row  = im[k];
227     if (row < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %d",row);
228     if (row >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %d max %d",row,A->m-1);
229     rp   = aj + ai[row]; ap = aa + ai[row];
230     nrow = ailen[row];
231     for (l=0; l<n; l++) { /* loop over columns */
232       if (in[l] < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %d",in[l]);
233       if (in[l] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %d max %d",in[l],A->n-1);
234       col = in[l] ;
235       high = nrow; low = 0; /* assume unsorted */
236       while (high-low > 5) {
237         t = (low+high)/2;
238         if (rp[t] > col) high = t;
239         else             low  = t;
240       }
241       for (i=low; i<high; i++) {
242         if (rp[i] > col) break;
243         if (rp[i] == col) {
244           *v++ = ap[i];
245           goto finished;
246         }
247       }
248       *v++ = zero;
249       finished:;
250     }
251   }
252   PetscFunctionReturn(0);
253 }
254 
255 
256 #undef __FUNCT__
257 #define __FUNCT__ "MatView_SeqAIJ_Binary"
258 int MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer)
259 {
260   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
261   int        i,fd,*col_lens,ierr;
262 
263   PetscFunctionBegin;
264   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
265   ierr = PetscMalloc((4+A->m)*sizeof(int),&col_lens);CHKERRQ(ierr);
266   col_lens[0] = MAT_FILE_COOKIE;
267   col_lens[1] = A->m;
268   col_lens[2] = A->n;
269   col_lens[3] = a->nz;
270 
271   /* store lengths of each row and write (including header) to file */
272   for (i=0; i<A->m; i++) {
273     col_lens[4+i] = a->i[i+1] - a->i[i];
274   }
275   ierr = PetscBinaryWrite(fd,col_lens,4+A->m,PETSC_INT,1);CHKERRQ(ierr);
276   ierr = PetscFree(col_lens);CHKERRQ(ierr);
277 
278   /* store column indices (zero start index) */
279   ierr = PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,0);CHKERRQ(ierr);
280 
281   /* store nonzero values */
282   ierr = PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,0);CHKERRQ(ierr);
283   PetscFunctionReturn(0);
284 }
285 
286 extern int MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
287 
288 #undef __FUNCT__
289 #define __FUNCT__ "MatView_SeqAIJ_ASCII"
290 int MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
291 {
292   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
293   int               ierr,i,j,m = A->m,shift=0;
294   char              *name;
295   PetscViewerFormat format;
296 
297   PetscFunctionBegin;
298   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
299   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
300   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL || format == PETSC_VIEWER_ASCII_INFO) {
301     if (a->inode.size) {
302       ierr = PetscViewerASCIIPrintf(viewer,"using I-node routines: found %d nodes, limit used is %d\n",a->inode.node_count,a->inode.limit);CHKERRQ(ierr);
303     } else {
304       ierr = PetscViewerASCIIPrintf(viewer,"not using I-node routines\n");CHKERRQ(ierr);
305     }
306   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
307     int nofinalvalue = 0;
308     if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->n-!shift)) {
309       nofinalvalue = 1;
310     }
311     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
312     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %d %d \n",m,A->n);CHKERRQ(ierr);
313     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %d \n",a->nz);CHKERRQ(ierr);
314     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%d,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
315     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
316 
317     for (i=0; i<m; i++) {
318       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
319 #if defined(PETSC_USE_COMPLEX)
320         ierr = PetscViewerASCIIPrintf(viewer,"%d %d  %18.16e + %18.16ei \n",i+1,a->j[j]+!shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
321 #else
322         ierr = PetscViewerASCIIPrintf(viewer,"%d %d  %18.16e\n",i+1,a->j[j]+!shift,a->a[j]);CHKERRQ(ierr);
323 #endif
324       }
325     }
326     if (nofinalvalue) {
327       ierr = PetscViewerASCIIPrintf(viewer,"%d %d  %18.16e\n",m,A->n,0.0);CHKERRQ(ierr);
328     }
329     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
330     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
331   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
332 #if defined(PETSC_HAVE_MATLAB) && !defined(PETSC_USE_SINGLE) && !defined(PETSC_USE_COMPLEX)
333      ierr = MatSeqAIJFactorInfo_Matlab(A,viewer);CHKERRQ(ierr);
334 #endif
335      PetscFunctionReturn(0);
336   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
337     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
338     for (i=0; i<m; i++) {
339       ierr = PetscViewerASCIIPrintf(viewer,"row %d:",i);CHKERRQ(ierr);
340       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
341 #if defined(PETSC_USE_COMPLEX)
342         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
343           ierr = PetscViewerASCIIPrintf(viewer," (%d, %g + %g i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
344         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
345           ierr = PetscViewerASCIIPrintf(viewer," (%d, %g - %g i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
346         } else if (PetscRealPart(a->a[j]) != 0.0) {
347           ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
348         }
349 #else
350         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);}
351 #endif
352       }
353       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
354     }
355     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
356   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
357     int nzd=0,fshift=1,*sptr;
358     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
359     ierr = PetscMalloc((m+1)*sizeof(int),&sptr);CHKERRQ(ierr);
360     for (i=0; i<m; i++) {
361       sptr[i] = nzd+1;
362       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
363         if (a->j[j] >= i) {
364 #if defined(PETSC_USE_COMPLEX)
365           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
366 #else
367           if (a->a[j] != 0.0) nzd++;
368 #endif
369         }
370       }
371     }
372     sptr[m] = nzd+1;
373     ierr = PetscViewerASCIIPrintf(viewer," %d %d\n\n",m,nzd);CHKERRQ(ierr);
374     for (i=0; i<m+1; i+=6) {
375       if (i+4<m) {ierr = PetscViewerASCIIPrintf(viewer," %d %d %d %d %d %d\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4],sptr[i+5]);CHKERRQ(ierr);}
376       else if (i+3<m) {ierr = PetscViewerASCIIPrintf(viewer," %d %d %d %d %d\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4]);CHKERRQ(ierr);}
377       else if (i+2<m) {ierr = PetscViewerASCIIPrintf(viewer," %d %d %d %d\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);}
378       else if (i+1<m) {ierr = PetscViewerASCIIPrintf(viewer," %d %d %d\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);}
379       else if (i<m)   {ierr = PetscViewerASCIIPrintf(viewer," %d %d\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);}
380       else            {ierr = PetscViewerASCIIPrintf(viewer," %d\n",sptr[i]);CHKERRQ(ierr);}
381     }
382     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
383     ierr = PetscFree(sptr);CHKERRQ(ierr);
384     for (i=0; i<m; i++) {
385       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
386         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %d ",a->j[j]+fshift);CHKERRQ(ierr);}
387       }
388       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
389     }
390     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
391     for (i=0; i<m; i++) {
392       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
393         if (a->j[j] >= i) {
394 #if defined(PETSC_USE_COMPLEX)
395           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
396             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
397           }
398 #else
399           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",a->a[j]);CHKERRQ(ierr);}
400 #endif
401         }
402       }
403       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
404     }
405     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
406   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
407     int         cnt = 0,jcnt;
408     PetscScalar value;
409 
410     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
411     for (i=0; i<m; i++) {
412       jcnt = 0;
413       for (j=0; j<A->n; j++) {
414         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
415           value = a->a[cnt++];
416           jcnt++;
417         } else {
418           value = 0.0;
419         }
420 #if defined(PETSC_USE_COMPLEX)
421         ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",PetscRealPart(value),PetscImaginaryPart(value));CHKERRQ(ierr);
422 #else
423         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",value);CHKERRQ(ierr);
424 #endif
425       }
426       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
427     }
428     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
429   } else {
430     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
431     for (i=0; i<m; i++) {
432       ierr = PetscViewerASCIIPrintf(viewer,"row %d:",i);CHKERRQ(ierr);
433       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
434 #if defined(PETSC_USE_COMPLEX)
435         if (PetscImaginaryPart(a->a[j]) > 0.0) {
436           ierr = PetscViewerASCIIPrintf(viewer," (%d, %g + %g i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
437         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
438           ierr = PetscViewerASCIIPrintf(viewer," (%d, %g - %g i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
439         } else {
440           ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
441         }
442 #else
443         ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);
444 #endif
445       }
446       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
447     }
448     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
449   }
450   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
451   PetscFunctionReturn(0);
452 }
453 
454 #undef __FUNCT__
455 #define __FUNCT__ "MatView_SeqAIJ_Draw_Zoom"
456 int MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
457 {
458   Mat               A = (Mat) Aa;
459   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
460   int               ierr,i,j,m = A->m,color;
461   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r,maxv = 0.0;
462   PetscViewer       viewer;
463   PetscViewerFormat format;
464 
465   PetscFunctionBegin;
466   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
467   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
468 
469   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
470   /* loop over matrix elements drawing boxes */
471 
472   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
473     /* Blue for negative, Cyan for zero and  Red for positive */
474     color = PETSC_DRAW_BLUE;
475     for (i=0; i<m; i++) {
476       y_l = m - i - 1.0; y_r = y_l + 1.0;
477       for (j=a->i[i]; j<a->i[i+1]; j++) {
478         x_l = a->j[j] ; x_r = x_l + 1.0;
479 #if defined(PETSC_USE_COMPLEX)
480         if (PetscRealPart(a->a[j]) >=  0.) continue;
481 #else
482         if (a->a[j] >=  0.) continue;
483 #endif
484         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
485       }
486     }
487     color = PETSC_DRAW_CYAN;
488     for (i=0; i<m; i++) {
489       y_l = m - i - 1.0; y_r = y_l + 1.0;
490       for (j=a->i[i]; j<a->i[i+1]; j++) {
491         x_l = a->j[j]; x_r = x_l + 1.0;
492         if (a->a[j] !=  0.) continue;
493         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
494       }
495     }
496     color = PETSC_DRAW_RED;
497     for (i=0; i<m; i++) {
498       y_l = m - i - 1.0; y_r = y_l + 1.0;
499       for (j=a->i[i]; j<a->i[i+1]; j++) {
500         x_l = a->j[j]; x_r = x_l + 1.0;
501 #if defined(PETSC_USE_COMPLEX)
502         if (PetscRealPart(a->a[j]) <=  0.) continue;
503 #else
504         if (a->a[j] <=  0.) continue;
505 #endif
506         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
507       }
508     }
509   } else {
510     /* use contour shading to indicate magnitude of values */
511     /* first determine max of all nonzero values */
512     int    nz = a->nz,count;
513     PetscDraw   popup;
514     PetscReal scale;
515 
516     for (i=0; i<nz; i++) {
517       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
518     }
519     scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv;
520     ierr  = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
521     if (popup) {ierr  = PetscDrawScalePopup(popup,0.0,maxv);CHKERRQ(ierr);}
522     count = 0;
523     for (i=0; i<m; i++) {
524       y_l = m - i - 1.0; y_r = y_l + 1.0;
525       for (j=a->i[i]; j<a->i[i+1]; j++) {
526         x_l = a->j[j]; x_r = x_l + 1.0;
527         color = PETSC_DRAW_BASIC_COLORS + (int)(scale*PetscAbsScalar(a->a[count]));
528         ierr  = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
529         count++;
530       }
531     }
532   }
533   PetscFunctionReturn(0);
534 }
535 
536 #undef __FUNCT__
537 #define __FUNCT__ "MatView_SeqAIJ_Draw"
538 int MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
539 {
540   int        ierr;
541   PetscDraw  draw;
542   PetscReal  xr,yr,xl,yl,h,w;
543   PetscTruth isnull;
544 
545   PetscFunctionBegin;
546   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
547   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
548   if (isnull) PetscFunctionReturn(0);
549 
550   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
551   xr  = A->n; yr = A->m; h = yr/10.0; w = xr/10.0;
552   xr += w;    yr += h;  xl = -w;     yl = -h;
553   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
554   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
555   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
556   PetscFunctionReturn(0);
557 }
558 
559 #undef __FUNCT__
560 #define __FUNCT__ "MatView_SeqAIJ"
561 int MatView_SeqAIJ(Mat A,PetscViewer viewer)
562 {
563   Mat_SeqAIJ  *a = (Mat_SeqAIJ*)A->data;
564   int         ierr;
565   PetscTruth  issocket,isascii,isbinary,isdraw;
566 
567   PetscFunctionBegin;
568   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);CHKERRQ(ierr);
569   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
570   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);CHKERRQ(ierr);
571   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
572   if (issocket) {
573     ierr = PetscViewerSocketPutSparse_Private(viewer,A->m,A->n,a->nz,a->a,a->i,a->j);CHKERRQ(ierr);
574   } else if (isascii) {
575     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
576   } else if (isbinary) {
577     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
578   } else if (isdraw) {
579     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
580   } else {
581     SETERRQ1(1,"Viewer type %s not supported by SeqAIJ matrices",((PetscObject)viewer)->type_name);
582   }
583   PetscFunctionReturn(0);
584 }
585 
586 #undef __FUNCT__
587 #define __FUNCT__ "MatAssemblyEnd_SeqAIJ"
588 int MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
589 {
590   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
591   int          fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax,ierr;
592   int          m = A->m,*ip,N,*ailen = a->ilen,rmax = 0;
593   PetscScalar  *aa = a->a,*ap;
594 
595   PetscFunctionBegin;
596   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
597 
598   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
599   for (i=1; i<m; i++) {
600     /* move each row back by the amount of empty slots (fshift) before it*/
601     fshift += imax[i-1] - ailen[i-1];
602     rmax   = PetscMax(rmax,ailen[i]);
603     if (fshift) {
604       ip = aj + ai[i] ;
605       ap = aa + ai[i] ;
606       N  = ailen[i];
607       for (j=0; j<N; j++) {
608         ip[j-fshift] = ip[j];
609         ap[j-fshift] = ap[j];
610       }
611     }
612     ai[i] = ai[i-1] + ailen[i-1];
613   }
614   if (m) {
615     fshift += imax[m-1] - ailen[m-1];
616     ai[m]  = ai[m-1] + ailen[m-1];
617   }
618   /* reset ilen and imax for each row */
619   for (i=0; i<m; i++) {
620     ailen[i] = imax[i] = ai[i+1] - ai[i];
621   }
622   a->nz = ai[m];
623 
624   /* diagonals may have moved, so kill the diagonal pointers */
625   if (fshift && a->diag) {
626     ierr = PetscFree(a->diag);CHKERRQ(ierr);
627     PetscLogObjectMemory(A,-(m+1)*sizeof(int));
628     a->diag = 0;
629   }
630   PetscLogInfo(A,"MatAssemblyEnd_SeqAIJ:Matrix size: %d X %d; storage space: %d unneeded,%d used\n",m,A->n,fshift,a->nz);
631   PetscLogInfo(A,"MatAssemblyEnd_SeqAIJ:Number of mallocs during MatSetValues() is %d\n",a->reallocs);
632   PetscLogInfo(A,"MatAssemblyEnd_SeqAIJ:Most nonzeros in any row is %d\n",rmax);
633   a->reallocs          = 0;
634   A->info.nz_unneeded  = (double)fshift;
635   a->rmax              = rmax;
636 
637   /* check out for identical nodes. If found, use inode functions */
638   ierr = Mat_AIJ_CheckInode(A,(PetscTruth)(!fshift));CHKERRQ(ierr);
639 
640   PetscFunctionReturn(0);
641 }
642 
643 #undef __FUNCT__
644 #define __FUNCT__ "MatZeroEntries_SeqAIJ"
645 int MatZeroEntries_SeqAIJ(Mat A)
646 {
647   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
648   int        ierr;
649 
650   PetscFunctionBegin;
651   ierr = PetscMemzero(a->a,(a->i[A->m])*sizeof(PetscScalar));CHKERRQ(ierr);
652   PetscFunctionReturn(0);
653 }
654 
655 #undef __FUNCT__
656 #define __FUNCT__ "MatDestroy_SeqAIJ"
657 int MatDestroy_SeqAIJ(Mat A)
658 {
659   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
660   int        ierr;
661 
662   PetscFunctionBegin;
663 #if defined(PETSC_USE_LOG)
664   PetscLogObjectState((PetscObject)A,"Rows=%d, Cols=%d, NZ=%d",A->m,A->n,a->nz);
665 #endif
666   if (a->freedata) {
667     ierr = PetscFree(a->a);CHKERRQ(ierr);
668     if (!a->singlemalloc) {
669       ierr = PetscFree(a->i);CHKERRQ(ierr);
670       ierr = PetscFree(a->j);CHKERRQ(ierr);
671     }
672   }
673   if (a->row) {
674     ierr = ISDestroy(a->row);CHKERRQ(ierr);
675   }
676   if (a->col) {
677     ierr = ISDestroy(a->col);CHKERRQ(ierr);
678   }
679   if (a->diag) {ierr = PetscFree(a->diag);CHKERRQ(ierr);}
680   if (a->ilen) {ierr = PetscFree(a->ilen);CHKERRQ(ierr);}
681   if (a->imax) {ierr = PetscFree(a->imax);CHKERRQ(ierr);}
682   if (a->idiag) {ierr = PetscFree(a->idiag);CHKERRQ(ierr);}
683   if (a->solve_work) {ierr = PetscFree(a->solve_work);CHKERRQ(ierr);}
684   if (a->inode.size) {ierr = PetscFree(a->inode.size);CHKERRQ(ierr);}
685   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);}
686   if (a->saved_values) {ierr = PetscFree(a->saved_values);CHKERRQ(ierr);}
687   if (a->coloring) {ierr = ISColoringDestroy(a->coloring);CHKERRQ(ierr);}
688   if (a->xtoy) {ierr = PetscFree(a->xtoy);CHKERRQ(ierr);}
689 
690   ierr = PetscFree(a);CHKERRQ(ierr);
691   PetscFunctionReturn(0);
692 }
693 
694 #undef __FUNCT__
695 #define __FUNCT__ "MatCompress_SeqAIJ"
696 int MatCompress_SeqAIJ(Mat A)
697 {
698   PetscFunctionBegin;
699   PetscFunctionReturn(0);
700 }
701 
702 #undef __FUNCT__
703 #define __FUNCT__ "MatSetOption_SeqAIJ"
704 int MatSetOption_SeqAIJ(Mat A,MatOption op)
705 {
706   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
707 
708   PetscFunctionBegin;
709   switch (op) {
710     case MAT_ROW_ORIENTED:
711       a->roworiented       = PETSC_TRUE;
712       break;
713     case MAT_KEEP_ZEROED_ROWS:
714       a->keepzeroedrows    = PETSC_TRUE;
715       break;
716     case MAT_COLUMN_ORIENTED:
717       a->roworiented       = PETSC_FALSE;
718       break;
719     case MAT_COLUMNS_SORTED:
720       a->sorted            = PETSC_TRUE;
721       break;
722     case MAT_COLUMNS_UNSORTED:
723       a->sorted            = PETSC_FALSE;
724       break;
725     case MAT_NO_NEW_NONZERO_LOCATIONS:
726       a->nonew             = 1;
727       break;
728     case MAT_NEW_NONZERO_LOCATION_ERR:
729       a->nonew             = -1;
730       break;
731     case MAT_NEW_NONZERO_ALLOCATION_ERR:
732       a->nonew             = -2;
733       break;
734     case MAT_YES_NEW_NONZERO_LOCATIONS:
735       a->nonew             = 0;
736       break;
737     case MAT_IGNORE_ZERO_ENTRIES:
738       a->ignorezeroentries = PETSC_TRUE;
739       break;
740     case MAT_USE_INODES:
741       a->inode.use         = PETSC_TRUE;
742       break;
743     case MAT_DO_NOT_USE_INODES:
744       a->inode.use         = PETSC_FALSE;
745       break;
746     case MAT_ROWS_SORTED:
747     case MAT_ROWS_UNSORTED:
748     case MAT_YES_NEW_DIAGONALS:
749     case MAT_IGNORE_OFF_PROC_ENTRIES:
750     case MAT_USE_HASH_TABLE:
751       PetscLogInfo(A,"MatSetOption_SeqAIJ:Option ignored\n");
752       break;
753     case MAT_NO_NEW_DIAGONALS:
754       SETERRQ(PETSC_ERR_SUP,"MAT_NO_NEW_DIAGONALS");
755     case MAT_INODE_LIMIT_1:
756       a->inode.limit  = 1;
757       break;
758     case MAT_INODE_LIMIT_2:
759       a->inode.limit  = 2;
760       break;
761     case MAT_INODE_LIMIT_3:
762       a->inode.limit  = 3;
763       break;
764     case MAT_INODE_LIMIT_4:
765       a->inode.limit  = 4;
766       break;
767     case MAT_INODE_LIMIT_5:
768       a->inode.limit  = 5;
769       break;
770     case MAT_SYMMETRIC:
771     case MAT_STRUCTURALLY_SYMMETRIC:
772     case MAT_NOT_SYMMETRIC:
773     case MAT_NOT_STRUCTURALLY_SYMMETRIC:
774     case MAT_HERMITIAN:
775     case MAT_NOT_HERMITIAN:
776     case MAT_SYMMETRY_ETERNAL:
777     case MAT_NOT_SYMMETRY_ETERNAL:
778       break;
779     default:
780       SETERRQ(PETSC_ERR_SUP,"unknown option");
781   }
782   PetscFunctionReturn(0);
783 }
784 
785 #undef __FUNCT__
786 #define __FUNCT__ "MatGetDiagonal_SeqAIJ"
787 int MatGetDiagonal_SeqAIJ(Mat A,Vec v)
788 {
789   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
790   int          i,j,n,ierr;
791   PetscScalar  *x,zero = 0.0;
792 
793   PetscFunctionBegin;
794   ierr = VecSet(&zero,v);CHKERRQ(ierr);
795   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
796   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
797   if (n != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
798   for (i=0; i<A->m; i++) {
799     for (j=a->i[i]; j<a->i[i+1]; j++) {
800       if (a->j[j] == i) {
801         x[i] = a->a[j];
802         break;
803       }
804     }
805   }
806   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
807   PetscFunctionReturn(0);
808 }
809 
810 
811 #undef __FUNCT__
812 #define __FUNCT__ "MatMultTransposeAdd_SeqAIJ"
813 int MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
814 {
815   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
816   PetscScalar  *x,*y;
817   int          ierr,m = A->m;
818 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
819   PetscScalar  *v,alpha;
820   int          n,i,*idx;
821 #endif
822 
823   PetscFunctionBegin;
824   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
825   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
826   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
827 
828 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
829   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
830 #else
831   for (i=0; i<m; i++) {
832     idx   = a->j + a->i[i] ;
833     v     = a->a + a->i[i] ;
834     n     = a->i[i+1] - a->i[i];
835     alpha = x[i];
836     while (n-->0) {y[*idx++] += alpha * *v++;}
837   }
838 #endif
839   PetscLogFlops(2*a->nz);
840   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
841   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
842   PetscFunctionReturn(0);
843 }
844 
845 #undef __FUNCT__
846 #define __FUNCT__ "MatMultTranspose_SeqAIJ"
847 int MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
848 {
849   PetscScalar  zero = 0.0;
850   int          ierr;
851 
852   PetscFunctionBegin;
853   ierr = VecSet(&zero,yy);CHKERRQ(ierr);
854   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
855   PetscFunctionReturn(0);
856 }
857 
858 
859 #undef __FUNCT__
860 #define __FUNCT__ "MatMult_SeqAIJ"
861 int MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
862 {
863   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
864   PetscScalar  *x,*y,*v;
865   int          ierr,m = A->m,*idx,*ii;
866 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
867   int          n,i,jrow,j;
868   PetscScalar  sum;
869 #endif
870 
871 #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
872 #pragma disjoint(*x,*y,*v)
873 #endif
874 
875   PetscFunctionBegin;
876   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
877   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
878   idx  = a->j;
879   v    = a->a;
880   ii   = a->i;
881 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
882   fortranmultaij_(&m,x,ii,idx,v,y);
883 #else
884   for (i=0; i<m; i++) {
885     jrow = ii[i];
886     n    = ii[i+1] - jrow;
887     sum  = 0.0;
888     for (j=0; j<n; j++) {
889       sum += v[jrow]*x[idx[jrow]]; jrow++;
890      }
891     y[i] = sum;
892   }
893 #endif
894   PetscLogFlops(2*a->nz - m);
895   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
896   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
897   PetscFunctionReturn(0);
898 }
899 
900 #undef __FUNCT__
901 #define __FUNCT__ "MatMultAdd_SeqAIJ"
902 int MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
903 {
904   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
905   PetscScalar  *x,*y,*z,*v;
906   int          ierr,m = A->m,*idx,*ii;
907 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
908   int          n,i,jrow,j;
909 PetscScalar    sum;
910 #endif
911 
912   PetscFunctionBegin;
913   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
914   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
915   if (zz != yy) {
916     ierr = VecGetArray(zz,&z);CHKERRQ(ierr);
917   } else {
918     z = y;
919   }
920 
921   idx  = a->j;
922   v    = a->a;
923   ii   = a->i;
924 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
925   fortranmultaddaij_(&m,x,ii,idx,v,y,z);
926 #else
927   for (i=0; i<m; i++) {
928     jrow = ii[i];
929     n    = ii[i+1] - jrow;
930     sum  = y[i];
931     for (j=0; j<n; j++) {
932       sum += v[jrow]*x[idx[jrow]]; jrow++;
933      }
934     z[i] = sum;
935   }
936 #endif
937   PetscLogFlops(2*a->nz);
938   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
939   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
940   if (zz != yy) {
941     ierr = VecRestoreArray(zz,&z);CHKERRQ(ierr);
942   }
943   PetscFunctionReturn(0);
944 }
945 
946 /*
947      Adds diagonal pointers to sparse matrix structure.
948 */
949 #undef __FUNCT__
950 #define __FUNCT__ "MatMarkDiagonal_SeqAIJ"
951 int MatMarkDiagonal_SeqAIJ(Mat A)
952 {
953   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
954   int        i,j,*diag,m = A->m,ierr;
955 
956   PetscFunctionBegin;
957   if (a->diag) PetscFunctionReturn(0);
958 
959   ierr = PetscMalloc((m+1)*sizeof(int),&diag);CHKERRQ(ierr);
960   PetscLogObjectMemory(A,(m+1)*sizeof(int));
961   for (i=0; i<A->m; i++) {
962     diag[i] = a->i[i+1];
963     for (j=a->i[i]; j<a->i[i+1]; j++) {
964       if (a->j[j] == i) {
965         diag[i] = j;
966         break;
967       }
968     }
969   }
970   a->diag = diag;
971   PetscFunctionReturn(0);
972 }
973 
974 /*
975      Checks for missing diagonals
976 */
977 #undef __FUNCT__
978 #define __FUNCT__ "MatMissingDiagonal_SeqAIJ"
979 int MatMissingDiagonal_SeqAIJ(Mat A)
980 {
981   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
982   int        *diag,*jj = a->j,i,ierr;
983 
984   PetscFunctionBegin;
985   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
986   diag = a->diag;
987   for (i=0; i<A->m; i++) {
988     if (jj[diag[i]] != i) {
989       SETERRQ1(1,"Matrix is missing diagonal number %d",i);
990     }
991   }
992   PetscFunctionReturn(0);
993 }
994 
995 #undef __FUNCT__
996 #define __FUNCT__ "MatRelax_SeqAIJ"
997 int MatRelax_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,int its,int lits,Vec xx)
998 {
999   Mat_SeqAIJ         *a = (Mat_SeqAIJ*)A->data;
1000   PetscScalar        *x,d,*xs,sum,*t,scale,*idiag=0,*mdiag;
1001   const PetscScalar  *v = a->a, *b, *bs,*xb, *ts;
1002   int                ierr,n = A->n,m = A->m,i;
1003   const int          *idx,*diag;
1004 
1005   PetscFunctionBegin;
1006   its = its*lits;
1007   if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %d and local its %d both positive",its,lits);
1008 
1009   if (!a->diag) {ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);}
1010   diag = a->diag;
1011   if (!a->idiag) {
1012     ierr     = PetscMalloc(3*m*sizeof(PetscScalar),&a->idiag);CHKERRQ(ierr);
1013     a->ssor  = a->idiag + m;
1014     mdiag    = a->ssor + m;
1015 
1016     v        = a->a;
1017 
1018     /* this is wrong when fshift omega changes each iteration */
1019     if (omega == 1.0 && fshift == 0.0) {
1020       for (i=0; i<m; i++) {
1021         mdiag[i]    = v[diag[i]];
1022         a->idiag[i] = 1.0/v[diag[i]];
1023       }
1024       PetscLogFlops(m);
1025     } else {
1026       for (i=0; i<m; i++) {
1027         mdiag[i]    = v[diag[i]];
1028         a->idiag[i] = omega/(fshift + v[diag[i]]);
1029       }
1030       PetscLogFlops(2*m);
1031     }
1032   }
1033   t     = a->ssor;
1034   idiag = a->idiag;
1035   mdiag = a->idiag + 2*m;
1036 
1037   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
1038   if (xx != bb) {
1039     ierr = VecGetArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);
1040   } else {
1041     b = x;
1042   }
1043 
1044   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
1045   xs   = x;
1046   if (flag == SOR_APPLY_UPPER) {
1047    /* apply (U + D/omega) to the vector */
1048     bs = b;
1049     for (i=0; i<m; i++) {
1050         d    = fshift + a->a[diag[i]];
1051         n    = a->i[i+1] - diag[i] - 1;
1052         idx  = a->j + diag[i] + 1;
1053         v    = a->a + diag[i] + 1;
1054         sum  = b[i]*d/omega;
1055         SPARSEDENSEDOT(sum,bs,v,idx,n);
1056         x[i] = sum;
1057     }
1058     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1059     if (bb != xx) {ierr = VecRestoreArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);}
1060     PetscLogFlops(a->nz);
1061     PetscFunctionReturn(0);
1062   }
1063 
1064 
1065     /* Let  A = L + U + D; where L is lower trianglar,
1066     U is upper triangular, E is diagonal; This routine applies
1067 
1068             (L + E)^{-1} A (U + E)^{-1}
1069 
1070     to a vector efficiently using Eisenstat's trick. This is for
1071     the case of SSOR preconditioner, so E is D/omega where omega
1072     is the relaxation factor.
1073     */
1074 
1075   if (flag == SOR_APPLY_LOWER) {
1076     SETERRQ(PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
1077   } else if (flag & SOR_EISENSTAT) {
1078     /* Let  A = L + U + D; where L is lower trianglar,
1079     U is upper triangular, E is diagonal; This routine applies
1080 
1081             (L + E)^{-1} A (U + E)^{-1}
1082 
1083     to a vector efficiently using Eisenstat's trick. This is for
1084     the case of SSOR preconditioner, so E is D/omega where omega
1085     is the relaxation factor.
1086     */
1087     scale = (2.0/omega) - 1.0;
1088 
1089     /*  x = (E + U)^{-1} b */
1090     for (i=m-1; i>=0; i--) {
1091       n    = a->i[i+1] - diag[i] - 1;
1092       idx  = a->j + diag[i] + 1;
1093       v    = a->a + diag[i] + 1;
1094       sum  = b[i];
1095       SPARSEDENSEMDOT(sum,xs,v,idx,n);
1096       x[i] = sum*idiag[i];
1097     }
1098 
1099     /*  t = b - (2*E - D)x */
1100     v = a->a;
1101     for (i=0; i<m; i++) { t[i] = b[i] - scale*(v[*diag++])*x[i]; }
1102 
1103     /*  t = (E + L)^{-1}t */
1104     ts = t;
1105     diag = a->diag;
1106     for (i=0; i<m; i++) {
1107       n    = diag[i] - a->i[i];
1108       idx  = a->j + a->i[i];
1109       v    = a->a + a->i[i];
1110       sum  = t[i];
1111       SPARSEDENSEMDOT(sum,ts,v,idx,n);
1112       t[i] = sum*idiag[i];
1113       /*  x = x + t */
1114       x[i] += t[i];
1115     }
1116 
1117     PetscLogFlops(6*m-1 + 2*a->nz);
1118     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1119     if (bb != xx) {ierr = VecRestoreArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);}
1120     PetscFunctionReturn(0);
1121   }
1122   if (flag & SOR_ZERO_INITIAL_GUESS) {
1123     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1124 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1125       fortranrelaxaijforwardzero_(&m,&omega,x,a->i,a->j,(int *)diag,idiag,a->a,(void*)b);
1126 #else
1127       for (i=0; i<m; i++) {
1128         n    = diag[i] - a->i[i];
1129         idx  = a->j + a->i[i];
1130         v    = a->a + a->i[i];
1131         sum  = b[i];
1132         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1133         x[i] = sum*idiag[i];
1134       }
1135 #endif
1136       xb = x;
1137       PetscLogFlops(a->nz);
1138     } else xb = b;
1139     if ((flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) &&
1140         (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP)) {
1141       for (i=0; i<m; i++) {
1142         x[i] *= mdiag[i];
1143       }
1144       PetscLogFlops(m);
1145     }
1146     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1147 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1148       fortranrelaxaijbackwardzero_(&m,&omega,x,a->i,a->j,(int*)diag,idiag,a->a,(void*)xb);
1149 #else
1150       for (i=m-1; i>=0; i--) {
1151         n    = a->i[i+1] - diag[i] - 1;
1152         idx  = a->j + diag[i] + 1;
1153         v    = a->a + diag[i] + 1;
1154         sum  = xb[i];
1155         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1156         x[i] = sum*idiag[i];
1157       }
1158 #endif
1159       PetscLogFlops(a->nz);
1160     }
1161     its--;
1162   }
1163   while (its--) {
1164     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1165 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1166       fortranrelaxaijforward_(&m,&omega,x,a->i,a->j,(int*)diag,a->a,(void*)b);
1167 #else
1168       for (i=0; i<m; i++) {
1169         d    = fshift + a->a[diag[i]];
1170         n    = a->i[i+1] - a->i[i];
1171         idx  = a->j + a->i[i];
1172         v    = a->a + a->i[i];
1173         sum  = b[i];
1174         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1175         x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1176       }
1177 #endif
1178       PetscLogFlops(a->nz);
1179     }
1180     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1181 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1182       fortranrelaxaijbackward_(&m,&omega,x,a->i,a->j,(int*)diag,a->a,(void*)b);
1183 #else
1184       for (i=m-1; i>=0; i--) {
1185         d    = fshift + a->a[diag[i]];
1186         n    = a->i[i+1] - a->i[i];
1187         idx  = a->j + a->i[i];
1188         v    = a->a + a->i[i];
1189         sum  = b[i];
1190         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1191         x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1192       }
1193 #endif
1194       PetscLogFlops(a->nz);
1195     }
1196   }
1197   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1198   if (bb != xx) {ierr = VecRestoreArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);}
1199   PetscFunctionReturn(0);
1200 }
1201 
1202 #undef __FUNCT__
1203 #define __FUNCT__ "MatGetInfo_SeqAIJ"
1204 int MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
1205 {
1206   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1207 
1208   PetscFunctionBegin;
1209   info->rows_global    = (double)A->m;
1210   info->columns_global = (double)A->n;
1211   info->rows_local     = (double)A->m;
1212   info->columns_local  = (double)A->n;
1213   info->block_size     = 1.0;
1214   info->nz_allocated   = (double)a->maxnz;
1215   info->nz_used        = (double)a->nz;
1216   info->nz_unneeded    = (double)(a->maxnz - a->nz);
1217   info->assemblies     = (double)A->num_ass;
1218   info->mallocs        = (double)a->reallocs;
1219   info->memory         = A->mem;
1220   if (A->factor) {
1221     info->fill_ratio_given  = A->info.fill_ratio_given;
1222     info->fill_ratio_needed = A->info.fill_ratio_needed;
1223     info->factor_mallocs    = A->info.factor_mallocs;
1224   } else {
1225     info->fill_ratio_given  = 0;
1226     info->fill_ratio_needed = 0;
1227     info->factor_mallocs    = 0;
1228   }
1229   PetscFunctionReturn(0);
1230 }
1231 
1232 #undef __FUNCT__
1233 #define __FUNCT__ "MatZeroRows_SeqAIJ"
1234 int MatZeroRows_SeqAIJ(Mat A,IS is,const PetscScalar *diag)
1235 {
1236   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1237   int         i,ierr,N,*rows,m = A->m - 1;
1238 
1239   PetscFunctionBegin;
1240   ierr = ISGetLocalSize(is,&N);CHKERRQ(ierr);
1241   ierr = ISGetIndices(is,&rows);CHKERRQ(ierr);
1242   if (a->keepzeroedrows) {
1243     for (i=0; i<N; i++) {
1244       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %d out of range", rows[i]);
1245       ierr = PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));CHKERRQ(ierr);
1246     }
1247     if (diag) {
1248       ierr = MatMissingDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1249       ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1250       for (i=0; i<N; i++) {
1251         a->a[a->diag[rows[i]]] = *diag;
1252       }
1253     }
1254   } else {
1255     if (diag) {
1256       for (i=0; i<N; i++) {
1257         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %d out of range", rows[i]);
1258         if (a->ilen[rows[i]] > 0) {
1259           a->ilen[rows[i]]          = 1;
1260           a->a[a->i[rows[i]]] = *diag;
1261           a->j[a->i[rows[i]]] = rows[i];
1262         } else { /* in case row was completely empty */
1263           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],diag,INSERT_VALUES);CHKERRQ(ierr);
1264         }
1265       }
1266     } else {
1267       for (i=0; i<N; i++) {
1268         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %d out of range", rows[i]);
1269         a->ilen[rows[i]] = 0;
1270       }
1271     }
1272   }
1273   ierr = ISRestoreIndices(is,&rows);CHKERRQ(ierr);
1274   ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1275   PetscFunctionReturn(0);
1276 }
1277 
1278 #undef __FUNCT__
1279 #define __FUNCT__ "MatGetRow_SeqAIJ"
1280 int MatGetRow_SeqAIJ(Mat A,int row,int *nz,int **idx,PetscScalar **v)
1281 {
1282   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1283   int        *itmp;
1284 
1285   PetscFunctionBegin;
1286   if (row < 0 || row >= A->m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Row %d out of range",row);
1287 
1288   *nz = a->i[row+1] - a->i[row];
1289   if (v) *v = a->a + a->i[row];
1290   if (idx) {
1291     itmp = a->j + a->i[row];
1292     if (*nz) {
1293       *idx = itmp;
1294     }
1295     else *idx = 0;
1296   }
1297   PetscFunctionReturn(0);
1298 }
1299 
1300 /* remove this function? */
1301 #undef __FUNCT__
1302 #define __FUNCT__ "MatRestoreRow_SeqAIJ"
1303 int MatRestoreRow_SeqAIJ(Mat A,int row,int *nz,int **idx,PetscScalar **v)
1304 {
1305   /* Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1306      int ierr; */
1307 
1308   PetscFunctionBegin;
1309   /* if (idx) {if (*idx && a->indexshift) {ierr = PetscFree(*idx);CHKERRQ(ierr);}} */
1310   PetscFunctionReturn(0);
1311 }
1312 
1313 #undef __FUNCT__
1314 #define __FUNCT__ "MatNorm_SeqAIJ"
1315 int MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
1316 {
1317   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
1318   PetscScalar  *v = a->a;
1319   PetscReal    sum = 0.0;
1320   int          i,j,ierr;
1321 
1322   PetscFunctionBegin;
1323   if (type == NORM_FROBENIUS) {
1324     for (i=0; i<a->nz; i++) {
1325 #if defined(PETSC_USE_COMPLEX)
1326       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1327 #else
1328       sum += (*v)*(*v); v++;
1329 #endif
1330     }
1331     *nrm = sqrt(sum);
1332   } else if (type == NORM_1) {
1333     PetscReal *tmp;
1334     int    *jj = a->j;
1335     ierr = PetscMalloc((A->n+1)*sizeof(PetscReal),&tmp);CHKERRQ(ierr);
1336     ierr = PetscMemzero(tmp,A->n*sizeof(PetscReal));CHKERRQ(ierr);
1337     *nrm = 0.0;
1338     for (j=0; j<a->nz; j++) {
1339         tmp[*jj++] += PetscAbsScalar(*v);  v++;
1340     }
1341     for (j=0; j<A->n; j++) {
1342       if (tmp[j] > *nrm) *nrm = tmp[j];
1343     }
1344     ierr = PetscFree(tmp);CHKERRQ(ierr);
1345   } else if (type == NORM_INFINITY) {
1346     *nrm = 0.0;
1347     for (j=0; j<A->m; j++) {
1348       v = a->a + a->i[j];
1349       sum = 0.0;
1350       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
1351         sum += PetscAbsScalar(*v); v++;
1352       }
1353       if (sum > *nrm) *nrm = sum;
1354     }
1355   } else {
1356     SETERRQ(PETSC_ERR_SUP,"No support for two norm");
1357   }
1358   PetscFunctionReturn(0);
1359 }
1360 
1361 #undef __FUNCT__
1362 #define __FUNCT__ "MatTranspose_SeqAIJ"
1363 int MatTranspose_SeqAIJ(Mat A,Mat *B)
1364 {
1365   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
1366   Mat          C;
1367   int          i,ierr,*aj = a->j,*ai = a->i,m = A->m,len,*col;
1368   PetscScalar  *array = a->a;
1369 
1370   PetscFunctionBegin;
1371   if (!B && m != A->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Square matrix only for in-place");
1372   ierr = PetscMalloc((1+A->n)*sizeof(int),&col);CHKERRQ(ierr);
1373   ierr = PetscMemzero(col,(1+A->n)*sizeof(int));CHKERRQ(ierr);
1374 
1375   for (i=0; i<ai[m]; i++) col[aj[i]] += 1;
1376   ierr = MatCreate(A->comm,A->n,m,A->n,m,&C);CHKERRQ(ierr);
1377   ierr = MatSetType(C,A->type_name);CHKERRQ(ierr);
1378   ierr = MatSeqAIJSetPreallocation(C,0,col);CHKERRQ(ierr);
1379   ierr = PetscFree(col);CHKERRQ(ierr);
1380   for (i=0; i<m; i++) {
1381     len    = ai[i+1]-ai[i];
1382     ierr   = MatSetValues(C,len,aj,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1383     array += len;
1384     aj    += len;
1385   }
1386 
1387   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1388   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1389 
1390   if (B) {
1391     *B = C;
1392   } else {
1393     ierr = MatHeaderCopy(A,C);CHKERRQ(ierr);
1394   }
1395   PetscFunctionReturn(0);
1396 }
1397 
1398 EXTERN_C_BEGIN
1399 #undef __FUNCT__
1400 #define __FUNCT__ "MatIsTranspose_SeqAIJ"
1401 int MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscTruth *f)
1402 {
1403   Mat_SeqAIJ *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1404   int *adx,*bdx,*aii,*bii,*aptr,*bptr; PetscScalar *va,*vb;
1405   int ma,na,mb,nb, i,ierr;
1406 
1407   PetscFunctionBegin;
1408   bij = (Mat_SeqAIJ *) B->data;
1409 
1410   ierr = MatGetSize(A,&ma,&na); CHKERRQ(ierr);
1411   ierr = MatGetSize(B,&mb,&nb); CHKERRQ(ierr);
1412   if (ma!=nb || na!=mb)
1413     SETERRQ(1,"Incompatible A/B sizes for symmetry test");
1414   aii = aij->i; bii = bij->i;
1415   adx = aij->j; bdx = bij->j;
1416   va = aij->a; vb = bij->a;
1417   ierr = PetscMalloc(ma*sizeof(int),&aptr); CHKERRQ(ierr);
1418   ierr = PetscMalloc(mb*sizeof(int),&bptr); CHKERRQ(ierr);
1419   for (i=0; i<ma; i++) aptr[i] = aii[i];
1420   for (i=0; i<mb; i++) bptr[i] = bii[i];
1421 
1422   *f = PETSC_TRUE;
1423   for (i=0; i<ma; i++) {
1424     /*printf("row %d spans %d--%d; we start @ %d\n",
1425       i,idx[ii[i]],idx[ii[i+1]-1],idx[aptr[i]]);*/
1426     while (aptr[i]<aii[i+1]) {
1427       int idc,idr; PetscScalar vc,vr;
1428       /* column/row index/value */
1429       idc = adx[aptr[i]]; idr = bdx[bptr[idc]];
1430       vc = va[aptr[i]]; vr = vb[bptr[idc]];
1431       /*printf("comparing %d: (%d,%d)=%e to (%d,%d)=%e\n",
1432 	aptr[i],i,idc,vc,idc,idr,vr);*/
1433       if (i!=idr || vc!=vr) {
1434 	*f = PETSC_FALSE; goto done;
1435       } else {
1436 	aptr[i]++; if (B || i!=idc) bptr[idc]++;
1437       }
1438     }
1439   }
1440  done:
1441   ierr = PetscFree(aptr); CHKERRQ(ierr);
1442   if (B) {
1443     ierr = PetscFree(bptr); CHKERRQ(ierr);
1444   }
1445 
1446   PetscFunctionReturn(0);
1447 }
1448 EXTERN_C_END
1449 
1450 #undef __FUNCT__
1451 #define __FUNCT__ "MatIsSymmetric_SeqAIJ"
1452 int MatIsSymmetric_SeqAIJ(Mat A,PetscTruth *f)
1453 {
1454   int ierr;
1455   PetscFunctionBegin;
1456   ierr = MatIsTranspose_SeqAIJ(A,A,f); CHKERRQ(ierr);
1457   PetscFunctionReturn(0);
1458 }
1459 
1460 #undef __FUNCT__
1461 #define __FUNCT__ "MatDiagonalScale_SeqAIJ"
1462 int MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
1463 {
1464   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
1465   PetscScalar  *l,*r,x,*v;
1466   int          ierr,i,j,m = A->m,n = A->n,M,nz = a->nz,*jj;
1467 
1468   PetscFunctionBegin;
1469   if (ll) {
1470     /* The local size is used so that VecMPI can be passed to this routine
1471        by MatDiagonalScale_MPIAIJ */
1472     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
1473     if (m != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
1474     ierr = VecGetArray(ll,&l);CHKERRQ(ierr);
1475     v = a->a;
1476     for (i=0; i<m; i++) {
1477       x = l[i];
1478       M = a->i[i+1] - a->i[i];
1479       for (j=0; j<M; j++) { (*v++) *= x;}
1480     }
1481     ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr);
1482     PetscLogFlops(nz);
1483   }
1484   if (rr) {
1485     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
1486     if (n != A->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
1487     ierr = VecGetArray(rr,&r);CHKERRQ(ierr);
1488     v = a->a; jj = a->j;
1489     for (i=0; i<nz; i++) {
1490       (*v++) *= r[*jj++];
1491     }
1492     ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr);
1493     PetscLogFlops(nz);
1494   }
1495   PetscFunctionReturn(0);
1496 }
1497 
1498 #undef __FUNCT__
1499 #define __FUNCT__ "MatGetSubMatrix_SeqAIJ"
1500 int MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,int csize,MatReuse scall,Mat *B)
1501 {
1502   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data,*c;
1503   int          *smap,i,k,kstart,kend,ierr,oldcols = A->n,*lens;
1504   int          row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
1505   int          *irow,*icol,nrows,ncols;
1506   int          *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
1507   PetscScalar  *a_new,*mat_a;
1508   Mat          C;
1509   PetscTruth   stride;
1510 
1511   PetscFunctionBegin;
1512   ierr = ISSorted(isrow,(PetscTruth*)&i);CHKERRQ(ierr);
1513   if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted");
1514   ierr = ISSorted(iscol,(PetscTruth*)&i);CHKERRQ(ierr);
1515   if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted");
1516 
1517   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
1518   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
1519   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
1520 
1521   ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
1522   ierr = ISStride(iscol,&stride);CHKERRQ(ierr);
1523   if (stride && step == 1) {
1524     /* special case of contiguous rows */
1525     ierr   = PetscMalloc((2*nrows+1)*sizeof(int),&lens);CHKERRQ(ierr);
1526     starts = lens + nrows;
1527     /* loop over new rows determining lens and starting points */
1528     for (i=0; i<nrows; i++) {
1529       kstart  = ai[irow[i]];
1530       kend    = kstart + ailen[irow[i]];
1531       for (k=kstart; k<kend; k++) {
1532         if (aj[k] >= first) {
1533           starts[i] = k;
1534           break;
1535 	}
1536       }
1537       sum = 0;
1538       while (k < kend) {
1539         if (aj[k++] >= first+ncols) break;
1540         sum++;
1541       }
1542       lens[i] = sum;
1543     }
1544     /* create submatrix */
1545     if (scall == MAT_REUSE_MATRIX) {
1546       int n_cols,n_rows;
1547       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
1548       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
1549       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
1550       C = *B;
1551     } else {
1552       ierr = MatCreate(A->comm,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE,&C);CHKERRQ(ierr);
1553       ierr = MatSetType(C,A->type_name);CHKERRQ(ierr);
1554       ierr = MatSeqAIJSetPreallocation(C,0,lens);CHKERRQ(ierr);
1555     }
1556     c = (Mat_SeqAIJ*)C->data;
1557 
1558     /* loop over rows inserting into submatrix */
1559     a_new    = c->a;
1560     j_new    = c->j;
1561     i_new    = c->i;
1562 
1563     for (i=0; i<nrows; i++) {
1564       ii    = starts[i];
1565       lensi = lens[i];
1566       for (k=0; k<lensi; k++) {
1567         *j_new++ = aj[ii+k] - first;
1568       }
1569       ierr = PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));CHKERRQ(ierr);
1570       a_new      += lensi;
1571       i_new[i+1]  = i_new[i] + lensi;
1572       c->ilen[i]  = lensi;
1573     }
1574     ierr = PetscFree(lens);CHKERRQ(ierr);
1575   } else {
1576     ierr  = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
1577     ierr  = PetscMalloc((1+oldcols)*sizeof(int),&smap);CHKERRQ(ierr);
1578 
1579     ierr  = PetscMalloc((1+nrows)*sizeof(int),&lens);CHKERRQ(ierr);
1580     ierr  = PetscMemzero(smap,oldcols*sizeof(int));CHKERRQ(ierr);
1581     for (i=0; i<ncols; i++) smap[icol[i]] = i+1;
1582     /* determine lens of each row */
1583     for (i=0; i<nrows; i++) {
1584       kstart  = ai[irow[i]];
1585       kend    = kstart + a->ilen[irow[i]];
1586       lens[i] = 0;
1587       for (k=kstart; k<kend; k++) {
1588         if (smap[aj[k]]) {
1589           lens[i]++;
1590         }
1591       }
1592     }
1593     /* Create and fill new matrix */
1594     if (scall == MAT_REUSE_MATRIX) {
1595       PetscTruth equal;
1596 
1597       c = (Mat_SeqAIJ *)((*B)->data);
1598       if ((*B)->m  != nrows || (*B)->n != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
1599       ierr = PetscMemcmp(c->ilen,lens,(*B)->m*sizeof(int),&equal);CHKERRQ(ierr);
1600       if (!equal) {
1601         SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
1602       }
1603       ierr = PetscMemzero(c->ilen,(*B)->m*sizeof(int));CHKERRQ(ierr);
1604       C = *B;
1605     } else {
1606       ierr = MatCreate(A->comm,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE,&C);CHKERRQ(ierr);
1607       ierr = MatSetType(C,A->type_name);CHKERRQ(ierr);
1608       ierr = MatSeqAIJSetPreallocation(C,0,lens);CHKERRQ(ierr);
1609     }
1610     c = (Mat_SeqAIJ *)(C->data);
1611     for (i=0; i<nrows; i++) {
1612       row    = irow[i];
1613       kstart = ai[row];
1614       kend   = kstart + a->ilen[row];
1615       mat_i  = c->i[i];
1616       mat_j  = c->j + mat_i;
1617       mat_a  = c->a + mat_i;
1618       mat_ilen = c->ilen + i;
1619       for (k=kstart; k<kend; k++) {
1620         if ((tcol=smap[a->j[k]])) {
1621           *mat_j++ = tcol - 1;
1622           *mat_a++ = a->a[k];
1623           (*mat_ilen)++;
1624 
1625         }
1626       }
1627     }
1628     /* Free work space */
1629     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
1630     ierr = PetscFree(smap);CHKERRQ(ierr);
1631     ierr = PetscFree(lens);CHKERRQ(ierr);
1632   }
1633   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1634   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1635 
1636   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
1637   *B = C;
1638   PetscFunctionReturn(0);
1639 }
1640 
1641 /*
1642 */
1643 #undef __FUNCT__
1644 #define __FUNCT__ "MatILUFactor_SeqAIJ"
1645 int MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,MatFactorInfo *info)
1646 {
1647   Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data;
1648   int        ierr;
1649   Mat        outA;
1650   PetscTruth row_identity,col_identity;
1651 
1652   PetscFunctionBegin;
1653   if (info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
1654   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
1655   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
1656   if (!row_identity || !col_identity) {
1657     SETERRQ(1,"Row and column permutations must be identity for in-place ILU");
1658   }
1659 
1660   outA          = inA;
1661   inA->factor   = FACTOR_LU;
1662   a->row        = row;
1663   a->col        = col;
1664   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
1665   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
1666 
1667   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
1668   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} /* need to remove old one */
1669   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
1670   PetscLogObjectParent(inA,a->icol);
1671 
1672   if (!a->solve_work) { /* this matrix may have been factored before */
1673      ierr = PetscMalloc((inA->m+1)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr);
1674   }
1675 
1676   if (!a->diag) {
1677     ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
1678   }
1679   ierr = MatLUFactorNumeric_SeqAIJ(inA,&outA);CHKERRQ(ierr);
1680   PetscFunctionReturn(0);
1681 }
1682 
1683 #include "petscblaslapack.h"
1684 #undef __FUNCT__
1685 #define __FUNCT__ "MatScale_SeqAIJ"
1686 int MatScale_SeqAIJ(const PetscScalar *alpha,Mat inA)
1687 {
1688   Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data;
1689   int        one = 1;
1690 
1691   PetscFunctionBegin;
1692   BLscal_(&a->nz,(PetscScalar*)alpha,a->a,&one);
1693   PetscLogFlops(a->nz);
1694   PetscFunctionReturn(0);
1695 }
1696 
1697 #undef __FUNCT__
1698 #define __FUNCT__ "MatGetSubMatrices_SeqAIJ"
1699 int MatGetSubMatrices_SeqAIJ(Mat A,int n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
1700 {
1701   int ierr,i;
1702 
1703   PetscFunctionBegin;
1704   if (scall == MAT_INITIAL_MATRIX) {
1705     ierr = PetscMalloc((n+1)*sizeof(Mat),B);CHKERRQ(ierr);
1706   }
1707 
1708   for (i=0; i<n; i++) {
1709     ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
1710   }
1711   PetscFunctionReturn(0);
1712 }
1713 
1714 #undef __FUNCT__
1715 #define __FUNCT__ "MatGetBlockSize_SeqAIJ"
1716 int MatGetBlockSize_SeqAIJ(Mat A,int *bs)
1717 {
1718   PetscFunctionBegin;
1719   *bs = 1;
1720   PetscFunctionReturn(0);
1721 }
1722 
1723 #undef __FUNCT__
1724 #define __FUNCT__ "MatIncreaseOverlap_SeqAIJ"
1725 int MatIncreaseOverlap_SeqAIJ(Mat A,int is_max,IS is[],int ov)
1726 {
1727   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1728   int        row,i,j,k,l,m,n,*idx,ierr,*nidx,isz,val;
1729   int        start,end,*ai,*aj;
1730   PetscBT    table;
1731 
1732   PetscFunctionBegin;
1733   m     = A->m;
1734   ai    = a->i;
1735   aj    = a->j;
1736 
1737   if (ov < 0)  SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
1738 
1739   ierr = PetscMalloc((m+1)*sizeof(int),&nidx);CHKERRQ(ierr);
1740   ierr = PetscBTCreate(m,table);CHKERRQ(ierr);
1741 
1742   for (i=0; i<is_max; i++) {
1743     /* Initialize the two local arrays */
1744     isz  = 0;
1745     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
1746 
1747     /* Extract the indices, assume there can be duplicate entries */
1748     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
1749     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
1750 
1751     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
1752     for (j=0; j<n ; ++j){
1753       if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];}
1754     }
1755     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
1756     ierr = ISDestroy(is[i]);CHKERRQ(ierr);
1757 
1758     k = 0;
1759     for (j=0; j<ov; j++){ /* for each overlap */
1760       n = isz;
1761       for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
1762         row   = nidx[k];
1763         start = ai[row];
1764         end   = ai[row+1];
1765         for (l = start; l<end ; l++){
1766           val = aj[l] ;
1767           if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;}
1768         }
1769       }
1770     }
1771     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,(is+i));CHKERRQ(ierr);
1772   }
1773   ierr = PetscBTDestroy(table);CHKERRQ(ierr);
1774   ierr = PetscFree(nidx);CHKERRQ(ierr);
1775   PetscFunctionReturn(0);
1776 }
1777 
1778 /* -------------------------------------------------------------- */
1779 #undef __FUNCT__
1780 #define __FUNCT__ "MatPermute_SeqAIJ"
1781 int MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
1782 {
1783   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
1784   PetscScalar  *vwork;
1785   int          i,ierr,nz,m = A->m,n = A->n,*cwork;
1786   int          *row,*col,*cnew,j,*lens;
1787   IS           icolp,irowp;
1788 
1789   PetscFunctionBegin;
1790   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
1791   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
1792   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
1793   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
1794 
1795   /* determine lengths of permuted rows */
1796   ierr = PetscMalloc((m+1)*sizeof(int),&lens);CHKERRQ(ierr);
1797   for (i=0; i<m; i++) {
1798     lens[row[i]] = a->i[i+1] - a->i[i];
1799   }
1800   ierr = MatCreate(A->comm,m,n,m,n,B);CHKERRQ(ierr);
1801   ierr = MatSetType(*B,A->type_name);CHKERRQ(ierr);
1802   ierr = MatSeqAIJSetPreallocation(*B,0,lens);CHKERRQ(ierr);
1803   ierr = PetscFree(lens);CHKERRQ(ierr);
1804 
1805   ierr = PetscMalloc(n*sizeof(int),&cnew);CHKERRQ(ierr);
1806   for (i=0; i<m; i++) {
1807     ierr = MatGetRow(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
1808     for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];}
1809     ierr = MatSetValues(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
1810     ierr = MatRestoreRow(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
1811   }
1812   ierr = PetscFree(cnew);CHKERRQ(ierr);
1813   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1814   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1815   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
1816   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
1817   ierr = ISDestroy(irowp);CHKERRQ(ierr);
1818   ierr = ISDestroy(icolp);CHKERRQ(ierr);
1819   PetscFunctionReturn(0);
1820 }
1821 
1822 #undef __FUNCT__
1823 #define __FUNCT__ "MatPrintHelp_SeqAIJ"
1824 int MatPrintHelp_SeqAIJ(Mat A)
1825 {
1826   static PetscTruth called = PETSC_FALSE;
1827   MPI_Comm          comm = A->comm;
1828   int               ierr;
1829 
1830   PetscFunctionBegin;
1831   if (called) {PetscFunctionReturn(0);} else called = PETSC_TRUE;
1832   ierr = (*PetscHelpPrintf)(comm," Options for MATSEQAIJ and MATMPIAIJ matrix formats (the defaults):\n");CHKERRQ(ierr);
1833   ierr = (*PetscHelpPrintf)(comm,"  -mat_lu_pivotthreshold <threshold>: Set pivoting threshold\n");CHKERRQ(ierr);
1834   ierr = (*PetscHelpPrintf)(comm,"  -mat_aij_oneindex: internal indices begin at 1 instead of the default 0.\n");CHKERRQ(ierr);
1835   ierr = (*PetscHelpPrintf)(comm,"  -mat_aij_no_inode: Do not use inodes\n");CHKERRQ(ierr);
1836   ierr = (*PetscHelpPrintf)(comm,"  -mat_aij_inode_limit <limit>: Set inode limit (max limit=5)\n");CHKERRQ(ierr);
1837 #if defined(PETSC_HAVE_MATLAB) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
1838   ierr = (*PetscHelpPrintf)(comm,"  -mat_aij_matlab: Use Matlab engine sparse LU factorization and solve.\n");CHKERRQ(ierr);
1839 #endif
1840   PetscFunctionReturn(0);
1841 }
1842 
1843 #undef __FUNCT__
1844 #define __FUNCT__ "MatCopy_SeqAIJ"
1845 int MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
1846 {
1847   int        ierr;
1848 
1849   PetscFunctionBegin;
1850   /* If the two matrices have the same copy implementation, use fast copy. */
1851   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
1852     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1853     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
1854 
1855     if (a->i[A->m] != b->i[B->m]) {
1856       SETERRQ(1,"Number of nonzeros in two matrices are different");
1857     }
1858     ierr = PetscMemcpy(b->a,a->a,(a->i[A->m])*sizeof(PetscScalar));CHKERRQ(ierr);
1859   } else {
1860     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
1861   }
1862   PetscFunctionReturn(0);
1863 }
1864 
1865 #undef __FUNCT__
1866 #define __FUNCT__ "MatSetUpPreallocation_SeqAIJ"
1867 int MatSetUpPreallocation_SeqAIJ(Mat A)
1868 {
1869   int        ierr;
1870 
1871   PetscFunctionBegin;
1872   ierr =  MatSeqAIJSetPreallocation(A,PETSC_DEFAULT,0);CHKERRQ(ierr);
1873   PetscFunctionReturn(0);
1874 }
1875 
1876 #undef __FUNCT__
1877 #define __FUNCT__ "MatGetArray_SeqAIJ"
1878 int MatGetArray_SeqAIJ(Mat A,PetscScalar *array[])
1879 {
1880   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1881   PetscFunctionBegin;
1882   *array = a->a;
1883   PetscFunctionReturn(0);
1884 }
1885 
1886 #undef __FUNCT__
1887 #define __FUNCT__ "MatRestoreArray_SeqAIJ"
1888 int MatRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
1889 {
1890   PetscFunctionBegin;
1891   PetscFunctionReturn(0);
1892 }
1893 
1894 #undef __FUNCT__
1895 #define __FUNCT__ "MatFDColoringApply_SeqAIJ"
1896 int MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
1897 {
1898   int           (*f)(void *,Vec,Vec,void*) = (int (*)(void *,Vec,Vec,void *))coloring->f;
1899   int           k,ierr,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
1900   PetscScalar   dx,mone = -1.0,*y,*xx,*w3_array;
1901   PetscScalar   *vscale_array;
1902   PetscReal     epsilon = coloring->error_rel,umin = coloring->umin;
1903   Vec           w1,w2,w3;
1904   void          *fctx = coloring->fctx;
1905   PetscTruth    flg;
1906 
1907   PetscFunctionBegin;
1908   if (!coloring->w1) {
1909     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
1910     PetscLogObjectParent(coloring,coloring->w1);
1911     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
1912     PetscLogObjectParent(coloring,coloring->w2);
1913     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
1914     PetscLogObjectParent(coloring,coloring->w3);
1915   }
1916   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
1917 
1918   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
1919   ierr = PetscOptionsHasName(coloring->prefix,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
1920   if (flg) {
1921     PetscLogInfo(coloring,"MatFDColoringApply_SeqAIJ: Not calling MatZeroEntries()\n");
1922   } else {
1923     ierr = MatZeroEntries(J);CHKERRQ(ierr);
1924   }
1925 
1926   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
1927   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
1928 
1929   /*
1930        This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets
1931      coloring->F for the coarser grids from the finest
1932   */
1933   if (coloring->F) {
1934     ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr);
1935     ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr);
1936     if (m1 != m2) {
1937       coloring->F = 0;
1938     }
1939   }
1940 
1941   if (coloring->F) {
1942     w1          = coloring->F;
1943     coloring->F = 0;
1944   } else {
1945     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
1946     ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr);
1947     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
1948   }
1949 
1950   /*
1951       Compute all the scale factors and share with other processors
1952   */
1953   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
1954   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
1955   for (k=0; k<coloring->ncolors; k++) {
1956     /*
1957        Loop over each column associated with color adding the
1958        perturbation to the vector w3.
1959     */
1960     for (l=0; l<coloring->ncolumns[k]; l++) {
1961       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
1962       dx  = xx[col];
1963       if (dx == 0.0) dx = 1.0;
1964 #if !defined(PETSC_USE_COMPLEX)
1965       if (dx < umin && dx >= 0.0)      dx = umin;
1966       else if (dx < 0.0 && dx > -umin) dx = -umin;
1967 #else
1968       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
1969       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
1970 #endif
1971       dx                *= epsilon;
1972       vscale_array[col] = 1.0/dx;
1973     }
1974   }
1975   vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
1976   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1977   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1978 
1979   /*  ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
1980       ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/
1981 
1982   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
1983   else                        vscaleforrow = coloring->columnsforrow;
1984 
1985   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
1986   /*
1987       Loop over each color
1988   */
1989   for (k=0; k<coloring->ncolors; k++) {
1990     coloring->currentcolor = k;
1991     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
1992     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
1993     /*
1994        Loop over each column associated with color adding the
1995        perturbation to the vector w3.
1996     */
1997     for (l=0; l<coloring->ncolumns[k]; l++) {
1998       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
1999       dx  = xx[col];
2000       if (dx == 0.0) dx = 1.0;
2001 #if !defined(PETSC_USE_COMPLEX)
2002       if (dx < umin && dx >= 0.0)      dx = umin;
2003       else if (dx < 0.0 && dx > -umin) dx = -umin;
2004 #else
2005       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
2006       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2007 #endif
2008       dx            *= epsilon;
2009       if (!PetscAbsScalar(dx)) SETERRQ(1,"Computed 0 differencing parameter");
2010       w3_array[col] += dx;
2011     }
2012     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
2013 
2014     /*
2015        Evaluate function at x1 + dx (here dx is a vector of perturbations)
2016     */
2017 
2018     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2019     ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
2020     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2021     ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
2022 
2023     /*
2024        Loop over rows of vector, putting results into Jacobian matrix
2025     */
2026     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
2027     for (l=0; l<coloring->nrows[k]; l++) {
2028       row    = coloring->rows[k][l];
2029       col    = coloring->columnsforrow[k][l];
2030       y[row] *= vscale_array[vscaleforrow[k][l]];
2031       srow   = row + start;
2032       ierr   = MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
2033     }
2034     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
2035   }
2036   coloring->currentcolor = k;
2037   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
2038   xx = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
2039   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2040   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2041   PetscFunctionReturn(0);
2042 }
2043 
2044 #include "petscblaslapack.h"
2045 #undef __FUNCT__
2046 #define __FUNCT__ "MatAXPY_SeqAIJ"
2047 int MatAXPY_SeqAIJ(const PetscScalar a[],Mat X,Mat Y,MatStructure str)
2048 {
2049   int        ierr,one=1,i;
2050   Mat_SeqAIJ *x  = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data;
2051 
2052   PetscFunctionBegin;
2053   if (str == SAME_NONZERO_PATTERN) {
2054     BLaxpy_(&x->nz,(PetscScalar*)a,x->a,&one,y->a,&one);
2055   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2056     if (y->xtoy && y->XtoY != X) {
2057       ierr = PetscFree(y->xtoy);CHKERRQ(ierr);
2058       ierr = MatDestroy(y->XtoY);CHKERRQ(ierr);
2059     }
2060     if (!y->xtoy) { /* get xtoy */
2061       ierr = MatAXPYGetxtoy_Private(X->m,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr);
2062       y->XtoY = X;
2063     }
2064     for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += (*a)*(x->a[i]);
2065     PetscLogInfo(0,"MatAXPY_SeqAIJ: ratio of nnz(X)/nnz(Y): %d/%d = %g\n",x->nz,y->nz,(PetscReal)(x->nz)/y->nz);
2066   } else {
2067     ierr = MatAXPY_Basic(a,X,Y,str);CHKERRQ(ierr);
2068   }
2069   PetscFunctionReturn(0);
2070 }
2071 
2072 /* -------------------------------------------------------------------*/
2073 static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
2074        MatGetRow_SeqAIJ,
2075        MatRestoreRow_SeqAIJ,
2076        MatMult_SeqAIJ,
2077 /* 4*/ MatMultAdd_SeqAIJ,
2078        MatMultTranspose_SeqAIJ,
2079        MatMultTransposeAdd_SeqAIJ,
2080        MatSolve_SeqAIJ,
2081        MatSolveAdd_SeqAIJ,
2082        MatSolveTranspose_SeqAIJ,
2083 /*10*/ MatSolveTransposeAdd_SeqAIJ,
2084        MatLUFactor_SeqAIJ,
2085        0,
2086        MatRelax_SeqAIJ,
2087        MatTranspose_SeqAIJ,
2088 /*15*/ MatGetInfo_SeqAIJ,
2089        MatEqual_SeqAIJ,
2090        MatGetDiagonal_SeqAIJ,
2091        MatDiagonalScale_SeqAIJ,
2092        MatNorm_SeqAIJ,
2093 /*20*/ 0,
2094        MatAssemblyEnd_SeqAIJ,
2095        MatCompress_SeqAIJ,
2096        MatSetOption_SeqAIJ,
2097        MatZeroEntries_SeqAIJ,
2098 /*25*/ MatZeroRows_SeqAIJ,
2099        MatLUFactorSymbolic_SeqAIJ,
2100        MatLUFactorNumeric_SeqAIJ,
2101        MatCholeskyFactorSymbolic_SeqAIJ,
2102        MatCholeskyFactorNumeric_SeqAIJ,
2103 /*30*/ MatSetUpPreallocation_SeqAIJ,
2104        MatILUFactorSymbolic_SeqAIJ,
2105        MatICCFactorSymbolic_SeqAIJ,
2106        MatGetArray_SeqAIJ,
2107        MatRestoreArray_SeqAIJ,
2108 /*35*/ MatDuplicate_SeqAIJ,
2109        0,
2110        0,
2111        MatILUFactor_SeqAIJ,
2112        0,
2113 /*40*/ MatAXPY_SeqAIJ,
2114        MatGetSubMatrices_SeqAIJ,
2115        MatIncreaseOverlap_SeqAIJ,
2116        MatGetValues_SeqAIJ,
2117        MatCopy_SeqAIJ,
2118 /*45*/ MatPrintHelp_SeqAIJ,
2119        MatScale_SeqAIJ,
2120        0,
2121        0,
2122        MatILUDTFactor_SeqAIJ,
2123 /*50*/ MatGetBlockSize_SeqAIJ,
2124        MatGetRowIJ_SeqAIJ,
2125        MatRestoreRowIJ_SeqAIJ,
2126        MatGetColumnIJ_SeqAIJ,
2127        MatRestoreColumnIJ_SeqAIJ,
2128 /*55*/ MatFDColoringCreate_SeqAIJ,
2129        0,
2130        0,
2131        MatPermute_SeqAIJ,
2132        0,
2133 /*60*/ 0,
2134        MatDestroy_SeqAIJ,
2135        MatView_SeqAIJ,
2136        MatGetPetscMaps_Petsc,
2137        0,
2138 /*65*/ 0,
2139        0,
2140        0,
2141        0,
2142        0,
2143 /*70*/ 0,
2144        0,
2145        MatSetColoring_SeqAIJ,
2146        MatSetValuesAdic_SeqAIJ,
2147        MatSetValuesAdifor_SeqAIJ,
2148 /*75*/ MatFDColoringApply_SeqAIJ,
2149        0,
2150        0,
2151        0,
2152        0,
2153 /*80*/ 0,
2154        0,
2155        0,
2156        0,
2157 /*85*/ MatLoad_SeqAIJ,
2158        MatIsSymmetric_SeqAIJ,
2159 };
2160 
2161 EXTERN_C_BEGIN
2162 #undef __FUNCT__
2163 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ"
2164 int MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,int *indices)
2165 {
2166   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2167   int        i,nz,n;
2168 
2169   PetscFunctionBegin;
2170 
2171   nz = aij->maxnz;
2172   n  = mat->n;
2173   for (i=0; i<nz; i++) {
2174     aij->j[i] = indices[i];
2175   }
2176   aij->nz = nz;
2177   for (i=0; i<n; i++) {
2178     aij->ilen[i] = aij->imax[i];
2179   }
2180 
2181   PetscFunctionReturn(0);
2182 }
2183 EXTERN_C_END
2184 
2185 #undef __FUNCT__
2186 #define __FUNCT__ "MatSeqAIJSetColumnIndices"
2187 /*@
2188     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
2189        in the matrix.
2190 
2191   Input Parameters:
2192 +  mat - the SeqAIJ matrix
2193 -  indices - the column indices
2194 
2195   Level: advanced
2196 
2197   Notes:
2198     This can be called if you have precomputed the nonzero structure of the
2199   matrix and want to provide it to the matrix object to improve the performance
2200   of the MatSetValues() operation.
2201 
2202     You MUST have set the correct numbers of nonzeros per row in the call to
2203   MatCreateSeqAIJ().
2204 
2205     MUST be called before any calls to MatSetValues();
2206 
2207     The indices should start with zero, not one.
2208 
2209 @*/
2210 int MatSeqAIJSetColumnIndices(Mat mat,int *indices)
2211 {
2212   int ierr,(*f)(Mat,int *);
2213 
2214   PetscFunctionBegin;
2215   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2216   PetscValidPointer(indices,2);
2217   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr);
2218   if (f) {
2219     ierr = (*f)(mat,indices);CHKERRQ(ierr);
2220   } else {
2221     SETERRQ(1,"Wrong type of matrix to set column indices");
2222   }
2223   PetscFunctionReturn(0);
2224 }
2225 
2226 /* ----------------------------------------------------------------------------------------*/
2227 
2228 EXTERN_C_BEGIN
2229 #undef __FUNCT__
2230 #define __FUNCT__ "MatStoreValues_SeqAIJ"
2231 int MatStoreValues_SeqAIJ(Mat mat)
2232 {
2233   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2234   size_t       nz = aij->i[mat->m],ierr;
2235 
2236   PetscFunctionBegin;
2237   if (aij->nonew != 1) {
2238     SETERRQ(1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
2239   }
2240 
2241   /* allocate space for values if not already there */
2242   if (!aij->saved_values) {
2243     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
2244   }
2245 
2246   /* copy values over */
2247   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2248   PetscFunctionReturn(0);
2249 }
2250 EXTERN_C_END
2251 
2252 #undef __FUNCT__
2253 #define __FUNCT__ "MatStoreValues"
2254 /*@
2255     MatStoreValues - Stashes a copy of the matrix values; this allows, for
2256        example, reuse of the linear part of a Jacobian, while recomputing the
2257        nonlinear portion.
2258 
2259    Collect on Mat
2260 
2261   Input Parameters:
2262 .  mat - the matrix (currently on AIJ matrices support this option)
2263 
2264   Level: advanced
2265 
2266   Common Usage, with SNESSolve():
2267 $    Create Jacobian matrix
2268 $    Set linear terms into matrix
2269 $    Apply boundary conditions to matrix, at this time matrix must have
2270 $      final nonzero structure (i.e. setting the nonlinear terms and applying
2271 $      boundary conditions again will not change the nonzero structure
2272 $    ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS);
2273 $    ierr = MatStoreValues(mat);
2274 $    Call SNESSetJacobian() with matrix
2275 $    In your Jacobian routine
2276 $      ierr = MatRetrieveValues(mat);
2277 $      Set nonlinear terms in matrix
2278 
2279   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
2280 $    // build linear portion of Jacobian
2281 $    ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS);
2282 $    ierr = MatStoreValues(mat);
2283 $    loop over nonlinear iterations
2284 $       ierr = MatRetrieveValues(mat);
2285 $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
2286 $       // call MatAssemblyBegin/End() on matrix
2287 $       Solve linear system with Jacobian
2288 $    endloop
2289 
2290   Notes:
2291     Matrix must already be assemblied before calling this routine
2292     Must set the matrix option MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS); before
2293     calling this routine.
2294 
2295 .seealso: MatRetrieveValues()
2296 
2297 @*/
2298 int MatStoreValues(Mat mat)
2299 {
2300   int ierr,(*f)(Mat);
2301 
2302   PetscFunctionBegin;
2303   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2304   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2305   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2306 
2307   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatStoreValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2308   if (f) {
2309     ierr = (*f)(mat);CHKERRQ(ierr);
2310   } else {
2311     SETERRQ(1,"Wrong type of matrix to store values");
2312   }
2313   PetscFunctionReturn(0);
2314 }
2315 
2316 EXTERN_C_BEGIN
2317 #undef __FUNCT__
2318 #define __FUNCT__ "MatRetrieveValues_SeqAIJ"
2319 int MatRetrieveValues_SeqAIJ(Mat mat)
2320 {
2321   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2322   int        nz = aij->i[mat->m],ierr;
2323 
2324   PetscFunctionBegin;
2325   if (aij->nonew != 1) {
2326     SETERRQ(1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
2327   }
2328   if (!aij->saved_values) {
2329     SETERRQ(1,"Must call MatStoreValues(A);first");
2330   }
2331 
2332   /* copy values over */
2333   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2334   PetscFunctionReturn(0);
2335 }
2336 EXTERN_C_END
2337 
2338 #undef __FUNCT__
2339 #define __FUNCT__ "MatRetrieveValues"
2340 /*@
2341     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
2342        example, reuse of the linear part of a Jacobian, while recomputing the
2343        nonlinear portion.
2344 
2345    Collect on Mat
2346 
2347   Input Parameters:
2348 .  mat - the matrix (currently on AIJ matrices support this option)
2349 
2350   Level: advanced
2351 
2352 .seealso: MatStoreValues()
2353 
2354 @*/
2355 int MatRetrieveValues(Mat mat)
2356 {
2357   int ierr,(*f)(Mat);
2358 
2359   PetscFunctionBegin;
2360   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2361   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2362   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2363 
2364   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatRetrieveValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2365   if (f) {
2366     ierr = (*f)(mat);CHKERRQ(ierr);
2367   } else {
2368     SETERRQ(1,"Wrong type of matrix to retrieve values");
2369   }
2370   PetscFunctionReturn(0);
2371 }
2372 
2373 /*
2374    This allows SeqAIJ matrices to be passed to the matlab engine
2375 */
2376 #if defined(PETSC_HAVE_MATLAB) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
2377 #include "engine.h"   /* Matlab include file */
2378 #include "mex.h"      /* Matlab include file */
2379 EXTERN_C_BEGIN
2380 #undef __FUNCT__
2381 #define __FUNCT__ "MatMatlabEnginePut_SeqAIJ"
2382 int MatMatlabEnginePut_SeqAIJ(PetscObject obj,void *mengine)
2383 {
2384   int         ierr;
2385   Mat         B = (Mat)obj;
2386   mxArray     *mat;
2387   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)B->data;
2388 
2389   PetscFunctionBegin;
2390   mat  = mxCreateSparse(B->n,B->m,aij->nz,mxREAL);
2391   ierr = PetscMemcpy(mxGetPr(mat),aij->a,aij->nz*sizeof(PetscScalar));CHKERRQ(ierr);
2392   /* Matlab stores by column, not row so we pass in the transpose of the matrix */
2393   ierr = PetscMemcpy(mxGetIr(mat),aij->j,aij->nz*sizeof(int));CHKERRQ(ierr);
2394   ierr = PetscMemcpy(mxGetJc(mat),aij->i,(B->m+1)*sizeof(int));CHKERRQ(ierr);
2395 
2396   /* Matlab indices start at 0 for sparse (what a surprise) */
2397 
2398   ierr = PetscObjectName(obj);CHKERRQ(ierr);
2399   engPutVariable((Engine *)mengine,obj->name,mat);
2400   PetscFunctionReturn(0);
2401 }
2402 EXTERN_C_END
2403 
2404 EXTERN_C_BEGIN
2405 #undef __FUNCT__
2406 #define __FUNCT__ "MatMatlabEngineGet_SeqAIJ"
2407 int MatMatlabEngineGet_SeqAIJ(PetscObject obj,void *mengine)
2408 {
2409   int        ierr,ii;
2410   Mat        mat = (Mat)obj;
2411   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
2412   mxArray    *mmat;
2413 
2414   PetscFunctionBegin;
2415   ierr = PetscFree(aij->a);CHKERRQ(ierr);
2416 
2417   mmat = engGetVariable((Engine *)mengine,obj->name);
2418 
2419   aij->nz           = (mxGetJc(mmat))[mat->m];
2420   ierr              = PetscMalloc(((size_t) aij->nz)*(sizeof(int)+sizeof(PetscScalar))+(mat->m+1)*sizeof(int),&aij->a);CHKERRQ(ierr);
2421   aij->j            = (int*)(aij->a + aij->nz);
2422   aij->i            = aij->j + aij->nz;
2423   aij->singlemalloc = PETSC_TRUE;
2424   aij->freedata     = PETSC_TRUE;
2425 
2426   ierr = PetscMemcpy(aij->a,mxGetPr(mmat),aij->nz*sizeof(PetscScalar));CHKERRQ(ierr);
2427   /* Matlab stores by column, not row so we pass in the transpose of the matrix */
2428   ierr = PetscMemcpy(aij->j,mxGetIr(mmat),aij->nz*sizeof(int));CHKERRQ(ierr);
2429   ierr = PetscMemcpy(aij->i,mxGetJc(mmat),(mat->m+1)*sizeof(int));CHKERRQ(ierr);
2430 
2431   for (ii=0; ii<mat->m; ii++) {
2432     aij->ilen[ii] = aij->imax[ii] = aij->i[ii+1] - aij->i[ii];
2433   }
2434 
2435   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2436   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2437 
2438   PetscFunctionReturn(0);
2439 }
2440 EXTERN_C_END
2441 #endif
2442 
2443 /* --------------------------------------------------------------------------------*/
2444 #undef __FUNCT__
2445 #define __FUNCT__ "MatCreateSeqAIJ"
2446 /*@C
2447    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
2448    (the default parallel PETSc format).  For good matrix assembly performance
2449    the user should preallocate the matrix storage by setting the parameter nz
2450    (or the array nnz).  By setting these parameters accurately, performance
2451    during matrix assembly can be increased by more than a factor of 50.
2452 
2453    Collective on MPI_Comm
2454 
2455    Input Parameters:
2456 +  comm - MPI communicator, set to PETSC_COMM_SELF
2457 .  m - number of rows
2458 .  n - number of columns
2459 .  nz - number of nonzeros per row (same for all rows)
2460 -  nnz - array containing the number of nonzeros in the various rows
2461          (possibly different for each row) or PETSC_NULL
2462 
2463    Output Parameter:
2464 .  A - the matrix
2465 
2466    Notes:
2467    The AIJ format (also called the Yale sparse matrix format or
2468    compressed row storage), is fully compatible with standard Fortran 77
2469    storage.  That is, the stored row and column indices can begin at
2470    either one (as in Fortran) or zero.  See the users' manual for details.
2471 
2472    Specify the preallocated storage with either nz or nnz (not both).
2473    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2474    allocation.  For large problems you MUST preallocate memory or you
2475    will get TERRIBLE performance, see the users' manual chapter on matrices.
2476 
2477    By default, this format uses inodes (identical nodes) when possible, to
2478    improve numerical efficiency of matrix-vector products and solves. We
2479    search for consecutive rows with the same nonzero structure, thereby
2480    reusing matrix information to achieve increased efficiency.
2481 
2482    Options Database Keys:
2483 +  -mat_aij_no_inode  - Do not use inodes
2484 .  -mat_aij_inode_limit <limit> - Sets inode limit (max limit=5)
2485 -  -mat_aij_oneindex - Internally use indexing starting at 1
2486         rather than 0.  Note that when calling MatSetValues(),
2487         the user still MUST index entries starting at 0!
2488 
2489    Level: intermediate
2490 
2491 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
2492 
2493 @*/
2494 int MatCreateSeqAIJ(MPI_Comm comm,int m,int n,int nz,const int nnz[],Mat *A)
2495 {
2496   int ierr;
2497 
2498   PetscFunctionBegin;
2499   ierr = MatCreate(comm,m,n,m,n,A);CHKERRQ(ierr);
2500   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
2501   ierr = MatSeqAIJSetPreallocation(*A,nz,nnz);CHKERRQ(ierr);
2502   PetscFunctionReturn(0);
2503 }
2504 
2505 #define SKIP_ALLOCATION -4
2506 
2507 #undef __FUNCT__
2508 #define __FUNCT__ "MatSeqAIJSetPreallocation"
2509 /*@C
2510    MatSeqAIJSetPreallocation - For good matrix assembly performance
2511    the user should preallocate the matrix storage by setting the parameter nz
2512    (or the array nnz).  By setting these parameters accurately, performance
2513    during matrix assembly can be increased by more than a factor of 50.
2514 
2515    Collective on MPI_Comm
2516 
2517    Input Parameters:
2518 +  comm - MPI communicator, set to PETSC_COMM_SELF
2519 .  m - number of rows
2520 .  n - number of columns
2521 .  nz - number of nonzeros per row (same for all rows)
2522 -  nnz - array containing the number of nonzeros in the various rows
2523          (possibly different for each row) or PETSC_NULL
2524 
2525    Output Parameter:
2526 .  A - the matrix
2527 
2528    Notes:
2529    The AIJ format (also called the Yale sparse matrix format or
2530    compressed row storage), is fully compatible with standard Fortran 77
2531    storage.  That is, the stored row and column indices can begin at
2532    either one (as in Fortran) or zero.  See the users' manual for details.
2533 
2534    Specify the preallocated storage with either nz or nnz (not both).
2535    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2536    allocation.  For large problems you MUST preallocate memory or you
2537    will get TERRIBLE performance, see the users' manual chapter on matrices.
2538 
2539    By default, this format uses inodes (identical nodes) when possible, to
2540    improve numerical efficiency of matrix-vector products and solves. We
2541    search for consecutive rows with the same nonzero structure, thereby
2542    reusing matrix information to achieve increased efficiency.
2543 
2544    Options Database Keys:
2545 +  -mat_aij_no_inode  - Do not use inodes
2546 .  -mat_aij_inode_limit <limit> - Sets inode limit (max limit=5)
2547 -  -mat_aij_oneindex - Internally use indexing starting at 1
2548         rather than 0.  Note that when calling MatSetValues(),
2549         the user still MUST index entries starting at 0!
2550 
2551    Level: intermediate
2552 
2553 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
2554 
2555 @*/
2556 int MatSeqAIJSetPreallocation(Mat B,int nz,const int nnz[])
2557 {
2558   int ierr,(*f)(Mat,int,const int[]);
2559 
2560   PetscFunctionBegin;
2561   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
2562   if (f) {
2563     ierr = (*f)(B,nz,nnz);CHKERRQ(ierr);
2564   }
2565   PetscFunctionReturn(0);
2566 }
2567 
2568 EXTERN_C_BEGIN
2569 #undef __FUNCT__
2570 #define __FUNCT__ "MatSeqAIJSetPreallocation_SeqAIJ"
2571 int MatSeqAIJSetPreallocation_SeqAIJ(Mat B,int nz,int *nnz)
2572 {
2573   Mat_SeqAIJ *b;
2574   size_t     len = 0;
2575   PetscTruth skipallocation = PETSC_FALSE;
2576   int        i,ierr;
2577 
2578   PetscFunctionBegin;
2579 
2580   if (nz == SKIP_ALLOCATION) {
2581     skipallocation = PETSC_TRUE;
2582     nz             = 0;
2583   }
2584 
2585   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
2586   if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
2587   if (nnz) {
2588     for (i=0; i<B->m; i++) {
2589       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
2590       if (nnz[i] > B->n) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %d value %d rowlength %d",i,nnz[i],B->n);
2591     }
2592   }
2593 
2594   B->preallocated = PETSC_TRUE;
2595   b = (Mat_SeqAIJ*)B->data;
2596 
2597   ierr = PetscMalloc((B->m+1)*sizeof(int),&b->imax);CHKERRQ(ierr);
2598   if (!nnz) {
2599     if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
2600     else if (nz <= 0)        nz = 1;
2601     for (i=0; i<B->m; i++) b->imax[i] = nz;
2602     nz = nz*B->m;
2603   } else {
2604     nz = 0;
2605     for (i=0; i<B->m; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
2606   }
2607 
2608   if (!skipallocation) {
2609     /* allocate the matrix space */
2610     len             = ((size_t) nz)*(sizeof(int) + sizeof(PetscScalar)) + (B->m+1)*sizeof(int);
2611     ierr            = PetscMalloc(len,&b->a);CHKERRQ(ierr);
2612     b->j            = (int*)(b->a + nz);
2613     ierr            = PetscMemzero(b->j,nz*sizeof(int));CHKERRQ(ierr);
2614     b->i            = b->j + nz;
2615     b->i[0] = 0;
2616     for (i=1; i<B->m+1; i++) {
2617       b->i[i] = b->i[i-1] + b->imax[i-1];
2618     }
2619     b->singlemalloc = PETSC_TRUE;
2620     b->freedata     = PETSC_TRUE;
2621   } else {
2622     b->freedata     = PETSC_FALSE;
2623   }
2624 
2625   /* b->ilen will count nonzeros in each row so far. */
2626   ierr = PetscMalloc((B->m+1)*sizeof(int),&b->ilen);CHKERRQ(ierr);
2627   PetscLogObjectMemory(B,len+2*(B->m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ));
2628   for (i=0; i<B->m; i++) { b->ilen[i] = 0;}
2629 
2630   b->nz                = 0;
2631   b->maxnz             = nz;
2632   B->info.nz_unneeded  = (double)b->maxnz;
2633   PetscFunctionReturn(0);
2634 }
2635 EXTERN_C_END
2636 
2637 /*MC
2638    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
2639    based on compressed sparse row format.
2640 
2641    Options Database Keys:
2642 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
2643 
2644   Level: beginner
2645 
2646 .seealso: MatCreateSeqAIJ
2647 M*/
2648 
2649 EXTERN_C_BEGIN
2650 #undef __FUNCT__
2651 #define __FUNCT__ "MatCreate_SeqAIJ"
2652 int MatCreate_SeqAIJ(Mat B)
2653 {
2654   Mat_SeqAIJ *b;
2655   int        ierr,size;
2656   PetscTruth flg;
2657 
2658   PetscFunctionBegin;
2659   ierr = MPI_Comm_size(B->comm,&size);CHKERRQ(ierr);
2660   if (size > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
2661 
2662   B->m = B->M = PetscMax(B->m,B->M);
2663   B->n = B->N = PetscMax(B->n,B->N);
2664 
2665   ierr = PetscNew(Mat_SeqAIJ,&b);CHKERRQ(ierr);
2666   B->data             = (void*)b;
2667   ierr = PetscMemzero(b,sizeof(Mat_SeqAIJ));CHKERRQ(ierr);
2668   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
2669   B->factor           = 0;
2670   B->lupivotthreshold = 1.0;
2671   B->mapping          = 0;
2672   ierr = PetscOptionsGetReal(B->prefix,"-mat_lu_pivotthreshold",&B->lupivotthreshold,PETSC_NULL);CHKERRQ(ierr);
2673   ierr = PetscOptionsHasName(B->prefix,"-pc_ilu_preserve_row_sums",&b->ilu_preserve_row_sums);CHKERRQ(ierr);
2674   b->row              = 0;
2675   b->col              = 0;
2676   b->icol             = 0;
2677   b->reallocs         = 0;
2678 
2679   ierr = PetscMapCreateMPI(B->comm,B->m,B->m,&B->rmap);CHKERRQ(ierr);
2680   ierr = PetscMapCreateMPI(B->comm,B->n,B->n,&B->cmap);CHKERRQ(ierr);
2681 
2682   b->sorted            = PETSC_FALSE;
2683   b->ignorezeroentries = PETSC_FALSE;
2684   b->roworiented       = PETSC_TRUE;
2685   b->nonew             = 0;
2686   b->diag              = 0;
2687   b->solve_work        = 0;
2688   B->spptr             = 0;
2689   b->inode.use         = PETSC_TRUE;
2690   b->inode.node_count  = 0;
2691   b->inode.size        = 0;
2692   b->inode.limit       = 5;
2693   b->inode.max_limit   = 5;
2694   b->saved_values      = 0;
2695   b->idiag             = 0;
2696   b->ssor              = 0;
2697   b->keepzeroedrows    = PETSC_FALSE;
2698   b->xtoy              = 0;
2699   b->XtoY              = 0;
2700 
2701   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
2702 
2703   ierr = PetscOptionsHasName(B->prefix,"-mat_aij_matlab",&flg);CHKERRQ(ierr);
2704   if (flg) {ierr = MatUseMatlab_SeqAIJ(B);CHKERRQ(ierr);}
2705   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C",
2706                                      "MatSeqAIJSetColumnIndices_SeqAIJ",
2707                                      MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
2708   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
2709                                      "MatStoreValues_SeqAIJ",
2710                                      MatStoreValues_SeqAIJ);CHKERRQ(ierr);
2711   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
2712                                      "MatRetrieveValues_SeqAIJ",
2713                                      MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
2714   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",
2715                                      "MatConvert_SeqAIJ_SeqSBAIJ",
2716                                       MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
2717   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C",
2718                                      "MatConvert_SeqAIJ_SeqBAIJ",
2719                                       MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
2720   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C",
2721                                      "MatIsTranspose_SeqAIJ",
2722                                       MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
2723   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C",
2724                                      "MatSeqAIJSetPreallocation_SeqAIJ",
2725                                       MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
2726   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C",
2727                                      "MatReorderForNonzeroDiagonal_SeqAIJ",
2728                                       MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
2729   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatAdjustForInodes_C",
2730                                      "MatAdjustForInodes_SeqAIJ",
2731                                       MatAdjustForInodes_SeqAIJ);CHKERRQ(ierr);
2732   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJGetInodeSizes_C",
2733                                      "MatSeqAIJGetInodeSizes_SeqAIJ",
2734                                       MatSeqAIJGetInodeSizes_SeqAIJ);CHKERRQ(ierr);
2735 #if defined(PETSC_HAVE_MATLAB) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
2736   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEnginePut_C","MatMatlabEnginePut_SeqAIJ",MatMatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
2737   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEngineGet_C","MatMatlabEngineGet_SeqAIJ",MatMatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
2738 #endif
2739   ierr = RegisterApplyPtAPRoutines_Private(B);CHKERRQ(ierr);
2740   PetscFunctionReturn(0);
2741 }
2742 EXTERN_C_END
2743 
2744 #undef __FUNCT__
2745 #define __FUNCT__ "MatDuplicate_SeqAIJ"
2746 int MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
2747 {
2748   Mat        C;
2749   Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data;
2750   int        i,m = A->m,ierr;
2751   size_t     len;
2752 
2753   PetscFunctionBegin;
2754   *B = 0;
2755   ierr = MatCreate(A->comm,A->m,A->n,A->m,A->n,&C);CHKERRQ(ierr);
2756   ierr = MatSetType(C,A->type_name);CHKERRQ(ierr);
2757   c    = (Mat_SeqAIJ*)C->data;
2758 
2759   C->factor         = A->factor;
2760   c->row            = 0;
2761   c->col            = 0;
2762   c->icol           = 0;
2763   c->keepzeroedrows = a->keepzeroedrows;
2764   C->assembled      = PETSC_TRUE;
2765 
2766   C->M          = A->m;
2767   C->N          = A->n;
2768 
2769   ierr = PetscMalloc((m+1)*sizeof(int),&c->imax);CHKERRQ(ierr);
2770   ierr = PetscMalloc((m+1)*sizeof(int),&c->ilen);CHKERRQ(ierr);
2771   for (i=0; i<m; i++) {
2772     c->imax[i] = a->imax[i];
2773     c->ilen[i] = a->ilen[i];
2774   }
2775 
2776   /* allocate the matrix space */
2777   c->singlemalloc = PETSC_TRUE;
2778   len   = ((size_t) (m+1))*sizeof(int)+(a->i[m])*(sizeof(PetscScalar)+sizeof(int));
2779   ierr  = PetscMalloc(len,&c->a);CHKERRQ(ierr);
2780   c->j  = (int*)(c->a + a->i[m] );
2781   c->i  = c->j + a->i[m];
2782   ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(int));CHKERRQ(ierr);
2783   if (m > 0) {
2784     ierr = PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(int));CHKERRQ(ierr);
2785     if (cpvalues == MAT_COPY_VALUES) {
2786       ierr = PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
2787     } else {
2788       ierr = PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
2789     }
2790   }
2791 
2792   PetscLogObjectMemory(C,len+2*(m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ));
2793   c->sorted      = a->sorted;
2794   c->roworiented = a->roworiented;
2795   c->nonew       = a->nonew;
2796   c->ilu_preserve_row_sums = a->ilu_preserve_row_sums;
2797   c->saved_values = 0;
2798   c->idiag        = 0;
2799   c->ssor         = 0;
2800   c->ignorezeroentries = a->ignorezeroentries;
2801   c->freedata     = PETSC_TRUE;
2802 
2803   if (a->diag) {
2804     ierr = PetscMalloc((m+1)*sizeof(int),&c->diag);CHKERRQ(ierr);
2805     PetscLogObjectMemory(C,(m+1)*sizeof(int));
2806     for (i=0; i<m; i++) {
2807       c->diag[i] = a->diag[i];
2808     }
2809   } else c->diag        = 0;
2810   c->inode.use          = a->inode.use;
2811   c->inode.limit        = a->inode.limit;
2812   c->inode.max_limit    = a->inode.max_limit;
2813   if (a->inode.size){
2814     ierr                = PetscMalloc((m+1)*sizeof(int),&c->inode.size);CHKERRQ(ierr);
2815     c->inode.node_count = a->inode.node_count;
2816     ierr                = PetscMemcpy(c->inode.size,a->inode.size,(m+1)*sizeof(int));CHKERRQ(ierr);
2817   } else {
2818     c->inode.size       = 0;
2819     c->inode.node_count = 0;
2820   }
2821   c->nz                 = a->nz;
2822   c->maxnz              = a->maxnz;
2823   c->solve_work         = 0;
2824   C->spptr              = 0;      /* Dangerous -I'm throwing away a->spptr */
2825   C->preallocated       = PETSC_TRUE;
2826 
2827   *B = C;
2828   ierr = PetscFListDuplicate(A->qlist,&C->qlist);CHKERRQ(ierr);
2829   PetscFunctionReturn(0);
2830 }
2831 
2832 #undef __FUNCT__
2833 #define __FUNCT__ "MatLoad_SeqAIJ"
2834 int MatLoad_SeqAIJ(PetscViewer viewer,const MatType type,Mat *A)
2835 {
2836   Mat_SeqAIJ   *a;
2837   Mat          B;
2838   int          i,nz,ierr,fd,header[4],size,*rowlengths = 0,M,N;
2839   MPI_Comm     comm;
2840 
2841   PetscFunctionBegin;
2842   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
2843   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
2844   if (size > 1) SETERRQ(PETSC_ERR_ARG_SIZ,"view must have one processor");
2845   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
2846   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
2847   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
2848   M = header[1]; N = header[2]; nz = header[3];
2849 
2850   if (nz < 0) {
2851     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
2852   }
2853 
2854   /* read in row lengths */
2855   ierr = PetscMalloc(M*sizeof(int),&rowlengths);CHKERRQ(ierr);
2856   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
2857 
2858   /* create our matrix */
2859   ierr = MatCreate(comm,PETSC_DECIDE,PETSC_DECIDE,M,N,&B);CHKERRQ(ierr);
2860   ierr = MatSetType(B,type);CHKERRQ(ierr);
2861   ierr = MatSeqAIJSetPreallocation(B,0,rowlengths);CHKERRQ(ierr);
2862   a = (Mat_SeqAIJ*)B->data;
2863 
2864   /* read in column indices and adjust for Fortran indexing*/
2865   ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr);
2866 
2867   /* read in nonzero values */
2868   ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr);
2869 
2870   /* set matrix "i" values */
2871   a->i[0] = 0;
2872   for (i=1; i<= M; i++) {
2873     a->i[i]      = a->i[i-1] + rowlengths[i-1];
2874     a->ilen[i-1] = rowlengths[i-1];
2875   }
2876   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
2877 
2878   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2879   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2880   *A = B;
2881   PetscFunctionReturn(0);
2882 }
2883 
2884 #undef __FUNCT__
2885 #define __FUNCT__ "MatEqual_SeqAIJ"
2886 int MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg)
2887 {
2888   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data;
2889   int        ierr;
2890 
2891   PetscFunctionBegin;
2892   /* If the  matrix dimensions are not equal,or no of nonzeros */
2893   if ((A->m != B->m) || (A->n != B->n) ||(a->nz != b->nz)) {
2894     *flg = PETSC_FALSE;
2895     PetscFunctionReturn(0);
2896   }
2897 
2898   /* if the a->i are the same */
2899   ierr = PetscMemcmp(a->i,b->i,(A->m+1)*sizeof(int),flg);CHKERRQ(ierr);
2900   if (*flg == PETSC_FALSE) PetscFunctionReturn(0);
2901 
2902   /* if a->j are the same */
2903   ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(int),flg);CHKERRQ(ierr);
2904   if (*flg == PETSC_FALSE) PetscFunctionReturn(0);
2905 
2906   /* if a->a are the same */
2907   ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr);
2908 
2909   PetscFunctionReturn(0);
2910 
2911 }
2912 
2913 #undef __FUNCT__
2914 #define __FUNCT__ "MatCreateSeqAIJWithArrays"
2915 /*@C
2916      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
2917               provided by the user.
2918 
2919       Coolective on MPI_Comm
2920 
2921    Input Parameters:
2922 +   comm - must be an MPI communicator of size 1
2923 .   m - number of rows
2924 .   n - number of columns
2925 .   i - row indices
2926 .   j - column indices
2927 -   a - matrix values
2928 
2929    Output Parameter:
2930 .   mat - the matrix
2931 
2932    Level: intermediate
2933 
2934    Notes:
2935        The i, j, and a arrays are not copied by this routine, the user must free these arrays
2936     once the matrix is destroyed
2937 
2938        You cannot set new nonzero locations into this matrix, that will generate an error.
2939 
2940        The i and j indices are 0 based
2941 
2942 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ()
2943 
2944 @*/
2945 int MatCreateSeqAIJWithArrays(MPI_Comm comm,int m,int n,int* i,int*j,PetscScalar *a,Mat *mat)
2946 {
2947   int        ierr,ii;
2948   Mat_SeqAIJ *aij;
2949 
2950   PetscFunctionBegin;
2951   ierr = MatCreate(comm,m,n,m,n,mat);CHKERRQ(ierr);
2952   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
2953   ierr = MatSeqAIJSetPreallocation(*mat,SKIP_ALLOCATION,0);CHKERRQ(ierr);
2954   aij  = (Mat_SeqAIJ*)(*mat)->data;
2955 
2956   if (i[0] != 0) {
2957     SETERRQ(1,"i (row indices) must start with 0");
2958   }
2959   aij->i = i;
2960   aij->j = j;
2961   aij->a = a;
2962   aij->singlemalloc = PETSC_FALSE;
2963   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2964   aij->freedata     = PETSC_FALSE;
2965 
2966   for (ii=0; ii<m; ii++) {
2967     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
2968 #if defined(PETSC_USE_BOPT_g)
2969     if (i[ii+1] - i[ii] < 0) SETERRQ2(1,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]);
2970 #endif
2971   }
2972 #if defined(PETSC_USE_BOPT_g)
2973   for (ii=0; ii<aij->i[m]; ii++) {
2974     if (j[ii] < 0) SETERRQ2(1,"Negative column index at location = %d index = %d",ii,j[ii]);
2975     if (j[ii] > n - 1) SETERRQ2(1,"Column index to large at location = %d index = %d",ii,j[ii]);
2976   }
2977 #endif
2978 
2979   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2980   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2981   PetscFunctionReturn(0);
2982 }
2983 
2984 #undef __FUNCT__
2985 #define __FUNCT__ "MatSetColoring_SeqAIJ"
2986 int MatSetColoring_SeqAIJ(Mat A,ISColoring coloring)
2987 {
2988   int        ierr;
2989   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2990 
2991   PetscFunctionBegin;
2992   if (coloring->ctype == IS_COLORING_LOCAL) {
2993     ierr        = ISColoringReference(coloring);CHKERRQ(ierr);
2994     a->coloring = coloring;
2995   } else if (coloring->ctype == IS_COLORING_GHOSTED) {
2996     int             i,*larray;
2997     ISColoring      ocoloring;
2998     ISColoringValue *colors;
2999 
3000     /* set coloring for diagonal portion */
3001     ierr = PetscMalloc((A->n+1)*sizeof(int),&larray);CHKERRQ(ierr);
3002     for (i=0; i<A->n; i++) {
3003       larray[i] = i;
3004     }
3005     ierr = ISGlobalToLocalMappingApply(A->mapping,IS_GTOLM_MASK,A->n,larray,PETSC_NULL,larray);CHKERRQ(ierr);
3006     ierr = PetscMalloc((A->n+1)*sizeof(ISColoringValue),&colors);CHKERRQ(ierr);
3007     for (i=0; i<A->n; i++) {
3008       colors[i] = coloring->colors[larray[i]];
3009     }
3010     ierr = PetscFree(larray);CHKERRQ(ierr);
3011     ierr = ISColoringCreate(PETSC_COMM_SELF,A->n,colors,&ocoloring);CHKERRQ(ierr);
3012     a->coloring = ocoloring;
3013   }
3014   PetscFunctionReturn(0);
3015 }
3016 
3017 #if defined(PETSC_HAVE_ADIC) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
3018 EXTERN_C_BEGIN
3019 #include "adic/ad_utils.h"
3020 EXTERN_C_END
3021 
3022 #undef __FUNCT__
3023 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ"
3024 int MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
3025 {
3026   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3027   int             m = A->m,*ii = a->i,*jj = a->j,nz,i,j,nlen;
3028   PetscScalar     *v = a->a,*values = ((PetscScalar*)advalues)+1;
3029   ISColoringValue *color;
3030 
3031   PetscFunctionBegin;
3032   if (!a->coloring) SETERRQ(1,"Coloring not set for matrix");
3033   nlen  = PetscADGetDerivTypeSize()/sizeof(PetscScalar);
3034   color = a->coloring->colors;
3035   /* loop over rows */
3036   for (i=0; i<m; i++) {
3037     nz = ii[i+1] - ii[i];
3038     /* loop over columns putting computed value into matrix */
3039     for (j=0; j<nz; j++) {
3040       *v++ = values[color[*jj++]];
3041     }
3042     values += nlen; /* jump to next row of derivatives */
3043   }
3044   PetscFunctionReturn(0);
3045 }
3046 
3047 #else
3048 
3049 #undef __FUNCT__
3050 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ"
3051 int MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
3052 {
3053   PetscFunctionBegin;
3054   SETERRQ(1,"PETSc installed without ADIC");
3055 }
3056 
3057 #endif
3058 
3059 #undef __FUNCT__
3060 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ"
3061 int MatSetValuesAdifor_SeqAIJ(Mat A,int nl,void *advalues)
3062 {
3063   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3064   int             m = A->m,*ii = a->i,*jj = a->j,nz,i,j;
3065   PetscScalar     *v = a->a,*values = (PetscScalar *)advalues;
3066   ISColoringValue *color;
3067 
3068   PetscFunctionBegin;
3069   if (!a->coloring) SETERRQ(1,"Coloring not set for matrix");
3070   color = a->coloring->colors;
3071   /* loop over rows */
3072   for (i=0; i<m; i++) {
3073     nz = ii[i+1] - ii[i];
3074     /* loop over columns putting computed value into matrix */
3075     for (j=0; j<nz; j++) {
3076       *v++ = values[color[*jj++]];
3077     }
3078     values += nl; /* jump to next row of derivatives */
3079   }
3080   PetscFunctionReturn(0);
3081 }
3082 
3083