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