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