xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 354c94de58a434b7a4e66a8dd3b0b59d9623044d)
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,rmax,aa,ai,aj,A->m,rp,ap,imax);
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   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(&zero,v);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(&zero,yy);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,A->n,m,A->n,m,&C);CHKERRQ(ierr);
1388   ierr = MatSetType(C,A->type_name);CHKERRQ(ierr);
1389   ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,col);CHKERRQ(ierr);
1390   ierr = PetscFree(col);CHKERRQ(ierr);
1391   for (i=0; i<m; i++) {
1392     len    = ai[i+1]-ai[i];
1393     ierr   = MatSetValues(C,len,aj,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1394     array += len;
1395     aj    += len;
1396   }
1397 
1398   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1399   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1400 
1401   if (B) {
1402     *B = C;
1403   } else {
1404     ierr = MatHeaderCopy(A,C);CHKERRQ(ierr);
1405   }
1406   PetscFunctionReturn(0);
1407 }
1408 
1409 EXTERN_C_BEGIN
1410 #undef __FUNCT__
1411 #define __FUNCT__ "MatIsTranspose_SeqAIJ"
1412 PetscErrorCode PETSCMAT_DLLEXPORT MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscTruth *f)
1413 {
1414   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1415   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr; PetscScalar *va,*vb;
1416   PetscErrorCode ierr;
1417   PetscInt       ma,na,mb,nb, i;
1418 
1419   PetscFunctionBegin;
1420   bij = (Mat_SeqAIJ *) B->data;
1421 
1422   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
1423   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
1424   if (ma!=nb || na!=mb){
1425     *f = PETSC_FALSE;
1426     PetscFunctionReturn(0);
1427   }
1428   aii = aij->i; bii = bij->i;
1429   adx = aij->j; bdx = bij->j;
1430   va  = aij->a; vb = bij->a;
1431   ierr = PetscMalloc(ma*sizeof(PetscInt),&aptr);CHKERRQ(ierr);
1432   ierr = PetscMalloc(mb*sizeof(PetscInt),&bptr);CHKERRQ(ierr);
1433   for (i=0; i<ma; i++) aptr[i] = aii[i];
1434   for (i=0; i<mb; i++) bptr[i] = bii[i];
1435 
1436   *f = PETSC_TRUE;
1437   for (i=0; i<ma; i++) {
1438     while (aptr[i]<aii[i+1]) {
1439       PetscInt         idc,idr;
1440       PetscScalar vc,vr;
1441       /* column/row index/value */
1442       idc = adx[aptr[i]];
1443       idr = bdx[bptr[idc]];
1444       vc  = va[aptr[i]];
1445       vr  = vb[bptr[idc]];
1446       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
1447 	*f = PETSC_FALSE;
1448         goto done;
1449       } else {
1450 	aptr[i]++;
1451         if (B || i!=idc) bptr[idc]++;
1452       }
1453     }
1454   }
1455  done:
1456   ierr = PetscFree(aptr);CHKERRQ(ierr);
1457   if (B) {
1458     ierr = PetscFree(bptr);CHKERRQ(ierr);
1459   }
1460   PetscFunctionReturn(0);
1461 }
1462 EXTERN_C_END
1463 
1464 #undef __FUNCT__
1465 #define __FUNCT__ "MatIsSymmetric_SeqAIJ"
1466 PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscTruth *f)
1467 {
1468   PetscErrorCode ierr;
1469   PetscFunctionBegin;
1470   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
1471   PetscFunctionReturn(0);
1472 }
1473 
1474 #undef __FUNCT__
1475 #define __FUNCT__ "MatDiagonalScale_SeqAIJ"
1476 PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
1477 {
1478   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1479   PetscScalar    *l,*r,x,*v;
1480   PetscErrorCode ierr;
1481   PetscInt       i,j,m = A->m,n = A->n,M,nz = a->nz,*jj;
1482 
1483   PetscFunctionBegin;
1484   if (ll) {
1485     /* The local size is used so that VecMPI can be passed to this routine
1486        by MatDiagonalScale_MPIAIJ */
1487     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
1488     if (m != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
1489     ierr = VecGetArray(ll,&l);CHKERRQ(ierr);
1490     v = a->a;
1491     for (i=0; i<m; i++) {
1492       x = l[i];
1493       M = a->i[i+1] - a->i[i];
1494       for (j=0; j<M; j++) { (*v++) *= x;}
1495     }
1496     ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr);
1497     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
1498   }
1499   if (rr) {
1500     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
1501     if (n != A->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
1502     ierr = VecGetArray(rr,&r);CHKERRQ(ierr);
1503     v = a->a; jj = a->j;
1504     for (i=0; i<nz; i++) {
1505       (*v++) *= r[*jj++];
1506     }
1507     ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr);
1508     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
1509   }
1510   PetscFunctionReturn(0);
1511 }
1512 
1513 #undef __FUNCT__
1514 #define __FUNCT__ "MatGetSubMatrix_SeqAIJ"
1515 PetscErrorCode MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
1516 {
1517   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*c;
1518   PetscErrorCode ierr;
1519   PetscInt       *smap,i,k,kstart,kend,oldcols = A->n,*lens;
1520   PetscInt       row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
1521   PetscInt       *irow,*icol,nrows,ncols;
1522   PetscInt       *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
1523   PetscScalar    *a_new,*mat_a;
1524   Mat            C;
1525   PetscTruth     stride;
1526 
1527   PetscFunctionBegin;
1528   ierr = ISSorted(isrow,(PetscTruth*)&i);CHKERRQ(ierr);
1529   if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted");
1530   ierr = ISSorted(iscol,(PetscTruth*)&i);CHKERRQ(ierr);
1531   if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted");
1532 
1533   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
1534   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
1535   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
1536 
1537   ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
1538   ierr = ISStride(iscol,&stride);CHKERRQ(ierr);
1539   if (stride && step == 1) {
1540     /* special case of contiguous rows */
1541     ierr   = PetscMalloc((2*nrows+1)*sizeof(PetscInt),&lens);CHKERRQ(ierr);
1542     starts = lens + nrows;
1543     /* loop over new rows determining lens and starting points */
1544     for (i=0; i<nrows; i++) {
1545       kstart  = ai[irow[i]];
1546       kend    = kstart + ailen[irow[i]];
1547       for (k=kstart; k<kend; k++) {
1548         if (aj[k] >= first) {
1549           starts[i] = k;
1550           break;
1551 	}
1552       }
1553       sum = 0;
1554       while (k < kend) {
1555         if (aj[k++] >= first+ncols) break;
1556         sum++;
1557       }
1558       lens[i] = sum;
1559     }
1560     /* create submatrix */
1561     if (scall == MAT_REUSE_MATRIX) {
1562       PetscInt n_cols,n_rows;
1563       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
1564       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
1565       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
1566       C = *B;
1567     } else {
1568       ierr = MatCreate(A->comm,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE,&C);CHKERRQ(ierr);
1569       ierr = MatSetType(C,A->type_name);CHKERRQ(ierr);
1570       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
1571     }
1572     c = (Mat_SeqAIJ*)C->data;
1573 
1574     /* loop over rows inserting into submatrix */
1575     a_new    = c->a;
1576     j_new    = c->j;
1577     i_new    = c->i;
1578 
1579     for (i=0; i<nrows; i++) {
1580       ii    = starts[i];
1581       lensi = lens[i];
1582       for (k=0; k<lensi; k++) {
1583         *j_new++ = aj[ii+k] - first;
1584       }
1585       ierr = PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));CHKERRQ(ierr);
1586       a_new      += lensi;
1587       i_new[i+1]  = i_new[i] + lensi;
1588       c->ilen[i]  = lensi;
1589     }
1590     ierr = PetscFree(lens);CHKERRQ(ierr);
1591   } else {
1592     ierr  = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
1593     ierr  = PetscMalloc((1+oldcols)*sizeof(PetscInt),&smap);CHKERRQ(ierr);
1594 
1595     ierr  = PetscMalloc((1+nrows)*sizeof(PetscInt),&lens);CHKERRQ(ierr);
1596     ierr  = PetscMemzero(smap,oldcols*sizeof(PetscInt));CHKERRQ(ierr);
1597     for (i=0; i<ncols; i++) smap[icol[i]] = i+1;
1598     /* determine lens of each row */
1599     for (i=0; i<nrows; i++) {
1600       kstart  = ai[irow[i]];
1601       kend    = kstart + a->ilen[irow[i]];
1602       lens[i] = 0;
1603       for (k=kstart; k<kend; k++) {
1604         if (smap[aj[k]]) {
1605           lens[i]++;
1606         }
1607       }
1608     }
1609     /* Create and fill new matrix */
1610     if (scall == MAT_REUSE_MATRIX) {
1611       PetscTruth equal;
1612 
1613       c = (Mat_SeqAIJ *)((*B)->data);
1614       if ((*B)->m  != nrows || (*B)->n != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
1615       ierr = PetscMemcmp(c->ilen,lens,(*B)->m*sizeof(PetscInt),&equal);CHKERRQ(ierr);
1616       if (!equal) {
1617         SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
1618       }
1619       ierr = PetscMemzero(c->ilen,(*B)->m*sizeof(PetscInt));CHKERRQ(ierr);
1620       C = *B;
1621     } else {
1622       ierr = MatCreate(A->comm,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE,&C);CHKERRQ(ierr);
1623       ierr = MatSetType(C,A->type_name);CHKERRQ(ierr);
1624       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
1625     }
1626     c = (Mat_SeqAIJ *)(C->data);
1627     for (i=0; i<nrows; i++) {
1628       row    = irow[i];
1629       kstart = ai[row];
1630       kend   = kstart + a->ilen[row];
1631       mat_i  = c->i[i];
1632       mat_j  = c->j + mat_i;
1633       mat_a  = c->a + mat_i;
1634       mat_ilen = c->ilen + i;
1635       for (k=kstart; k<kend; k++) {
1636         if ((tcol=smap[a->j[k]])) {
1637           *mat_j++ = tcol - 1;
1638           *mat_a++ = a->a[k];
1639           (*mat_ilen)++;
1640 
1641         }
1642       }
1643     }
1644     /* Free work space */
1645     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
1646     ierr = PetscFree(smap);CHKERRQ(ierr);
1647     ierr = PetscFree(lens);CHKERRQ(ierr);
1648   }
1649   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1650   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1651 
1652   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
1653   *B = C;
1654   PetscFunctionReturn(0);
1655 }
1656 
1657 /*
1658 */
1659 #undef __FUNCT__
1660 #define __FUNCT__ "MatILUFactor_SeqAIJ"
1661 PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,MatFactorInfo *info)
1662 {
1663   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
1664   PetscErrorCode ierr;
1665   Mat            outA;
1666   PetscTruth     row_identity,col_identity;
1667 
1668   PetscFunctionBegin;
1669   if (info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
1670   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
1671   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
1672   if (!row_identity || !col_identity) {
1673     SETERRQ(PETSC_ERR_ARG_WRONG,"Row and column permutations must be identity for in-place ILU");
1674   }
1675 
1676   outA          = inA;
1677   inA->factor   = FACTOR_LU;
1678   a->row        = row;
1679   a->col        = col;
1680   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
1681   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
1682 
1683   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
1684   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} /* need to remove old one */
1685   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
1686   ierr = PetscLogObjectParent(inA,a->icol);CHKERRQ(ierr);
1687 
1688   if (!a->solve_work) { /* this matrix may have been factored before */
1689      ierr = PetscMalloc((inA->m+1)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr);
1690   }
1691 
1692   if (!a->diag) {
1693     ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
1694   }
1695   ierr = MatLUFactorNumeric_SeqAIJ(inA,info,&outA);CHKERRQ(ierr);
1696   PetscFunctionReturn(0);
1697 }
1698 
1699 #include "petscblaslapack.h"
1700 #undef __FUNCT__
1701 #define __FUNCT__ "MatScale_SeqAIJ"
1702 PetscErrorCode MatScale_SeqAIJ(const PetscScalar *alpha,Mat inA)
1703 {
1704   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)inA->data;
1705   PetscBLASInt bnz = (PetscBLASInt)a->nz,one = 1;
1706   PetscErrorCode ierr;
1707 
1708 
1709   PetscFunctionBegin;
1710   BLASscal_(&bnz,(PetscScalar*)alpha,a->a,&one);
1711   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
1712   PetscFunctionReturn(0);
1713 }
1714 
1715 #undef __FUNCT__
1716 #define __FUNCT__ "MatGetSubMatrices_SeqAIJ"
1717 PetscErrorCode MatGetSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
1718 {
1719   PetscErrorCode ierr;
1720   PetscInt       i;
1721 
1722   PetscFunctionBegin;
1723   if (scall == MAT_INITIAL_MATRIX) {
1724     ierr = PetscMalloc((n+1)*sizeof(Mat),B);CHKERRQ(ierr);
1725   }
1726 
1727   for (i=0; i<n; i++) {
1728     ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
1729   }
1730   PetscFunctionReturn(0);
1731 }
1732 
1733 #undef __FUNCT__
1734 #define __FUNCT__ "MatIncreaseOverlap_SeqAIJ"
1735 PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
1736 {
1737   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1738   PetscErrorCode ierr;
1739   PetscInt       row,i,j,k,l,m,n,*idx,*nidx,isz,val;
1740   PetscInt       start,end,*ai,*aj;
1741   PetscBT        table;
1742 
1743   PetscFunctionBegin;
1744   m     = A->m;
1745   ai    = a->i;
1746   aj    = a->j;
1747 
1748   if (ov < 0)  SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
1749 
1750   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&nidx);CHKERRQ(ierr);
1751   ierr = PetscBTCreate(m,table);CHKERRQ(ierr);
1752 
1753   for (i=0; i<is_max; i++) {
1754     /* Initialize the two local arrays */
1755     isz  = 0;
1756     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
1757 
1758     /* Extract the indices, assume there can be duplicate entries */
1759     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
1760     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
1761 
1762     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
1763     for (j=0; j<n ; ++j){
1764       if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];}
1765     }
1766     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
1767     ierr = ISDestroy(is[i]);CHKERRQ(ierr);
1768 
1769     k = 0;
1770     for (j=0; j<ov; j++){ /* for each overlap */
1771       n = isz;
1772       for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
1773         row   = nidx[k];
1774         start = ai[row];
1775         end   = ai[row+1];
1776         for (l = start; l<end ; l++){
1777           val = aj[l] ;
1778           if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;}
1779         }
1780       }
1781     }
1782     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,(is+i));CHKERRQ(ierr);
1783   }
1784   ierr = PetscBTDestroy(table);CHKERRQ(ierr);
1785   ierr = PetscFree(nidx);CHKERRQ(ierr);
1786   PetscFunctionReturn(0);
1787 }
1788 
1789 /* -------------------------------------------------------------- */
1790 #undef __FUNCT__
1791 #define __FUNCT__ "MatPermute_SeqAIJ"
1792 PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
1793 {
1794   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1795   PetscErrorCode ierr;
1796   PetscInt       i,nz,m = A->m,n = A->n,*col;
1797   PetscInt       *row,*cnew,j,*lens;
1798   IS             icolp,irowp;
1799   PetscInt       *cwork;
1800   PetscScalar    *vwork;
1801 
1802   PetscFunctionBegin;
1803   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
1804   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
1805   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
1806   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
1807 
1808   /* determine lengths of permuted rows */
1809   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&lens);CHKERRQ(ierr);
1810   for (i=0; i<m; i++) {
1811     lens[row[i]] = a->i[i+1] - a->i[i];
1812   }
1813   ierr = MatCreate(A->comm,m,n,m,n,B);CHKERRQ(ierr);
1814   ierr = MatSetType(*B,A->type_name);CHKERRQ(ierr);
1815   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
1816   ierr = PetscFree(lens);CHKERRQ(ierr);
1817 
1818   ierr = PetscMalloc(n*sizeof(PetscInt),&cnew);CHKERRQ(ierr);
1819   for (i=0; i<m; i++) {
1820     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
1821     for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];}
1822     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
1823     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
1824   }
1825   ierr = PetscFree(cnew);CHKERRQ(ierr);
1826   (*B)->assembled     = PETSC_FALSE;
1827   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1828   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1829   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
1830   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
1831   ierr = ISDestroy(irowp);CHKERRQ(ierr);
1832   ierr = ISDestroy(icolp);CHKERRQ(ierr);
1833   PetscFunctionReturn(0);
1834 }
1835 
1836 #undef __FUNCT__
1837 #define __FUNCT__ "MatPrintHelp_SeqAIJ"
1838 PetscErrorCode MatPrintHelp_SeqAIJ(Mat A)
1839 {
1840   static PetscTruth called = PETSC_FALSE;
1841   MPI_Comm          comm = A->comm;
1842   PetscErrorCode    ierr;
1843 
1844   PetscFunctionBegin;
1845   ierr = MatPrintHelp_Inode(A);CHKERRQ(ierr);
1846   if (called) {PetscFunctionReturn(0);} else called = PETSC_TRUE;
1847   ierr = (*PetscHelpPrintf)(comm," Options for MATSEQAIJ and MATMPIAIJ matrix formats (the defaults):\n");CHKERRQ(ierr);
1848   ierr = (*PetscHelpPrintf)(comm,"  -mat_lu_pivotthreshold <threshold>: Set pivoting threshold\n");CHKERRQ(ierr);
1849   ierr = (*PetscHelpPrintf)(comm,"  -mat_aij_oneindex: internal indices begin at 1 instead of the default 0.\n");CHKERRQ(ierr);
1850   ierr = (*PetscHelpPrintf)(comm,"  -mat_no_compressedrow: Do not use compressedrow\n");CHKERRQ(ierr);
1851   PetscFunctionReturn(0);
1852 }
1853 
1854 #undef __FUNCT__
1855 #define __FUNCT__ "MatCopy_SeqAIJ"
1856 PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
1857 {
1858   PetscErrorCode ierr;
1859 
1860   PetscFunctionBegin;
1861   /* If the two matrices have the same copy implementation, use fast copy. */
1862   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
1863     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1864     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
1865 
1866     if (a->i[A->m] != b->i[B->m]) {
1867       SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
1868     }
1869     ierr = PetscMemcpy(b->a,a->a,(a->i[A->m])*sizeof(PetscScalar));CHKERRQ(ierr);
1870   } else {
1871     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
1872   }
1873   PetscFunctionReturn(0);
1874 }
1875 
1876 #undef __FUNCT__
1877 #define __FUNCT__ "MatSetUpPreallocation_SeqAIJ"
1878 PetscErrorCode MatSetUpPreallocation_SeqAIJ(Mat A)
1879 {
1880   PetscErrorCode ierr;
1881 
1882   PetscFunctionBegin;
1883   ierr =  MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);CHKERRQ(ierr);
1884   PetscFunctionReturn(0);
1885 }
1886 
1887 #undef __FUNCT__
1888 #define __FUNCT__ "MatGetArray_SeqAIJ"
1889 PetscErrorCode MatGetArray_SeqAIJ(Mat A,PetscScalar *array[])
1890 {
1891   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1892   PetscFunctionBegin;
1893   *array = a->a;
1894   PetscFunctionReturn(0);
1895 }
1896 
1897 #undef __FUNCT__
1898 #define __FUNCT__ "MatRestoreArray_SeqAIJ"
1899 PetscErrorCode MatRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
1900 {
1901   PetscFunctionBegin;
1902   PetscFunctionReturn(0);
1903 }
1904 
1905 #undef __FUNCT__
1906 #define __FUNCT__ "MatFDColoringApply_SeqAIJ"
1907 PetscErrorCode MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
1908 {
1909   PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f;
1910   PetscErrorCode ierr;
1911   PetscInt       k,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
1912   PetscScalar    dx,mone = -1.0,*y,*xx,*w3_array;
1913   PetscScalar    *vscale_array;
1914   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin;
1915   Vec            w1,w2,w3;
1916   void           *fctx = coloring->fctx;
1917   PetscTruth     flg;
1918 
1919   PetscFunctionBegin;
1920   if (!coloring->w1) {
1921     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
1922     ierr = PetscLogObjectParent(coloring,coloring->w1);CHKERRQ(ierr);
1923     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
1924     ierr = PetscLogObjectParent(coloring,coloring->w2);CHKERRQ(ierr);
1925     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
1926     ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr);
1927   }
1928   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
1929 
1930   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
1931   ierr = PetscOptionsHasName(coloring->prefix,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
1932   if (flg) {
1933     ierr = PetscLogInfo((coloring,"MatFDColoringApply_SeqAIJ: Not calling MatZeroEntries()\n"));CHKERRQ(ierr);
1934   } else {
1935     PetscTruth assembled;
1936     ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
1937     if (assembled) {
1938       ierr = MatZeroEntries(J);CHKERRQ(ierr);
1939     }
1940   }
1941 
1942   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
1943   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
1944 
1945   /*
1946        This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets
1947      coloring->F for the coarser grids from the finest
1948   */
1949   if (coloring->F) {
1950     ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr);
1951     ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr);
1952     if (m1 != m2) {
1953       coloring->F = 0;
1954     }
1955   }
1956 
1957   if (coloring->F) {
1958     w1          = coloring->F;
1959     coloring->F = 0;
1960   } else {
1961     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
1962     ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr);
1963     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
1964   }
1965 
1966   /*
1967       Compute all the scale factors and share with other processors
1968   */
1969   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
1970   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
1971   for (k=0; k<coloring->ncolors; k++) {
1972     /*
1973        Loop over each column associated with color adding the
1974        perturbation to the vector w3.
1975     */
1976     for (l=0; l<coloring->ncolumns[k]; l++) {
1977       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
1978       dx  = xx[col];
1979       if (dx == 0.0) dx = 1.0;
1980 #if !defined(PETSC_USE_COMPLEX)
1981       if (dx < umin && dx >= 0.0)      dx = umin;
1982       else if (dx < 0.0 && dx > -umin) dx = -umin;
1983 #else
1984       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
1985       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
1986 #endif
1987       dx                *= epsilon;
1988       vscale_array[col] = 1.0/dx;
1989     }
1990   }
1991   vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
1992   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1993   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1994 
1995   /*  ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
1996       ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/
1997 
1998   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
1999   else                        vscaleforrow = coloring->columnsforrow;
2000 
2001   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
2002   /*
2003       Loop over each color
2004   */
2005   for (k=0; k<coloring->ncolors; k++) {
2006     coloring->currentcolor = k;
2007     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
2008     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
2009     /*
2010        Loop over each column associated with color adding the
2011        perturbation to the vector w3.
2012     */
2013     for (l=0; l<coloring->ncolumns[k]; l++) {
2014       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
2015       dx  = xx[col];
2016       if (dx == 0.0) dx = 1.0;
2017 #if !defined(PETSC_USE_COMPLEX)
2018       if (dx < umin && dx >= 0.0)      dx = umin;
2019       else if (dx < 0.0 && dx > -umin) dx = -umin;
2020 #else
2021       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
2022       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2023 #endif
2024       dx            *= epsilon;
2025       if (!PetscAbsScalar(dx)) SETERRQ(PETSC_ERR_PLIB,"Computed 0 differencing parameter");
2026       w3_array[col] += dx;
2027     }
2028     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
2029 
2030     /*
2031        Evaluate function at x1 + dx (here dx is a vector of perturbations)
2032     */
2033 
2034     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2035     ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
2036     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2037     ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
2038 
2039     /*
2040        Loop over rows of vector, putting results into Jacobian matrix
2041     */
2042     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
2043     for (l=0; l<coloring->nrows[k]; l++) {
2044       row    = coloring->rows[k][l];
2045       col    = coloring->columnsforrow[k][l];
2046       y[row] *= vscale_array[vscaleforrow[k][l]];
2047       srow   = row + start;
2048       ierr   = MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
2049     }
2050     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
2051   }
2052   coloring->currentcolor = k;
2053   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
2054   xx = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
2055   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2056   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2057   PetscFunctionReturn(0);
2058 }
2059 
2060 #include "petscblaslapack.h"
2061 #undef __FUNCT__
2062 #define __FUNCT__ "MatAXPY_SeqAIJ"
2063 PetscErrorCode MatAXPY_SeqAIJ(const PetscScalar a[],Mat X,Mat Y,MatStructure str)
2064 {
2065   PetscErrorCode ierr;
2066   PetscInt       i;
2067   Mat_SeqAIJ     *x  = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data;
2068   PetscBLASInt   one=1,bnz = (PetscBLASInt)x->nz;
2069 
2070   PetscFunctionBegin;
2071   if (str == SAME_NONZERO_PATTERN) {
2072     BLASaxpy_(&bnz,(PetscScalar*)a,x->a,&one,y->a,&one);
2073   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2074     if (y->xtoy && y->XtoY != X) {
2075       ierr = PetscFree(y->xtoy);CHKERRQ(ierr);
2076       ierr = MatDestroy(y->XtoY);CHKERRQ(ierr);
2077     }
2078     if (!y->xtoy) { /* get xtoy */
2079       ierr = MatAXPYGetxtoy_Private(X->m,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr);
2080       y->XtoY = X;
2081     }
2082     for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += (*a)*(x->a[i]);
2083     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);
2084   } else {
2085     ierr = MatAXPY_Basic(a,X,Y,str);CHKERRQ(ierr);
2086   }
2087   PetscFunctionReturn(0);
2088 }
2089 
2090 #undef __FUNCT__
2091 #define __FUNCT__ "MatSetBlockSize_SeqAIJ"
2092 PetscErrorCode MatSetBlockSize_SeqAIJ(Mat A,PetscInt bs)
2093 {
2094   PetscFunctionBegin;
2095   PetscFunctionReturn(0);
2096 }
2097 
2098 #undef __FUNCT__
2099 #define __FUNCT__ "MatConjugate_SeqAIJ"
2100 PetscErrorCode PETSCMAT_DLLEXPORT MatConjugate_SeqAIJ(Mat mat)
2101 {
2102 #if defined(PETSC_USE_COMPLEX)
2103   Mat_SeqAIJ  *aij = (Mat_SeqAIJ *)mat->data;
2104   PetscInt    i,nz;
2105   PetscScalar *a;
2106 
2107   PetscFunctionBegin;
2108   nz = aij->nz;
2109   a  = aij->a;
2110   for (i=0; i<nz; i++) {
2111     a[i] = PetscConj(a[i]);
2112   }
2113 #else
2114   PetscFunctionBegin;
2115 #endif
2116   PetscFunctionReturn(0);
2117 }
2118 
2119 /* -------------------------------------------------------------------*/
2120 static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
2121        MatGetRow_SeqAIJ,
2122        MatRestoreRow_SeqAIJ,
2123        MatMult_SeqAIJ,
2124 /* 4*/ MatMultAdd_SeqAIJ,
2125        MatMultTranspose_SeqAIJ,
2126        MatMultTransposeAdd_SeqAIJ,
2127        MatSolve_SeqAIJ,
2128        MatSolveAdd_SeqAIJ,
2129        MatSolveTranspose_SeqAIJ,
2130 /*10*/ MatSolveTransposeAdd_SeqAIJ,
2131        MatLUFactor_SeqAIJ,
2132        0,
2133        MatRelax_SeqAIJ,
2134        MatTranspose_SeqAIJ,
2135 /*15*/ MatGetInfo_SeqAIJ,
2136        MatEqual_SeqAIJ,
2137        MatGetDiagonal_SeqAIJ,
2138        MatDiagonalScale_SeqAIJ,
2139        MatNorm_SeqAIJ,
2140 /*20*/ 0,
2141        MatAssemblyEnd_SeqAIJ,
2142        MatCompress_SeqAIJ,
2143        MatSetOption_SeqAIJ,
2144        MatZeroEntries_SeqAIJ,
2145 /*25*/ MatZeroRows_SeqAIJ,
2146        MatLUFactorSymbolic_SeqAIJ,
2147        MatLUFactorNumeric_SeqAIJ,
2148        MatCholeskyFactorSymbolic_SeqAIJ,
2149        MatCholeskyFactorNumeric_SeqAIJ,
2150 /*30*/ MatSetUpPreallocation_SeqAIJ,
2151        MatILUFactorSymbolic_SeqAIJ,
2152        MatICCFactorSymbolic_SeqAIJ,
2153        MatGetArray_SeqAIJ,
2154        MatRestoreArray_SeqAIJ,
2155 /*35*/ MatDuplicate_SeqAIJ,
2156        0,
2157        0,
2158        MatILUFactor_SeqAIJ,
2159        0,
2160 /*40*/ MatAXPY_SeqAIJ,
2161        MatGetSubMatrices_SeqAIJ,
2162        MatIncreaseOverlap_SeqAIJ,
2163        MatGetValues_SeqAIJ,
2164        MatCopy_SeqAIJ,
2165 /*45*/ MatPrintHelp_SeqAIJ,
2166        MatScale_SeqAIJ,
2167        0,
2168        0,
2169        MatILUDTFactor_SeqAIJ,
2170 /*50*/ MatSetBlockSize_SeqAIJ,
2171        MatGetRowIJ_SeqAIJ,
2172        MatRestoreRowIJ_SeqAIJ,
2173        MatGetColumnIJ_SeqAIJ,
2174        MatRestoreColumnIJ_SeqAIJ,
2175 /*55*/ MatFDColoringCreate_SeqAIJ,
2176        0,
2177        0,
2178        MatPermute_SeqAIJ,
2179        0,
2180 /*60*/ 0,
2181        MatDestroy_SeqAIJ,
2182        MatView_SeqAIJ,
2183        MatGetPetscMaps_Petsc,
2184        0,
2185 /*65*/ 0,
2186        0,
2187        0,
2188        0,
2189        0,
2190 /*70*/ 0,
2191        0,
2192        MatSetColoring_SeqAIJ,
2193 #if defined(PETSC_HAVE_ADIC)
2194        MatSetValuesAdic_SeqAIJ,
2195 #else
2196        0,
2197 #endif
2198        MatSetValuesAdifor_SeqAIJ,
2199 /*75*/ MatFDColoringApply_SeqAIJ,
2200        0,
2201        0,
2202        0,
2203        0,
2204 /*80*/ 0,
2205        0,
2206        0,
2207        0,
2208        MatLoad_SeqAIJ,
2209 /*85*/ MatIsSymmetric_SeqAIJ,
2210        0,
2211        0,
2212        0,
2213        0,
2214 /*90*/ MatMatMult_SeqAIJ_SeqAIJ,
2215        MatMatMultSymbolic_SeqAIJ_SeqAIJ,
2216        MatMatMultNumeric_SeqAIJ_SeqAIJ,
2217        MatPtAP_Basic,
2218        MatPtAPSymbolic_SeqAIJ,
2219 /*95*/ MatPtAPNumeric_SeqAIJ,
2220        MatMatMultTranspose_SeqAIJ_SeqAIJ,
2221        MatMatMultTransposeSymbolic_SeqAIJ_SeqAIJ,
2222        MatMatMultTransposeNumeric_SeqAIJ_SeqAIJ,
2223        MatPtAPSymbolic_SeqAIJ_SeqAIJ,
2224 /*100*/MatPtAPNumeric_SeqAIJ_SeqAIJ,
2225        0,
2226        0,
2227        MatConjugate_SeqAIJ
2228 };
2229 
2230 EXTERN_C_BEGIN
2231 #undef __FUNCT__
2232 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ"
2233 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
2234 {
2235   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2236   PetscInt   i,nz,n;
2237 
2238   PetscFunctionBegin;
2239 
2240   nz = aij->maxnz;
2241   n  = mat->n;
2242   for (i=0; i<nz; i++) {
2243     aij->j[i] = indices[i];
2244   }
2245   aij->nz = nz;
2246   for (i=0; i<n; i++) {
2247     aij->ilen[i] = aij->imax[i];
2248   }
2249 
2250   PetscFunctionReturn(0);
2251 }
2252 EXTERN_C_END
2253 
2254 #undef __FUNCT__
2255 #define __FUNCT__ "MatSeqAIJSetColumnIndices"
2256 /*@
2257     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
2258        in the matrix.
2259 
2260   Input Parameters:
2261 +  mat - the SeqAIJ matrix
2262 -  indices - the column indices
2263 
2264   Level: advanced
2265 
2266   Notes:
2267     This can be called if you have precomputed the nonzero structure of the
2268   matrix and want to provide it to the matrix object to improve the performance
2269   of the MatSetValues() operation.
2270 
2271     You MUST have set the correct numbers of nonzeros per row in the call to
2272   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
2273 
2274     MUST be called before any calls to MatSetValues();
2275 
2276     The indices should start with zero, not one.
2277 
2278 @*/
2279 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
2280 {
2281   PetscErrorCode ierr,(*f)(Mat,PetscInt *);
2282 
2283   PetscFunctionBegin;
2284   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2285   PetscValidPointer(indices,2);
2286   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr);
2287   if (f) {
2288     ierr = (*f)(mat,indices);CHKERRQ(ierr);
2289   } else {
2290     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to set column indices");
2291   }
2292   PetscFunctionReturn(0);
2293 }
2294 
2295 /* ----------------------------------------------------------------------------------------*/
2296 
2297 EXTERN_C_BEGIN
2298 #undef __FUNCT__
2299 #define __FUNCT__ "MatStoreValues_SeqAIJ"
2300 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues_SeqAIJ(Mat mat)
2301 {
2302   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
2303   PetscErrorCode ierr;
2304   size_t         nz = aij->i[mat->m];
2305 
2306   PetscFunctionBegin;
2307   if (aij->nonew != 1) {
2308     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
2309   }
2310 
2311   /* allocate space for values if not already there */
2312   if (!aij->saved_values) {
2313     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
2314   }
2315 
2316   /* copy values over */
2317   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2318   PetscFunctionReturn(0);
2319 }
2320 EXTERN_C_END
2321 
2322 #undef __FUNCT__
2323 #define __FUNCT__ "MatStoreValues"
2324 /*@
2325     MatStoreValues - Stashes a copy of the matrix values; this allows, for
2326        example, reuse of the linear part of a Jacobian, while recomputing the
2327        nonlinear portion.
2328 
2329    Collect on Mat
2330 
2331   Input Parameters:
2332 .  mat - the matrix (currently only AIJ matrices support this option)
2333 
2334   Level: advanced
2335 
2336   Common Usage, with SNESSolve():
2337 $    Create Jacobian matrix
2338 $    Set linear terms into matrix
2339 $    Apply boundary conditions to matrix, at this time matrix must have
2340 $      final nonzero structure (i.e. setting the nonlinear terms and applying
2341 $      boundary conditions again will not change the nonzero structure
2342 $    ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS);
2343 $    ierr = MatStoreValues(mat);
2344 $    Call SNESSetJacobian() with matrix
2345 $    In your Jacobian routine
2346 $      ierr = MatRetrieveValues(mat);
2347 $      Set nonlinear terms in matrix
2348 
2349   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
2350 $    // build linear portion of Jacobian
2351 $    ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS);
2352 $    ierr = MatStoreValues(mat);
2353 $    loop over nonlinear iterations
2354 $       ierr = MatRetrieveValues(mat);
2355 $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
2356 $       // call MatAssemblyBegin/End() on matrix
2357 $       Solve linear system with Jacobian
2358 $    endloop
2359 
2360   Notes:
2361     Matrix must already be assemblied before calling this routine
2362     Must set the matrix option MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS); before
2363     calling this routine.
2364 
2365     When this is called multiple times it overwrites the previous set of stored values
2366     and does not allocated additional space.
2367 
2368 .seealso: MatRetrieveValues()
2369 
2370 @*/
2371 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues(Mat mat)
2372 {
2373   PetscErrorCode ierr,(*f)(Mat);
2374 
2375   PetscFunctionBegin;
2376   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2377   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2378   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2379 
2380   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatStoreValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2381   if (f) {
2382     ierr = (*f)(mat);CHKERRQ(ierr);
2383   } else {
2384     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to store values");
2385   }
2386   PetscFunctionReturn(0);
2387 }
2388 
2389 EXTERN_C_BEGIN
2390 #undef __FUNCT__
2391 #define __FUNCT__ "MatRetrieveValues_SeqAIJ"
2392 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues_SeqAIJ(Mat mat)
2393 {
2394   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
2395   PetscErrorCode ierr;
2396   PetscInt       nz = aij->i[mat->m];
2397 
2398   PetscFunctionBegin;
2399   if (aij->nonew != 1) {
2400     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
2401   }
2402   if (!aij->saved_values) {
2403     SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
2404   }
2405   /* copy values over */
2406   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2407   PetscFunctionReturn(0);
2408 }
2409 EXTERN_C_END
2410 
2411 #undef __FUNCT__
2412 #define __FUNCT__ "MatRetrieveValues"
2413 /*@
2414     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
2415        example, reuse of the linear part of a Jacobian, while recomputing the
2416        nonlinear portion.
2417 
2418    Collect on Mat
2419 
2420   Input Parameters:
2421 .  mat - the matrix (currently on AIJ matrices support this option)
2422 
2423   Level: advanced
2424 
2425 .seealso: MatStoreValues()
2426 
2427 @*/
2428 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues(Mat mat)
2429 {
2430   PetscErrorCode ierr,(*f)(Mat);
2431 
2432   PetscFunctionBegin;
2433   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2434   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2435   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2436 
2437   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatRetrieveValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2438   if (f) {
2439     ierr = (*f)(mat);CHKERRQ(ierr);
2440   } else {
2441     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to retrieve values");
2442   }
2443   PetscFunctionReturn(0);
2444 }
2445 
2446 
2447 /* --------------------------------------------------------------------------------*/
2448 #undef __FUNCT__
2449 #define __FUNCT__ "MatCreateSeqAIJ"
2450 /*@C
2451    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
2452    (the default parallel PETSc format).  For good matrix assembly performance
2453    the user should preallocate the matrix storage by setting the parameter nz
2454    (or the array nnz).  By setting these parameters accurately, performance
2455    during matrix assembly can be increased by more than a factor of 50.
2456 
2457    Collective on MPI_Comm
2458 
2459    Input Parameters:
2460 +  comm - MPI communicator, set to PETSC_COMM_SELF
2461 .  m - number of rows
2462 .  n - number of columns
2463 .  nz - number of nonzeros per row (same for all rows)
2464 -  nnz - array containing the number of nonzeros in the various rows
2465          (possibly different for each row) or PETSC_NULL
2466 
2467    Output Parameter:
2468 .  A - the matrix
2469 
2470    Notes:
2471    If nnz is given then nz is ignored
2472 
2473    The AIJ format (also called the Yale sparse matrix format or
2474    compressed row storage), is fully compatible with standard Fortran 77
2475    storage.  That is, the stored row and column indices can begin at
2476    either one (as in Fortran) or zero.  See the users' manual for details.
2477 
2478    Specify the preallocated storage with either nz or nnz (not both).
2479    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2480    allocation.  For large problems you MUST preallocate memory or you
2481    will get TERRIBLE performance, see the users' manual chapter on matrices.
2482 
2483    By default, this format uses inodes (identical nodes) when possible, to
2484    improve numerical efficiency of matrix-vector products and solves. We
2485    search for consecutive rows with the same nonzero structure, thereby
2486    reusing matrix information to achieve increased efficiency.
2487 
2488    Options Database Keys:
2489 +  -mat_no_inode  - Do not use inodes
2490 .  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
2491 -  -mat_aij_oneindex - Internally use indexing starting at 1
2492         rather than 0.  Note that when calling MatSetValues(),
2493         the user still MUST index entries starting at 0!
2494 
2495    Level: intermediate
2496 
2497 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
2498 
2499 @*/
2500 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
2501 {
2502   PetscErrorCode ierr;
2503 
2504   PetscFunctionBegin;
2505   ierr = MatCreate(comm,m,n,m,n,A);CHKERRQ(ierr);
2506   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
2507   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,(PetscInt*)nnz);CHKERRQ(ierr);
2508   PetscFunctionReturn(0);
2509 }
2510 
2511 #undef __FUNCT__
2512 #define __FUNCT__ "MatSeqAIJSetPreallocation"
2513 /*@C
2514    MatSeqAIJSetPreallocation - For good matrix assembly performance
2515    the user should preallocate the matrix storage by setting the parameter nz
2516    (or the array nnz).  By setting these parameters accurately, performance
2517    during matrix assembly can be increased by more than a factor of 50.
2518 
2519    Collective on MPI_Comm
2520 
2521    Input Parameters:
2522 +  B - The matrix
2523 .  nz - number of nonzeros per row (same for all rows)
2524 -  nnz - array containing the number of nonzeros in the various rows
2525          (possibly different for each row) or PETSC_NULL
2526 
2527    Notes:
2528      If nnz is given then nz is ignored
2529 
2530     The AIJ format (also called the Yale sparse matrix format or
2531    compressed row storage), is fully compatible with standard Fortran 77
2532    storage.  That is, the stored row and column indices can begin at
2533    either one (as in Fortran) or zero.  See the users' manual for details.
2534 
2535    Specify the preallocated storage with either nz or nnz (not both).
2536    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2537    allocation.  For large problems you MUST preallocate memory or you
2538    will get TERRIBLE performance, see the users' manual chapter on matrices.
2539 
2540    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
2541    entries or columns indices
2542 
2543    By default, this format uses inodes (identical nodes) when possible, to
2544    improve numerical efficiency of matrix-vector products and solves. We
2545    search for consecutive rows with the same nonzero structure, thereby
2546    reusing matrix information to achieve increased efficiency.
2547 
2548    Options Database Keys:
2549 +  -mat_no_inode  - Do not use inodes
2550 .  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
2551 -  -mat_aij_oneindex - Internally use indexing starting at 1
2552         rather than 0.  Note that when calling MatSetValues(),
2553         the user still MUST index entries starting at 0!
2554 
2555    Level: intermediate
2556 
2557 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
2558 
2559 @*/
2560 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
2561 {
2562   PetscErrorCode ierr,(*f)(Mat,PetscInt,const PetscInt[]);
2563 
2564   PetscFunctionBegin;
2565   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
2566   if (f) {
2567     ierr = (*f)(B,nz,nnz);CHKERRQ(ierr);
2568   }
2569   PetscFunctionReturn(0);
2570 }
2571 
2572 EXTERN_C_BEGIN
2573 #undef __FUNCT__
2574 #define __FUNCT__ "MatSeqAIJSetPreallocation_SeqAIJ"
2575 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,PetscInt *nnz)
2576 {
2577   Mat_SeqAIJ     *b;
2578   PetscTruth     skipallocation = PETSC_FALSE;
2579   PetscErrorCode ierr;
2580   PetscInt       i;
2581 
2582   PetscFunctionBegin;
2583 
2584   if (nz == MAT_SKIP_ALLOCATION) {
2585     skipallocation = PETSC_TRUE;
2586     nz             = 0;
2587   }
2588 
2589   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
2590   if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
2591   if (nnz) {
2592     for (i=0; i<B->m; i++) {
2593       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
2594       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);
2595     }
2596   }
2597 
2598   B->preallocated = PETSC_TRUE;
2599   b = (Mat_SeqAIJ*)B->data;
2600 
2601   if (!skipallocation) {
2602     ierr = PetscMalloc2(B->m,PetscInt,&b->imax,B->m,PetscInt,&b->ilen);CHKERRQ(ierr);
2603     if (!nnz) {
2604       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
2605       else if (nz <= 0)        nz = 1;
2606       for (i=0; i<B->m; i++) b->imax[i] = nz;
2607       nz = nz*B->m;
2608     } else {
2609       nz = 0;
2610       for (i=0; i<B->m; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
2611     }
2612 
2613     /* b->ilen will count nonzeros in each row so far. */
2614     for (i=0; i<B->m; i++) { b->ilen[i] = 0;}
2615 
2616     /* allocate the matrix space */
2617     ierr = PetscMalloc3(nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->m+1,PetscInt,&b->i);CHKERRQ(ierr);
2618     b->i[0] = 0;
2619     for (i=1; i<B->m+1; i++) {
2620       b->i[i] = b->i[i-1] + b->imax[i-1];
2621     }
2622     b->singlemalloc = PETSC_TRUE;
2623     b->freedata     = PETSC_TRUE;
2624   } else {
2625     b->freedata     = PETSC_FALSE;
2626   }
2627 
2628   b->nz                = 0;
2629   b->maxnz             = nz;
2630   B->info.nz_unneeded  = (double)b->maxnz;
2631   PetscFunctionReturn(0);
2632 }
2633 EXTERN_C_END
2634 
2635 /*MC
2636    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
2637    based on compressed sparse row format.
2638 
2639    Options Database Keys:
2640 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
2641 
2642   Level: beginner
2643 
2644 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
2645 M*/
2646 
2647 EXTERN_C_BEGIN
2648 #undef __FUNCT__
2649 #define __FUNCT__ "MatCreate_SeqAIJ"
2650 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqAIJ(Mat B)
2651 {
2652   Mat_SeqAIJ     *b;
2653   PetscErrorCode ierr;
2654   PetscMPIInt    size;
2655 
2656   PetscFunctionBegin;
2657   ierr = MPI_Comm_size(B->comm,&size);CHKERRQ(ierr);
2658   if (size > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
2659 
2660   B->m = B->M = PetscMax(B->m,B->M);
2661   B->n = B->N = PetscMax(B->n,B->N);
2662 
2663   ierr = PetscNew(Mat_SeqAIJ,&b);CHKERRQ(ierr);
2664   B->data             = (void*)b;
2665   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
2666   B->factor           = 0;
2667   B->mapping          = 0;
2668   b->row              = 0;
2669   b->col              = 0;
2670   b->icol             = 0;
2671   b->reallocs         = 0;
2672 
2673   ierr = PetscMapCreateMPI(B->comm,B->m,B->m,&B->rmap);CHKERRQ(ierr);
2674   ierr = PetscMapCreateMPI(B->comm,B->n,B->n,&B->cmap);CHKERRQ(ierr);
2675 
2676   b->sorted            = PETSC_FALSE;
2677   b->ignorezeroentries = PETSC_FALSE;
2678   b->roworiented       = PETSC_TRUE;
2679   b->nonew             = 0;
2680   b->diag              = 0;
2681   b->solve_work        = 0;
2682   B->spptr             = 0;
2683   b->saved_values      = 0;
2684   b->idiag             = 0;
2685   b->ssor              = 0;
2686   b->keepzeroedrows    = PETSC_FALSE;
2687   b->xtoy              = 0;
2688   b->XtoY              = 0;
2689   b->compressedrow.use     = PETSC_FALSE;
2690   b->compressedrow.nrows   = B->m;
2691   b->compressedrow.i       = PETSC_NULL;
2692   b->compressedrow.rindex  = PETSC_NULL;
2693   b->compressedrow.checked = PETSC_FALSE;
2694   B->same_nonzero          = PETSC_FALSE;
2695 
2696   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
2697 
2698   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C",
2699                                      "MatSeqAIJSetColumnIndices_SeqAIJ",
2700                                      MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
2701   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
2702                                      "MatStoreValues_SeqAIJ",
2703                                      MatStoreValues_SeqAIJ);CHKERRQ(ierr);
2704   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
2705                                      "MatRetrieveValues_SeqAIJ",
2706                                      MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
2707   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",
2708                                      "MatConvert_SeqAIJ_SeqSBAIJ",
2709                                       MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
2710   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C",
2711                                      "MatConvert_SeqAIJ_SeqBAIJ",
2712                                       MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
2713   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C",
2714                                      "MatIsTranspose_SeqAIJ",
2715                                       MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
2716   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C",
2717                                      "MatSeqAIJSetPreallocation_SeqAIJ",
2718                                       MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
2719   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C",
2720                                      "MatReorderForNonzeroDiagonal_SeqAIJ",
2721                                       MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
2722   ierr = MatCreate_Inode(B);CHKERRQ(ierr);
2723   PetscFunctionReturn(0);
2724 }
2725 EXTERN_C_END
2726 
2727 #undef __FUNCT__
2728 #define __FUNCT__ "MatDuplicate_SeqAIJ"
2729 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
2730 {
2731   Mat            C;
2732   Mat_SeqAIJ     *c,*a = (Mat_SeqAIJ*)A->data;
2733   PetscErrorCode ierr;
2734   PetscInt       i,m = A->m;
2735 
2736   PetscFunctionBegin;
2737   *B = 0;
2738   ierr = MatCreate(A->comm,A->m,A->n,A->m,A->n,&C);CHKERRQ(ierr);
2739   ierr = MatSetType(C,A->type_name);CHKERRQ(ierr);
2740   ierr = PetscMemcpy(C->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2741 
2742   c = (Mat_SeqAIJ*)C->data;
2743 
2744   C->factor           = A->factor;
2745 
2746   c->row            = 0;
2747   c->col            = 0;
2748   c->icol           = 0;
2749   c->reallocs       = 0;
2750 
2751   C->assembled      = PETSC_TRUE;
2752 
2753   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&c->imax);CHKERRQ(ierr);
2754   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&c->ilen);CHKERRQ(ierr);
2755   for (i=0; i<m; i++) {
2756     c->imax[i] = a->imax[i];
2757     c->ilen[i] = a->ilen[i];
2758   }
2759 
2760   /* allocate the matrix space */
2761   ierr = PetscMalloc3(a->i[m],PetscScalar,&c->a,a->i[m],PetscInt,&c->j,m+1,PetscInt,&c->i);CHKERRQ(ierr);
2762   c->singlemalloc = PETSC_TRUE;
2763   ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
2764   if (m > 0) {
2765     ierr = PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));CHKERRQ(ierr);
2766     if (cpvalues == MAT_COPY_VALUES) {
2767       ierr = PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
2768     } else {
2769       ierr = PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
2770     }
2771   }
2772 
2773   c->sorted            = a->sorted;
2774   c->ignorezeroentries = a->ignorezeroentries;
2775   c->roworiented       = a->roworiented;
2776   c->nonew             = a->nonew;
2777   if (a->diag) {
2778     ierr = PetscMalloc((m+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr);
2779     ierr = PetscLogObjectMemory(C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
2780     for (i=0; i<m; i++) {
2781       c->diag[i] = a->diag[i];
2782     }
2783   } else c->diag        = 0;
2784   c->solve_work         = 0;
2785   c->saved_values          = 0;
2786   c->idiag                 = 0;
2787   c->ssor                  = 0;
2788   c->keepzeroedrows        = a->keepzeroedrows;
2789   c->freedata              = PETSC_TRUE;
2790   c->xtoy                  = 0;
2791   c->XtoY                  = 0;
2792 
2793   c->nz                 = a->nz;
2794   c->maxnz              = a->maxnz;
2795   C->preallocated       = PETSC_TRUE;
2796 
2797   c->compressedrow.use     = a->compressedrow.use;
2798   c->compressedrow.nrows   = a->compressedrow.nrows;
2799   c->compressedrow.checked = a->compressedrow.checked;
2800   if ( a->compressedrow.checked && a->compressedrow.use){
2801     i = a->compressedrow.nrows;
2802     ierr = PetscMalloc((2*i+1)*sizeof(PetscInt),&c->compressedrow.i);CHKERRQ(ierr);
2803     c->compressedrow.rindex = c->compressedrow.i + i + 1;
2804     ierr = PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));CHKERRQ(ierr);
2805     ierr = PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));CHKERRQ(ierr);
2806   } else {
2807     c->compressedrow.use    = PETSC_FALSE;
2808     c->compressedrow.i      = PETSC_NULL;
2809     c->compressedrow.rindex = PETSC_NULL;
2810   }
2811   C->same_nonzero = A->same_nonzero;
2812 
2813   ierr = MatDuplicate_Inode(A,cpvalues,&C);CHKERRQ(ierr);
2814 
2815   *B = C;
2816   ierr = PetscFListDuplicate(A->qlist,&C->qlist);CHKERRQ(ierr);
2817   PetscFunctionReturn(0);
2818 }
2819 
2820 #undef __FUNCT__
2821 #define __FUNCT__ "MatLoad_SeqAIJ"
2822 PetscErrorCode MatLoad_SeqAIJ(PetscViewer viewer,const MatType type,Mat *A)
2823 {
2824   Mat_SeqAIJ     *a;
2825   Mat            B;
2826   PetscErrorCode ierr;
2827   PetscInt       i,sum,nz,header[4],*rowlengths = 0,M,N;
2828   int            fd;
2829   PetscMPIInt    size;
2830   MPI_Comm       comm;
2831 
2832   PetscFunctionBegin;
2833   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
2834   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
2835   if (size > 1) SETERRQ(PETSC_ERR_ARG_SIZ,"view must have one processor");
2836   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
2837   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
2838   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
2839   M = header[1]; N = header[2]; nz = header[3];
2840 
2841   if (nz < 0) {
2842     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
2843   }
2844 
2845   /* read in row lengths */
2846   ierr = PetscMalloc(M*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
2847   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
2848 
2849   /* check if sum of rowlengths is same as nz */
2850   for (i=0,sum=0; i< M; i++) sum +=rowlengths[i];
2851   if (sum != nz) SETERRQ2(PETSC_ERR_FILE_READ,"Inconsistant matrix data in file. no-nonzeros = %d, sum-row-lengths = %d\n",nz,sum);
2852 
2853   /* create our matrix */
2854   ierr = MatCreate(comm,PETSC_DECIDE,PETSC_DECIDE,M,N,&B);CHKERRQ(ierr);
2855   ierr = MatSetType(B,type);CHKERRQ(ierr);
2856   ierr = MatSeqAIJSetPreallocation_SeqAIJ(B,0,rowlengths);CHKERRQ(ierr);
2857   a = (Mat_SeqAIJ*)B->data;
2858 
2859   /* read in column indices and adjust for Fortran indexing*/
2860   ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr);
2861 
2862   /* read in nonzero values */
2863   ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr);
2864 
2865   /* set matrix "i" values */
2866   a->i[0] = 0;
2867   for (i=1; i<= M; i++) {
2868     a->i[i]      = a->i[i-1] + rowlengths[i-1];
2869     a->ilen[i-1] = rowlengths[i-1];
2870   }
2871   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
2872 
2873   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2874   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2875   *A = B;
2876   PetscFunctionReturn(0);
2877 }
2878 
2879 #undef __FUNCT__
2880 #define __FUNCT__ "MatEqual_SeqAIJ"
2881 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg)
2882 {
2883   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data;
2884   PetscErrorCode ierr;
2885 
2886   PetscFunctionBegin;
2887   /* If the  matrix dimensions are not equal,or no of nonzeros */
2888   if ((A->m != B->m) || (A->n != B->n) ||(a->nz != b->nz)) {
2889     *flg = PETSC_FALSE;
2890     PetscFunctionReturn(0);
2891   }
2892 
2893   /* if the a->i are the same */
2894   ierr = PetscMemcmp(a->i,b->i,(A->m+1)*sizeof(PetscInt),flg);CHKERRQ(ierr);
2895   if (!*flg) PetscFunctionReturn(0);
2896 
2897   /* if a->j are the same */
2898   ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);CHKERRQ(ierr);
2899   if (!*flg) PetscFunctionReturn(0);
2900 
2901   /* if a->a are the same */
2902   ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr);
2903 
2904   PetscFunctionReturn(0);
2905 
2906 }
2907 
2908 #undef __FUNCT__
2909 #define __FUNCT__ "MatCreateSeqAIJWithArrays"
2910 /*@C
2911      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
2912               provided by the user.
2913 
2914       Coolective on MPI_Comm
2915 
2916    Input Parameters:
2917 +   comm - must be an MPI communicator of size 1
2918 .   m - number of rows
2919 .   n - number of columns
2920 .   i - row indices
2921 .   j - column indices
2922 -   a - matrix values
2923 
2924    Output Parameter:
2925 .   mat - the matrix
2926 
2927    Level: intermediate
2928 
2929    Notes:
2930        The i, j, and a arrays are not copied by this routine, the user must free these arrays
2931     once the matrix is destroyed
2932 
2933        You cannot set new nonzero locations into this matrix, that will generate an error.
2934 
2935        The i and j indices are 0 based
2936 
2937 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ()
2938 
2939 @*/
2940 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
2941 {
2942   PetscErrorCode ierr;
2943   PetscInt       ii;
2944   Mat_SeqAIJ     *aij;
2945 
2946   PetscFunctionBegin;
2947   if (i[0]) {
2948     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
2949   }
2950   ierr = MatCreate(comm,m,n,m,n,mat);CHKERRQ(ierr);
2951   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
2952   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr);
2953   aij  = (Mat_SeqAIJ*)(*mat)->data;
2954   ierr = PetscMalloc2(m,PetscInt,&aij->imax,m,PetscInt,&aij->ilen);CHKERRQ(ierr);
2955 
2956   aij->i = i;
2957   aij->j = j;
2958   aij->a = a;
2959   aij->singlemalloc = PETSC_FALSE;
2960   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2961   aij->freedata     = PETSC_FALSE;
2962 
2963   for (ii=0; ii<m; ii++) {
2964     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
2965 #if defined(PETSC_USE_DEBUG)
2966     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]);
2967 #endif
2968   }
2969 #if defined(PETSC_USE_DEBUG)
2970   for (ii=0; ii<aij->i[m]; ii++) {
2971     if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
2972     if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]);
2973   }
2974 #endif
2975 
2976   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2977   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2978   PetscFunctionReturn(0);
2979 }
2980 
2981 #undef __FUNCT__
2982 #define __FUNCT__ "MatSetColoring_SeqAIJ"
2983 PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring)
2984 {
2985   PetscErrorCode ierr;
2986   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2987 
2988   PetscFunctionBegin;
2989   if (coloring->ctype == IS_COLORING_LOCAL) {
2990     ierr        = ISColoringReference(coloring);CHKERRQ(ierr);
2991     a->coloring = coloring;
2992   } else if (coloring->ctype == IS_COLORING_GHOSTED) {
2993     PetscInt             i,*larray;
2994     ISColoring      ocoloring;
2995     ISColoringValue *colors;
2996 
2997     /* set coloring for diagonal portion */
2998     ierr = PetscMalloc((A->n+1)*sizeof(PetscInt),&larray);CHKERRQ(ierr);
2999     for (i=0; i<A->n; i++) {
3000       larray[i] = i;
3001     }
3002     ierr = ISGlobalToLocalMappingApply(A->mapping,IS_GTOLM_MASK,A->n,larray,PETSC_NULL,larray);CHKERRQ(ierr);
3003     ierr = PetscMalloc((A->n+1)*sizeof(ISColoringValue),&colors);CHKERRQ(ierr);
3004     for (i=0; i<A->n; i++) {
3005       colors[i] = coloring->colors[larray[i]];
3006     }
3007     ierr = PetscFree(larray);CHKERRQ(ierr);
3008     ierr = ISColoringCreate(PETSC_COMM_SELF,A->n,colors,&ocoloring);CHKERRQ(ierr);
3009     a->coloring = ocoloring;
3010   }
3011   PetscFunctionReturn(0);
3012 }
3013 
3014 #if defined(PETSC_HAVE_ADIC)
3015 EXTERN_C_BEGIN
3016 #include "adic/ad_utils.h"
3017 EXTERN_C_END
3018 
3019 #undef __FUNCT__
3020 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ"
3021 PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
3022 {
3023   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3024   PetscInt        m = A->m,*ii = a->i,*jj = a->j,nz,i,j,nlen;
3025   PetscScalar     *v = a->a,*values = ((PetscScalar*)advalues)+1;
3026   ISColoringValue *color;
3027 
3028   PetscFunctionBegin;
3029   if (!a->coloring) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
3030   nlen  = PetscADGetDerivTypeSize()/sizeof(PetscScalar);
3031   color = a->coloring->colors;
3032   /* loop over rows */
3033   for (i=0; i<m; i++) {
3034     nz = ii[i+1] - ii[i];
3035     /* loop over columns putting computed value into matrix */
3036     for (j=0; j<nz; j++) {
3037       *v++ = values[color[*jj++]];
3038     }
3039     values += nlen; /* jump to next row of derivatives */
3040   }
3041   PetscFunctionReturn(0);
3042 }
3043 #endif
3044 
3045 #undef __FUNCT__
3046 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ"
3047 PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues)
3048 {
3049   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3050   PetscInt             m = A->m,*ii = a->i,*jj = a->j,nz,i,j;
3051   PetscScalar     *v = a->a,*values = (PetscScalar *)advalues;
3052   ISColoringValue *color;
3053 
3054   PetscFunctionBegin;
3055   if (!a->coloring) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
3056   color = a->coloring->colors;
3057   /* loop over rows */
3058   for (i=0; i<m; i++) {
3059     nz = ii[i+1] - ii[i];
3060     /* loop over columns putting computed value into matrix */
3061     for (j=0; j<nz; j++) {
3062       *v++ = values[color[*jj++]];
3063     }
3064     values += nl; /* jump to next row of derivatives */
3065   }
3066   PetscFunctionReturn(0);
3067 }
3068 
3069