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