xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 4ce68768e41e382c1fc596e135fd299def09fddc)
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   PetscBLASInt bnz = (PetscBLASInt)a->nz,one = 1;
1713 
1714   PetscFunctionBegin;
1715   BLscal_(&bnz,(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            i;
2076   Mat_SeqAIJ     *x  = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data;
2077   PetscBLASInt   one=1,bnz = (PetscBLASInt)x->nz;
2078 
2079   PetscFunctionBegin;
2080   if (str == SAME_NONZERO_PATTERN) {
2081     BLaxpy_(&bnz,(PetscScalar*)a,x->a,&one,y->a,&one);
2082   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2083     if (y->xtoy && y->XtoY != X) {
2084       ierr = PetscFree(y->xtoy);CHKERRQ(ierr);
2085       ierr = MatDestroy(y->XtoY);CHKERRQ(ierr);
2086     }
2087     if (!y->xtoy) { /* get xtoy */
2088       ierr = MatAXPYGetxtoy_Private(X->m,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr);
2089       y->XtoY = X;
2090     }
2091     for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += (*a)*(x->a[i]);
2092     PetscLogInfo(0,"MatAXPY_SeqAIJ: ratio of nnz(X)/nnz(Y): %d/%d = %g\n",x->nz,y->nz,(PetscReal)(x->nz)/y->nz);
2093   } else {
2094     ierr = MatAXPY_Basic(a,X,Y,str);CHKERRQ(ierr);
2095   }
2096   PetscFunctionReturn(0);
2097 }
2098 
2099 /* -------------------------------------------------------------------*/
2100 static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
2101        MatGetRow_SeqAIJ,
2102        MatRestoreRow_SeqAIJ,
2103        MatMult_SeqAIJ,
2104 /* 4*/ MatMultAdd_SeqAIJ,
2105        MatMultTranspose_SeqAIJ,
2106        MatMultTransposeAdd_SeqAIJ,
2107        MatSolve_SeqAIJ,
2108        MatSolveAdd_SeqAIJ,
2109        MatSolveTranspose_SeqAIJ,
2110 /*10*/ MatSolveTransposeAdd_SeqAIJ,
2111        MatLUFactor_SeqAIJ,
2112        0,
2113        MatRelax_SeqAIJ,
2114        MatTranspose_SeqAIJ,
2115 /*15*/ MatGetInfo_SeqAIJ,
2116        MatEqual_SeqAIJ,
2117        MatGetDiagonal_SeqAIJ,
2118        MatDiagonalScale_SeqAIJ,
2119        MatNorm_SeqAIJ,
2120 /*20*/ 0,
2121        MatAssemblyEnd_SeqAIJ,
2122        MatCompress_SeqAIJ,
2123        MatSetOption_SeqAIJ,
2124        MatZeroEntries_SeqAIJ,
2125 /*25*/ MatZeroRows_SeqAIJ,
2126        MatLUFactorSymbolic_SeqAIJ,
2127        MatLUFactorNumeric_SeqAIJ,
2128        MatCholeskyFactorSymbolic_SeqAIJ,
2129        MatCholeskyFactorNumeric_SeqAIJ,
2130 /*30*/ MatSetUpPreallocation_SeqAIJ,
2131        MatILUFactorSymbolic_SeqAIJ,
2132        MatICCFactorSymbolic_SeqAIJ,
2133        MatGetArray_SeqAIJ,
2134        MatRestoreArray_SeqAIJ,
2135 /*35*/ MatDuplicate_SeqAIJ,
2136        0,
2137        0,
2138        MatILUFactor_SeqAIJ,
2139        0,
2140 /*40*/ MatAXPY_SeqAIJ,
2141        MatGetSubMatrices_SeqAIJ,
2142        MatIncreaseOverlap_SeqAIJ,
2143        MatGetValues_SeqAIJ,
2144        MatCopy_SeqAIJ,
2145 /*45*/ MatPrintHelp_SeqAIJ,
2146        MatScale_SeqAIJ,
2147        0,
2148        0,
2149        MatILUDTFactor_SeqAIJ,
2150 /*50*/ MatGetBlockSize_SeqAIJ,
2151        MatGetRowIJ_SeqAIJ,
2152        MatRestoreRowIJ_SeqAIJ,
2153        MatGetColumnIJ_SeqAIJ,
2154        MatRestoreColumnIJ_SeqAIJ,
2155 /*55*/ MatFDColoringCreate_SeqAIJ,
2156        0,
2157        0,
2158        MatPermute_SeqAIJ,
2159        0,
2160 /*60*/ 0,
2161        MatDestroy_SeqAIJ,
2162        MatView_SeqAIJ,
2163        MatGetPetscMaps_Petsc,
2164        0,
2165 /*65*/ 0,
2166        0,
2167        0,
2168        0,
2169        0,
2170 /*70*/ 0,
2171        0,
2172        MatSetColoring_SeqAIJ,
2173        MatSetValuesAdic_SeqAIJ,
2174        MatSetValuesAdifor_SeqAIJ,
2175 /*75*/ MatFDColoringApply_SeqAIJ,
2176        0,
2177        0,
2178        0,
2179        0,
2180 /*80*/ 0,
2181        0,
2182        0,
2183        0,
2184 /*84*/ MatLoad_SeqAIJ,
2185        MatIsSymmetric_SeqAIJ,
2186        0,
2187        0,
2188        0,
2189 /*89*/ 0,
2190        MatMatMult_SeqAIJ_SeqAIJ,
2191        MatMatMultSymbolic_SeqAIJ_SeqAIJ,
2192        MatMatMultNumeric_SeqAIJ_SeqAIJ,
2193        MatPtAP_SeqAIJ_SeqAIJ,
2194 /*94*/ MatPtAPSymbolic_SeqAIJ_SeqAIJ,
2195        MatPtAPNumeric_SeqAIJ_SeqAIJ,
2196 };
2197 
2198 EXTERN_C_BEGIN
2199 #undef __FUNCT__
2200 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ"
2201 PetscErrorCode MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,int *indices)
2202 {
2203   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2204   int        i,nz,n;
2205 
2206   PetscFunctionBegin;
2207 
2208   nz = aij->maxnz;
2209   n  = mat->n;
2210   for (i=0; i<nz; i++) {
2211     aij->j[i] = indices[i];
2212   }
2213   aij->nz = nz;
2214   for (i=0; i<n; i++) {
2215     aij->ilen[i] = aij->imax[i];
2216   }
2217 
2218   PetscFunctionReturn(0);
2219 }
2220 EXTERN_C_END
2221 
2222 #undef __FUNCT__
2223 #define __FUNCT__ "MatSeqAIJSetColumnIndices"
2224 /*@
2225     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
2226        in the matrix.
2227 
2228   Input Parameters:
2229 +  mat - the SeqAIJ matrix
2230 -  indices - the column indices
2231 
2232   Level: advanced
2233 
2234   Notes:
2235     This can be called if you have precomputed the nonzero structure of the
2236   matrix and want to provide it to the matrix object to improve the performance
2237   of the MatSetValues() operation.
2238 
2239     You MUST have set the correct numbers of nonzeros per row in the call to
2240   MatCreateSeqAIJ().
2241 
2242     MUST be called before any calls to MatSetValues();
2243 
2244     The indices should start with zero, not one.
2245 
2246 @*/
2247 PetscErrorCode MatSeqAIJSetColumnIndices(Mat mat,int *indices)
2248 {
2249   PetscErrorCode ierr,(*f)(Mat,int *);
2250 
2251   PetscFunctionBegin;
2252   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2253   PetscValidPointer(indices,2);
2254   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr);
2255   if (f) {
2256     ierr = (*f)(mat,indices);CHKERRQ(ierr);
2257   } else {
2258     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to set column indices");
2259   }
2260   PetscFunctionReturn(0);
2261 }
2262 
2263 /* ----------------------------------------------------------------------------------------*/
2264 
2265 EXTERN_C_BEGIN
2266 #undef __FUNCT__
2267 #define __FUNCT__ "MatStoreValues_SeqAIJ"
2268 PetscErrorCode MatStoreValues_SeqAIJ(Mat mat)
2269 {
2270   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2271   PetscErrorCode ierr;
2272   size_t       nz = aij->i[mat->m];
2273 
2274   PetscFunctionBegin;
2275   if (aij->nonew != 1) {
2276     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
2277   }
2278 
2279   /* allocate space for values if not already there */
2280   if (!aij->saved_values) {
2281     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
2282   }
2283 
2284   /* copy values over */
2285   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2286   PetscFunctionReturn(0);
2287 }
2288 EXTERN_C_END
2289 
2290 #undef __FUNCT__
2291 #define __FUNCT__ "MatStoreValues"
2292 /*@
2293     MatStoreValues - Stashes a copy of the matrix values; this allows, for
2294        example, reuse of the linear part of a Jacobian, while recomputing the
2295        nonlinear portion.
2296 
2297    Collect on Mat
2298 
2299   Input Parameters:
2300 .  mat - the matrix (currently on AIJ matrices support this option)
2301 
2302   Level: advanced
2303 
2304   Common Usage, with SNESSolve():
2305 $    Create Jacobian matrix
2306 $    Set linear terms into matrix
2307 $    Apply boundary conditions to matrix, at this time matrix must have
2308 $      final nonzero structure (i.e. setting the nonlinear terms and applying
2309 $      boundary conditions again will not change the nonzero structure
2310 $    ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS);
2311 $    ierr = MatStoreValues(mat);
2312 $    Call SNESSetJacobian() with matrix
2313 $    In your Jacobian routine
2314 $      ierr = MatRetrieveValues(mat);
2315 $      Set nonlinear terms in matrix
2316 
2317   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
2318 $    // build linear portion of Jacobian
2319 $    ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS);
2320 $    ierr = MatStoreValues(mat);
2321 $    loop over nonlinear iterations
2322 $       ierr = MatRetrieveValues(mat);
2323 $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
2324 $       // call MatAssemblyBegin/End() on matrix
2325 $       Solve linear system with Jacobian
2326 $    endloop
2327 
2328   Notes:
2329     Matrix must already be assemblied before calling this routine
2330     Must set the matrix option MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS); before
2331     calling this routine.
2332 
2333 .seealso: MatRetrieveValues()
2334 
2335 @*/
2336 PetscErrorCode MatStoreValues(Mat mat)
2337 {
2338   PetscErrorCode ierr,(*f)(Mat);
2339 
2340   PetscFunctionBegin;
2341   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2342   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2343   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2344 
2345   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatStoreValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2346   if (f) {
2347     ierr = (*f)(mat);CHKERRQ(ierr);
2348   } else {
2349     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to store values");
2350   }
2351   PetscFunctionReturn(0);
2352 }
2353 
2354 EXTERN_C_BEGIN
2355 #undef __FUNCT__
2356 #define __FUNCT__ "MatRetrieveValues_SeqAIJ"
2357 PetscErrorCode MatRetrieveValues_SeqAIJ(Mat mat)
2358 {
2359   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2360   PetscErrorCode ierr;
2361   int        nz = aij->i[mat->m];
2362 
2363   PetscFunctionBegin;
2364   if (aij->nonew != 1) {
2365     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
2366   }
2367   if (!aij->saved_values) {
2368     SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
2369   }
2370   /* copy values over */
2371   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2372   PetscFunctionReturn(0);
2373 }
2374 EXTERN_C_END
2375 
2376 #undef __FUNCT__
2377 #define __FUNCT__ "MatRetrieveValues"
2378 /*@
2379     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
2380        example, reuse of the linear part of a Jacobian, while recomputing the
2381        nonlinear portion.
2382 
2383    Collect on Mat
2384 
2385   Input Parameters:
2386 .  mat - the matrix (currently on AIJ matrices support this option)
2387 
2388   Level: advanced
2389 
2390 .seealso: MatStoreValues()
2391 
2392 @*/
2393 PetscErrorCode MatRetrieveValues(Mat mat)
2394 {
2395   PetscErrorCode ierr,(*f)(Mat);
2396 
2397   PetscFunctionBegin;
2398   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2399   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2400   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2401 
2402   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatRetrieveValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2403   if (f) {
2404     ierr = (*f)(mat);CHKERRQ(ierr);
2405   } else {
2406     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to retrieve values");
2407   }
2408   PetscFunctionReturn(0);
2409 }
2410 
2411 
2412 /* --------------------------------------------------------------------------------*/
2413 #undef __FUNCT__
2414 #define __FUNCT__ "MatCreateSeqAIJ"
2415 /*@C
2416    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
2417    (the default parallel PETSc format).  For good matrix assembly performance
2418    the user should preallocate the matrix storage by setting the parameter nz
2419    (or the array nnz).  By setting these parameters accurately, performance
2420    during matrix assembly can be increased by more than a factor of 50.
2421 
2422    Collective on MPI_Comm
2423 
2424    Input Parameters:
2425 +  comm - MPI communicator, set to PETSC_COMM_SELF
2426 .  m - number of rows
2427 .  n - number of columns
2428 .  nz - number of nonzeros per row (same for all rows)
2429 -  nnz - array containing the number of nonzeros in the various rows
2430          (possibly different for each row) or PETSC_NULL
2431 
2432    Output Parameter:
2433 .  A - the matrix
2434 
2435    Notes:
2436    The AIJ format (also called the Yale sparse matrix format or
2437    compressed row storage), is fully compatible with standard Fortran 77
2438    storage.  That is, the stored row and column indices can begin at
2439    either one (as in Fortran) or zero.  See the users' manual for details.
2440 
2441    Specify the preallocated storage with either nz or nnz (not both).
2442    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2443    allocation.  For large problems you MUST preallocate memory or you
2444    will get TERRIBLE performance, see the users' manual chapter on matrices.
2445 
2446    By default, this format uses inodes (identical nodes) when possible, to
2447    improve numerical efficiency of matrix-vector products and solves. We
2448    search for consecutive rows with the same nonzero structure, thereby
2449    reusing matrix information to achieve increased efficiency.
2450 
2451    Options Database Keys:
2452 +  -mat_aij_no_inode  - Do not use inodes
2453 .  -mat_aij_inode_limit <limit> - Sets inode limit (max limit=5)
2454 -  -mat_aij_oneindex - Internally use indexing starting at 1
2455         rather than 0.  Note that when calling MatSetValues(),
2456         the user still MUST index entries starting at 0!
2457 
2458    Level: intermediate
2459 
2460 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
2461 
2462 @*/
2463 PetscErrorCode MatCreateSeqAIJ(MPI_Comm comm,int m,int n,int nz,const int nnz[],Mat *A)
2464 {
2465   PetscErrorCode ierr;
2466 
2467   PetscFunctionBegin;
2468   ierr = MatCreate(comm,m,n,m,n,A);CHKERRQ(ierr);
2469   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
2470   ierr = MatSeqAIJSetPreallocation(*A,nz,nnz);CHKERRQ(ierr);
2471   PetscFunctionReturn(0);
2472 }
2473 
2474 #define SKIP_ALLOCATION -4
2475 
2476 #undef __FUNCT__
2477 #define __FUNCT__ "MatSeqAIJSetPreallocation"
2478 /*@C
2479    MatSeqAIJSetPreallocation - For good matrix assembly performance
2480    the user should preallocate the matrix storage by setting the parameter nz
2481    (or the array nnz).  By setting these parameters accurately, performance
2482    during matrix assembly can be increased by more than a factor of 50.
2483 
2484    Collective on MPI_Comm
2485 
2486    Input Parameters:
2487 +  comm - MPI communicator, set to PETSC_COMM_SELF
2488 .  m - number of rows
2489 .  n - number of columns
2490 .  nz - number of nonzeros per row (same for all rows)
2491 -  nnz - array containing the number of nonzeros in the various rows
2492          (possibly different for each row) or PETSC_NULL
2493 
2494    Output Parameter:
2495 .  A - the matrix
2496 
2497    Notes:
2498    The AIJ format (also called the Yale sparse matrix format or
2499    compressed row storage), is fully compatible with standard Fortran 77
2500    storage.  That is, the stored row and column indices can begin at
2501    either one (as in Fortran) or zero.  See the users' manual for details.
2502 
2503    Specify the preallocated storage with either nz or nnz (not both).
2504    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2505    allocation.  For large problems you MUST preallocate memory or you
2506    will get TERRIBLE performance, see the users' manual chapter on matrices.
2507 
2508    By default, this format uses inodes (identical nodes) when possible, to
2509    improve numerical efficiency of matrix-vector products and solves. We
2510    search for consecutive rows with the same nonzero structure, thereby
2511    reusing matrix information to achieve increased efficiency.
2512 
2513    Options Database Keys:
2514 +  -mat_aij_no_inode  - Do not use inodes
2515 .  -mat_aij_inode_limit <limit> - Sets inode limit (max limit=5)
2516 -  -mat_aij_oneindex - Internally use indexing starting at 1
2517         rather than 0.  Note that when calling MatSetValues(),
2518         the user still MUST index entries starting at 0!
2519 
2520    Level: intermediate
2521 
2522 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
2523 
2524 @*/
2525 PetscErrorCode MatSeqAIJSetPreallocation(Mat B,int nz,const int nnz[])
2526 {
2527   PetscErrorCode ierr,(*f)(Mat,int,const int[]);
2528 
2529   PetscFunctionBegin;
2530   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
2531   if (f) {
2532     ierr = (*f)(B,nz,nnz);CHKERRQ(ierr);
2533   }
2534   PetscFunctionReturn(0);
2535 }
2536 
2537 EXTERN_C_BEGIN
2538 #undef __FUNCT__
2539 #define __FUNCT__ "MatSeqAIJSetPreallocation_SeqAIJ"
2540 PetscErrorCode MatSeqAIJSetPreallocation_SeqAIJ(Mat B,int nz,int *nnz)
2541 {
2542   Mat_SeqAIJ *b;
2543   size_t     len = 0;
2544   PetscTruth skipallocation = PETSC_FALSE;
2545   PetscErrorCode ierr;
2546   int        i;
2547 
2548   PetscFunctionBegin;
2549 
2550   if (nz == SKIP_ALLOCATION) {
2551     skipallocation = PETSC_TRUE;
2552     nz             = 0;
2553   }
2554 
2555   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
2556   if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
2557   if (nnz) {
2558     for (i=0; i<B->m; i++) {
2559       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
2560       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);
2561     }
2562   }
2563 
2564   B->preallocated = PETSC_TRUE;
2565   b = (Mat_SeqAIJ*)B->data;
2566 
2567   ierr = PetscMalloc((B->m+1)*sizeof(int),&b->imax);CHKERRQ(ierr);
2568   if (!nnz) {
2569     if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
2570     else if (nz <= 0)        nz = 1;
2571     for (i=0; i<B->m; i++) b->imax[i] = nz;
2572     nz = nz*B->m;
2573   } else {
2574     nz = 0;
2575     for (i=0; i<B->m; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
2576   }
2577 
2578   if (!skipallocation) {
2579     /* allocate the matrix space */
2580     len             = ((size_t) nz)*(sizeof(int) + sizeof(PetscScalar)) + (B->m+1)*sizeof(int);
2581     ierr            = PetscMalloc(len,&b->a);CHKERRQ(ierr);
2582     b->j            = (int*)(b->a + nz);
2583     ierr            = PetscMemzero(b->j,nz*sizeof(int));CHKERRQ(ierr);
2584     b->i            = b->j + nz;
2585     b->i[0] = 0;
2586     for (i=1; i<B->m+1; i++) {
2587       b->i[i] = b->i[i-1] + b->imax[i-1];
2588     }
2589     b->singlemalloc = PETSC_TRUE;
2590     b->freedata     = PETSC_TRUE;
2591   } else {
2592     b->freedata     = PETSC_FALSE;
2593   }
2594 
2595   /* b->ilen will count nonzeros in each row so far. */
2596   ierr = PetscMalloc((B->m+1)*sizeof(int),&b->ilen);CHKERRQ(ierr);
2597   PetscLogObjectMemory(B,len+2*(B->m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ));
2598   for (i=0; i<B->m; i++) { b->ilen[i] = 0;}
2599 
2600   b->nz                = 0;
2601   b->maxnz             = nz;
2602   B->info.nz_unneeded  = (double)b->maxnz;
2603   PetscFunctionReturn(0);
2604 }
2605 EXTERN_C_END
2606 
2607 /*MC
2608    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
2609    based on compressed sparse row format.
2610 
2611    Options Database Keys:
2612 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
2613 
2614   Level: beginner
2615 
2616 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
2617 M*/
2618 
2619 EXTERN_C_BEGIN
2620 #undef __FUNCT__
2621 #define __FUNCT__ "MatCreate_SeqAIJ"
2622 PetscErrorCode MatCreate_SeqAIJ(Mat B)
2623 {
2624   Mat_SeqAIJ *b;
2625   PetscErrorCode ierr;
2626   int        size;
2627 
2628   PetscFunctionBegin;
2629   ierr = MPI_Comm_size(B->comm,&size);CHKERRQ(ierr);
2630   if (size > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
2631 
2632   B->m = B->M = PetscMax(B->m,B->M);
2633   B->n = B->N = PetscMax(B->n,B->N);
2634 
2635   ierr = PetscNew(Mat_SeqAIJ,&b);CHKERRQ(ierr);
2636   B->data             = (void*)b;
2637   ierr = PetscMemzero(b,sizeof(Mat_SeqAIJ));CHKERRQ(ierr);
2638   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
2639   B->factor           = 0;
2640   B->lupivotthreshold = 1.0;
2641   B->mapping          = 0;
2642   ierr = PetscOptionsGetReal(B->prefix,"-mat_lu_pivotthreshold",&B->lupivotthreshold,PETSC_NULL);CHKERRQ(ierr);
2643   ierr = PetscOptionsHasName(B->prefix,"-pc_ilu_preserve_row_sums",&b->ilu_preserve_row_sums);CHKERRQ(ierr);
2644   b->row              = 0;
2645   b->col              = 0;
2646   b->icol             = 0;
2647   b->reallocs         = 0;
2648 
2649   ierr = PetscMapCreateMPI(B->comm,B->m,B->m,&B->rmap);CHKERRQ(ierr);
2650   ierr = PetscMapCreateMPI(B->comm,B->n,B->n,&B->cmap);CHKERRQ(ierr);
2651 
2652   b->sorted            = PETSC_FALSE;
2653   b->ignorezeroentries = PETSC_FALSE;
2654   b->roworiented       = PETSC_TRUE;
2655   b->nonew             = 0;
2656   b->diag              = 0;
2657   b->solve_work        = 0;
2658   B->spptr             = 0;
2659   b->inode.use         = PETSC_TRUE;
2660   b->inode.node_count  = 0;
2661   b->inode.size        = 0;
2662   b->inode.limit       = 5;
2663   b->inode.max_limit   = 5;
2664   b->saved_values      = 0;
2665   b->idiag             = 0;
2666   b->ssor              = 0;
2667   b->keepzeroedrows    = PETSC_FALSE;
2668   b->xtoy              = 0;
2669   b->XtoY              = 0;
2670 
2671   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
2672 
2673   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C",
2674                                      "MatSeqAIJSetColumnIndices_SeqAIJ",
2675                                      MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
2676   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
2677                                      "MatStoreValues_SeqAIJ",
2678                                      MatStoreValues_SeqAIJ);CHKERRQ(ierr);
2679   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
2680                                      "MatRetrieveValues_SeqAIJ",
2681                                      MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
2682   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",
2683                                      "MatConvert_SeqAIJ_SeqSBAIJ",
2684                                       MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
2685   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C",
2686                                      "MatConvert_SeqAIJ_SeqBAIJ",
2687                                       MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
2688   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C",
2689                                      "MatIsTranspose_SeqAIJ",
2690                                       MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
2691   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C",
2692                                      "MatSeqAIJSetPreallocation_SeqAIJ",
2693                                       MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
2694   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C",
2695                                      "MatReorderForNonzeroDiagonal_SeqAIJ",
2696                                       MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
2697   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatAdjustForInodes_C",
2698                                      "MatAdjustForInodes_SeqAIJ",
2699                                       MatAdjustForInodes_SeqAIJ);CHKERRQ(ierr);
2700   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJGetInodeSizes_C",
2701                                      "MatSeqAIJGetInodeSizes_SeqAIJ",
2702                                       MatSeqAIJGetInodeSizes_SeqAIJ);CHKERRQ(ierr);
2703   PetscFunctionReturn(0);
2704 }
2705 EXTERN_C_END
2706 
2707 #undef __FUNCT__
2708 #define __FUNCT__ "MatDuplicate_SeqAIJ"
2709 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
2710 {
2711   Mat        C;
2712   Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data;
2713   PetscErrorCode ierr;
2714   int        i,m = A->m;
2715   size_t     len;
2716 
2717   PetscFunctionBegin;
2718   *B = 0;
2719   ierr = MatCreate(A->comm,A->m,A->n,A->m,A->n,&C);CHKERRQ(ierr);
2720   ierr = MatSetType(C,A->type_name);CHKERRQ(ierr);
2721   ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2722 
2723   c    = (Mat_SeqAIJ*)C->data;
2724 
2725   C->factor         = A->factor;
2726   c->row            = 0;
2727   c->col            = 0;
2728   c->icol           = 0;
2729   c->keepzeroedrows = a->keepzeroedrows;
2730   C->assembled      = PETSC_TRUE;
2731 
2732   C->M          = A->m;
2733   C->N          = A->n;
2734 
2735   ierr = PetscMalloc((m+1)*sizeof(int),&c->imax);CHKERRQ(ierr);
2736   ierr = PetscMalloc((m+1)*sizeof(int),&c->ilen);CHKERRQ(ierr);
2737   for (i=0; i<m; i++) {
2738     c->imax[i] = a->imax[i];
2739     c->ilen[i] = a->ilen[i];
2740   }
2741 
2742   /* allocate the matrix space */
2743   c->singlemalloc = PETSC_TRUE;
2744   len   = ((size_t) (m+1))*sizeof(int)+(a->i[m])*(sizeof(PetscScalar)+sizeof(int));
2745   ierr  = PetscMalloc(len,&c->a);CHKERRQ(ierr);
2746   c->j  = (int*)(c->a + a->i[m] );
2747   c->i  = c->j + a->i[m];
2748   ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(int));CHKERRQ(ierr);
2749   if (m > 0) {
2750     ierr = PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(int));CHKERRQ(ierr);
2751     if (cpvalues == MAT_COPY_VALUES) {
2752       ierr = PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
2753     } else {
2754       ierr = PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
2755     }
2756   }
2757 
2758   PetscLogObjectMemory(C,len+2*(m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ));
2759   c->sorted      = a->sorted;
2760   c->roworiented = a->roworiented;
2761   c->nonew       = a->nonew;
2762   c->ilu_preserve_row_sums = a->ilu_preserve_row_sums;
2763   c->saved_values = 0;
2764   c->idiag        = 0;
2765   c->ssor         = 0;
2766   c->ignorezeroentries = a->ignorezeroentries;
2767   c->freedata     = PETSC_TRUE;
2768 
2769   if (a->diag) {
2770     ierr = PetscMalloc((m+1)*sizeof(int),&c->diag);CHKERRQ(ierr);
2771     PetscLogObjectMemory(C,(m+1)*sizeof(int));
2772     for (i=0; i<m; i++) {
2773       c->diag[i] = a->diag[i];
2774     }
2775   } else c->diag        = 0;
2776   c->inode.use          = a->inode.use;
2777   c->inode.limit        = a->inode.limit;
2778   c->inode.max_limit    = a->inode.max_limit;
2779   if (a->inode.size){
2780     ierr                = PetscMalloc((m+1)*sizeof(int),&c->inode.size);CHKERRQ(ierr);
2781     c->inode.node_count = a->inode.node_count;
2782     ierr                = PetscMemcpy(c->inode.size,a->inode.size,(m+1)*sizeof(int));CHKERRQ(ierr);
2783   } else {
2784     c->inode.size       = 0;
2785     c->inode.node_count = 0;
2786   }
2787   c->nz                 = a->nz;
2788   c->maxnz              = a->maxnz;
2789   c->solve_work         = 0;
2790   C->preallocated       = PETSC_TRUE;
2791 
2792   *B = C;
2793   ierr = PetscFListDuplicate(A->qlist,&C->qlist);CHKERRQ(ierr);
2794   PetscFunctionReturn(0);
2795 }
2796 
2797 #undef __FUNCT__
2798 #define __FUNCT__ "MatLoad_SeqAIJ"
2799 PetscErrorCode MatLoad_SeqAIJ(PetscViewer viewer,const MatType type,Mat *A)
2800 {
2801   Mat_SeqAIJ   *a;
2802   Mat          B;
2803   PetscErrorCode ierr;
2804   int          i,nz,fd,header[4],size,*rowlengths = 0,M,N;
2805   MPI_Comm     comm;
2806 
2807   PetscFunctionBegin;
2808   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
2809   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
2810   if (size > 1) SETERRQ(PETSC_ERR_ARG_SIZ,"view must have one processor");
2811   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
2812   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
2813   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
2814   M = header[1]; N = header[2]; nz = header[3];
2815 
2816   if (nz < 0) {
2817     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
2818   }
2819 
2820   /* read in row lengths */
2821   ierr = PetscMalloc(M*sizeof(int),&rowlengths);CHKERRQ(ierr);
2822   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
2823 
2824   /* create our matrix */
2825   ierr = MatCreate(comm,PETSC_DECIDE,PETSC_DECIDE,M,N,&B);CHKERRQ(ierr);
2826   ierr = MatSetType(B,type);CHKERRQ(ierr);
2827   ierr = MatSeqAIJSetPreallocation(B,0,rowlengths);CHKERRQ(ierr);
2828   a = (Mat_SeqAIJ*)B->data;
2829 
2830   /* read in column indices and adjust for Fortran indexing*/
2831   ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr);
2832 
2833   /* read in nonzero values */
2834   ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr);
2835 
2836   /* set matrix "i" values */
2837   a->i[0] = 0;
2838   for (i=1; i<= M; i++) {
2839     a->i[i]      = a->i[i-1] + rowlengths[i-1];
2840     a->ilen[i-1] = rowlengths[i-1];
2841   }
2842   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
2843 
2844   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2845   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2846   *A = B;
2847   PetscFunctionReturn(0);
2848 }
2849 
2850 #undef __FUNCT__
2851 #define __FUNCT__ "MatEqual_SeqAIJ"
2852 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg)
2853 {
2854   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data;
2855   PetscErrorCode ierr;
2856 
2857   PetscFunctionBegin;
2858   /* If the  matrix dimensions are not equal,or no of nonzeros */
2859   if ((A->m != B->m) || (A->n != B->n) ||(a->nz != b->nz)) {
2860     *flg = PETSC_FALSE;
2861     PetscFunctionReturn(0);
2862   }
2863 
2864   /* if the a->i are the same */
2865   ierr = PetscMemcmp(a->i,b->i,(A->m+1)*sizeof(int),flg);CHKERRQ(ierr);
2866   if (*flg == PETSC_FALSE) PetscFunctionReturn(0);
2867 
2868   /* if a->j are the same */
2869   ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(int),flg);CHKERRQ(ierr);
2870   if (*flg == PETSC_FALSE) PetscFunctionReturn(0);
2871 
2872   /* if a->a are the same */
2873   ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr);
2874 
2875   PetscFunctionReturn(0);
2876 
2877 }
2878 
2879 #undef __FUNCT__
2880 #define __FUNCT__ "MatCreateSeqAIJWithArrays"
2881 /*@C
2882      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
2883               provided by the user.
2884 
2885       Coolective on MPI_Comm
2886 
2887    Input Parameters:
2888 +   comm - must be an MPI communicator of size 1
2889 .   m - number of rows
2890 .   n - number of columns
2891 .   i - row indices
2892 .   j - column indices
2893 -   a - matrix values
2894 
2895    Output Parameter:
2896 .   mat - the matrix
2897 
2898    Level: intermediate
2899 
2900    Notes:
2901        The i, j, and a arrays are not copied by this routine, the user must free these arrays
2902     once the matrix is destroyed
2903 
2904        You cannot set new nonzero locations into this matrix, that will generate an error.
2905 
2906        The i and j indices are 0 based
2907 
2908 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ()
2909 
2910 @*/
2911 PetscErrorCode MatCreateSeqAIJWithArrays(MPI_Comm comm,int m,int n,int* i,int*j,PetscScalar *a,Mat *mat)
2912 {
2913   PetscErrorCode ierr;
2914   int        ii;
2915   Mat_SeqAIJ *aij;
2916 
2917   PetscFunctionBegin;
2918   ierr = MatCreate(comm,m,n,m,n,mat);CHKERRQ(ierr);
2919   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
2920   ierr = MatSeqAIJSetPreallocation(*mat,SKIP_ALLOCATION,0);CHKERRQ(ierr);
2921   aij  = (Mat_SeqAIJ*)(*mat)->data;
2922 
2923   if (i[0] != 0) {
2924     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
2925   }
2926   aij->i = i;
2927   aij->j = j;
2928   aij->a = a;
2929   aij->singlemalloc = PETSC_FALSE;
2930   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2931   aij->freedata     = PETSC_FALSE;
2932 
2933   for (ii=0; ii<m; ii++) {
2934     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
2935 #if defined(PETSC_USE_BOPT_g)
2936     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]);
2937 #endif
2938   }
2939 #if defined(PETSC_USE_BOPT_g)
2940   for (ii=0; ii<aij->i[m]; ii++) {
2941     if (j[ii] < 0) SETERRQ2(1,"Negative column index at location = %d index = %d",ii,j[ii]);
2942     if (j[ii] > n - 1) SETERRQ2(1,"Column index to large at location = %d index = %d",ii,j[ii]);
2943   }
2944 #endif
2945 
2946   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2947   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2948   PetscFunctionReturn(0);
2949 }
2950 
2951 #undef __FUNCT__
2952 #define __FUNCT__ "MatSetColoring_SeqAIJ"
2953 PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring)
2954 {
2955   PetscErrorCode ierr;
2956   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2957 
2958   PetscFunctionBegin;
2959   if (coloring->ctype == IS_COLORING_LOCAL) {
2960     ierr        = ISColoringReference(coloring);CHKERRQ(ierr);
2961     a->coloring = coloring;
2962   } else if (coloring->ctype == IS_COLORING_GHOSTED) {
2963     int             i,*larray;
2964     ISColoring      ocoloring;
2965     ISColoringValue *colors;
2966 
2967     /* set coloring for diagonal portion */
2968     ierr = PetscMalloc((A->n+1)*sizeof(int),&larray);CHKERRQ(ierr);
2969     for (i=0; i<A->n; i++) {
2970       larray[i] = i;
2971     }
2972     ierr = ISGlobalToLocalMappingApply(A->mapping,IS_GTOLM_MASK,A->n,larray,PETSC_NULL,larray);CHKERRQ(ierr);
2973     ierr = PetscMalloc((A->n+1)*sizeof(ISColoringValue),&colors);CHKERRQ(ierr);
2974     for (i=0; i<A->n; i++) {
2975       colors[i] = coloring->colors[larray[i]];
2976     }
2977     ierr = PetscFree(larray);CHKERRQ(ierr);
2978     ierr = ISColoringCreate(PETSC_COMM_SELF,A->n,colors,&ocoloring);CHKERRQ(ierr);
2979     a->coloring = ocoloring;
2980   }
2981   PetscFunctionReturn(0);
2982 }
2983 
2984 #if defined(PETSC_HAVE_ADIC) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
2985 EXTERN_C_BEGIN
2986 #include "adic/ad_utils.h"
2987 EXTERN_C_END
2988 
2989 #undef __FUNCT__
2990 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ"
2991 PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
2992 {
2993   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
2994   int             m = A->m,*ii = a->i,*jj = a->j,nz,i,j,nlen;
2995   PetscScalar     *v = a->a,*values = ((PetscScalar*)advalues)+1;
2996   ISColoringValue *color;
2997 
2998   PetscFunctionBegin;
2999   if (!a->coloring) SETERRQ(1,"Coloring not set for matrix");
3000   nlen  = PetscADGetDerivTypeSize()/sizeof(PetscScalar);
3001   color = a->coloring->colors;
3002   /* loop over rows */
3003   for (i=0; i<m; i++) {
3004     nz = ii[i+1] - ii[i];
3005     /* loop over columns putting computed value into matrix */
3006     for (j=0; j<nz; j++) {
3007       *v++ = values[color[*jj++]];
3008     }
3009     values += nlen; /* jump to next row of derivatives */
3010   }
3011   PetscFunctionReturn(0);
3012 }
3013 
3014 #else
3015 
3016 #undef __FUNCT__
3017 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ"
3018 PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
3019 {
3020   PetscFunctionBegin;
3021   SETERRQ(1,"PETSc installed without ADIC");
3022 }
3023 
3024 #endif
3025 
3026 #undef __FUNCT__
3027 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ"
3028 PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,int nl,void *advalues)
3029 {
3030   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3031   int             m = A->m,*ii = a->i,*jj = a->j,nz,i,j;
3032   PetscScalar     *v = a->a,*values = (PetscScalar *)advalues;
3033   ISColoringValue *color;
3034 
3035   PetscFunctionBegin;
3036   if (!a->coloring) SETERRQ(1,"Coloring not set for matrix");
3037   color = a->coloring->colors;
3038   /* loop over rows */
3039   for (i=0; i<m; i++) {
3040     nz = ii[i+1] - ii[i];
3041     /* loop over columns putting computed value into matrix */
3042     for (j=0; j<nz; j++) {
3043       *v++ = values[color[*jj++]];
3044     }
3045     values += nl; /* jump to next row of derivatives */
3046   }
3047   PetscFunctionReturn(0);
3048 }
3049 
3050