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