xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 5a586d828132823a7f656d0d7f79985f923612fa)
1 #define PETSCMAT_DLL
2 
3 
4 /*
5     Defines the basic matrix operations for the AIJ (compressed row)
6   matrix storage format.
7 */
8 
9 
10 #include "../src/mat/impls/aij/seq/aij.h"          /*I "petscmat.h" I*/
11 #include "petscblaslapack.h"
12 #include "petscbt.h"
13 
14 #undef __FUNCT__
15 #define __FUNCT__ "MatDiagonalSet_SeqAIJ"
16 PetscErrorCode PETSCMAT_DLLEXPORT MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
17 {
18   PetscErrorCode ierr;
19   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) Y->data;
20   PetscInt       i,*diag, m = Y->rmap->n;
21   MatScalar      *aa = aij->a;
22   PetscScalar    *v;
23   PetscTruth     missing;
24 
25   PetscFunctionBegin;
26   if (Y->assembled) {
27     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,PETSC_NULL);CHKERRQ(ierr);
28     if (!missing) {
29       diag = aij->diag;
30       ierr = VecGetArray(D,&v);CHKERRQ(ierr);
31       if (is == INSERT_VALUES) {
32 	for (i=0; i<m; i++) {
33 	  aa[diag[i]] = v[i];
34 	}
35       } else {
36 	for (i=0; i<m; i++) {
37 	  aa[diag[i]] += v[i];
38 	}
39       }
40       ierr = VecRestoreArray(D,&v);CHKERRQ(ierr);
41       PetscFunctionReturn(0);
42     }
43   }
44   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
45   PetscFunctionReturn(0);
46 }
47 
48 #undef __FUNCT__
49 #define __FUNCT__ "MatGetRowIJ_SeqAIJ"
50 PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *m,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
51 {
52   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
53   PetscErrorCode ierr;
54   PetscInt       i,ishift;
55 
56   PetscFunctionBegin;
57   *m     = A->rmap->n;
58   if (!ia) PetscFunctionReturn(0);
59   ishift = 0;
60   if (symmetric && !A->structurally_symmetric) {
61     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,ishift,oshift,ia,ja);CHKERRQ(ierr);
62   } else if (oshift == 1) {
63     PetscInt nz = a->i[A->rmap->n];
64     /* malloc space and  add 1 to i and j indices */
65     ierr = PetscMalloc((A->rmap->n+1)*sizeof(PetscInt),ia);CHKERRQ(ierr);
66     for (i=0; i<A->rmap->n+1; i++) (*ia)[i] = a->i[i] + 1;
67     if (ja) {
68       ierr = PetscMalloc((nz+1)*sizeof(PetscInt),ja);CHKERRQ(ierr);
69       for (i=0; i<nz; i++) (*ja)[i] = a->j[i] + 1;
70     }
71   } else {
72     *ia = a->i;
73     if (ja) *ja = a->j;
74   }
75   PetscFunctionReturn(0);
76 }
77 
78 #undef __FUNCT__
79 #define __FUNCT__ "MatRestoreRowIJ_SeqAIJ"
80 PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
81 {
82   PetscErrorCode ierr;
83 
84   PetscFunctionBegin;
85   if (!ia) PetscFunctionReturn(0);
86   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
87     ierr = PetscFree(*ia);CHKERRQ(ierr);
88     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
89   }
90   PetscFunctionReturn(0);
91 }
92 
93 #undef __FUNCT__
94 #define __FUNCT__ "MatGetColumnIJ_SeqAIJ"
95 PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
96 {
97   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
98   PetscErrorCode ierr;
99   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
100   PetscInt       nz = a->i[m],row,*jj,mr,col;
101 
102   PetscFunctionBegin;
103   *nn = n;
104   if (!ia) PetscFunctionReturn(0);
105   if (symmetric) {
106     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,0,oshift,ia,ja);CHKERRQ(ierr);
107   } else {
108     ierr = PetscMalloc((n+1)*sizeof(PetscInt),&collengths);CHKERRQ(ierr);
109     ierr = PetscMemzero(collengths,n*sizeof(PetscInt));CHKERRQ(ierr);
110     ierr = PetscMalloc((n+1)*sizeof(PetscInt),&cia);CHKERRQ(ierr);
111     ierr = PetscMalloc((nz+1)*sizeof(PetscInt),&cja);CHKERRQ(ierr);
112     jj = a->j;
113     for (i=0; i<nz; i++) {
114       collengths[jj[i]]++;
115     }
116     cia[0] = oshift;
117     for (i=0; i<n; i++) {
118       cia[i+1] = cia[i] + collengths[i];
119     }
120     ierr = PetscMemzero(collengths,n*sizeof(PetscInt));CHKERRQ(ierr);
121     jj   = a->j;
122     for (row=0; row<m; row++) {
123       mr = a->i[row+1] - a->i[row];
124       for (i=0; i<mr; i++) {
125         col = *jj++;
126         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
127       }
128     }
129     ierr = PetscFree(collengths);CHKERRQ(ierr);
130     *ia = cia; *ja = cja;
131   }
132   PetscFunctionReturn(0);
133 }
134 
135 #undef __FUNCT__
136 #define __FUNCT__ "MatRestoreColumnIJ_SeqAIJ"
137 PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
138 {
139   PetscErrorCode ierr;
140 
141   PetscFunctionBegin;
142   if (!ia) PetscFunctionReturn(0);
143 
144   ierr = PetscFree(*ia);CHKERRQ(ierr);
145   ierr = PetscFree(*ja);CHKERRQ(ierr);
146 
147   PetscFunctionReturn(0);
148 }
149 
150 #undef __FUNCT__
151 #define __FUNCT__ "MatSetValuesRow_SeqAIJ"
152 PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
153 {
154   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
155   PetscInt       *ai = a->i;
156   PetscErrorCode ierr;
157 
158   PetscFunctionBegin;
159   ierr = PetscMemcpy(a->a+ai[row],v,(ai[row+1]-ai[row])*sizeof(PetscScalar));CHKERRQ(ierr);
160   PetscFunctionReturn(0);
161 }
162 
163 #undef __FUNCT__
164 #define __FUNCT__ "MatSetValues_SeqAIJ"
165 PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
166 {
167   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
168   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
169   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
170   PetscErrorCode ierr;
171   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
172   MatScalar      *ap,value,*aa = a->a;
173   PetscTruth     ignorezeroentries = a->ignorezeroentries;
174   PetscTruth     roworiented = a->roworiented;
175 
176   PetscFunctionBegin;
177   if (v) PetscValidScalarPointer(v,6);
178   for (k=0; k<m; k++) { /* loop over added rows */
179     row  = im[k];
180     if (row < 0) continue;
181 #if defined(PETSC_USE_DEBUG)
182     if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
183 #endif
184     rp   = aj + ai[row]; ap = aa + ai[row];
185     rmax = imax[row]; nrow = ailen[row];
186     low  = 0;
187     high = nrow;
188     for (l=0; l<n; l++) { /* loop over added columns */
189       if (in[l] < 0) continue;
190 #if defined(PETSC_USE_DEBUG)
191       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
192 #endif
193       col = in[l];
194       if (v) {
195 	if (roworiented) {
196 	  value = v[l + k*n];
197 	} else {
198 	  value = v[k + l*m];
199 	}
200       } else {
201         value = 0.;
202       }
203       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
204 
205       if (col <= lastcol) low = 0; else high = nrow;
206       lastcol = col;
207       while (high-low > 5) {
208         t = (low+high)/2;
209         if (rp[t] > col) high = t;
210         else             low  = t;
211       }
212       for (i=low; i<high; i++) {
213         if (rp[i] > col) break;
214         if (rp[i] == col) {
215           if (is == ADD_VALUES) ap[i] += value;
216           else                  ap[i] = value;
217           low = i + 1;
218           goto noinsert;
219         }
220       }
221       if (value == 0.0 && ignorezeroentries) goto noinsert;
222       if (nonew == 1) goto noinsert;
223       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
224       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
225       N = nrow++ - 1; a->nz++; high++;
226       /* shift up all the later entries in this row */
227       for (ii=N; ii>=i; ii--) {
228         rp[ii+1] = rp[ii];
229         ap[ii+1] = ap[ii];
230       }
231       rp[i] = col;
232       ap[i] = value;
233       low   = i + 1;
234       noinsert:;
235     }
236     ailen[row] = nrow;
237   }
238   A->same_nonzero = PETSC_FALSE;
239   PetscFunctionReturn(0);
240 }
241 
242 
243 #undef __FUNCT__
244 #define __FUNCT__ "MatGetValues_SeqAIJ"
245 PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
246 {
247   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
248   PetscInt     *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
249   PetscInt     *ai = a->i,*ailen = a->ilen;
250   MatScalar    *ap,*aa = a->a;
251 
252   PetscFunctionBegin;
253   for (k=0; k<m; k++) { /* loop over rows */
254     row  = im[k];
255     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
256     if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
257     rp   = aj + ai[row]; ap = aa + ai[row];
258     nrow = ailen[row];
259     for (l=0; l<n; l++) { /* loop over columns */
260       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
261       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
262       col = in[l] ;
263       high = nrow; low = 0; /* assume unsorted */
264       while (high-low > 5) {
265         t = (low+high)/2;
266         if (rp[t] > col) high = t;
267         else             low  = t;
268       }
269       for (i=low; i<high; i++) {
270         if (rp[i] > col) break;
271         if (rp[i] == col) {
272           *v++ = ap[i];
273           goto finished;
274         }
275       }
276       *v++ = 0.0;
277       finished:;
278     }
279   }
280   PetscFunctionReturn(0);
281 }
282 
283 
284 #undef __FUNCT__
285 #define __FUNCT__ "MatView_SeqAIJ_Binary"
286 PetscErrorCode MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer)
287 {
288   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
289   PetscErrorCode ierr;
290   PetscInt       i,*col_lens;
291   int            fd;
292 
293   PetscFunctionBegin;
294   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
295   ierr = PetscMalloc((4+A->rmap->n)*sizeof(PetscInt),&col_lens);CHKERRQ(ierr);
296   col_lens[0] = MAT_FILE_CLASSID;
297   col_lens[1] = A->rmap->n;
298   col_lens[2] = A->cmap->n;
299   col_lens[3] = a->nz;
300 
301   /* store lengths of each row and write (including header) to file */
302   for (i=0; i<A->rmap->n; i++) {
303     col_lens[4+i] = a->i[i+1] - a->i[i];
304   }
305   ierr = PetscBinaryWrite(fd,col_lens,4+A->rmap->n,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
306   ierr = PetscFree(col_lens);CHKERRQ(ierr);
307 
308   /* store column indices (zero start index) */
309   ierr = PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
310 
311   /* store nonzero values */
312   ierr = PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
313   PetscFunctionReturn(0);
314 }
315 
316 EXTERN PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
317 
318 #undef __FUNCT__
319 #define __FUNCT__ "MatView_SeqAIJ_ASCII"
320 PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
321 {
322   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
323   PetscErrorCode    ierr;
324   PetscInt          i,j,m = A->rmap->n,shift=0;
325   const char        *name;
326   PetscViewerFormat format;
327 
328   PetscFunctionBegin;
329   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
330   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
331   if (format == PETSC_VIEWER_ASCII_MATLAB) {
332     PetscInt nofinalvalue = 0;
333     if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-!shift)) {
334       nofinalvalue = 1;
335     }
336     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
337     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
338     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
339     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
340     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
341 
342     for (i=0; i<m; i++) {
343       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
344 #if defined(PETSC_USE_COMPLEX)
345         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);
346 #else
347         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+!shift,a->a[j]);CHKERRQ(ierr);
348 #endif
349       }
350     }
351     if (nofinalvalue) {
352       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
353     }
354     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
355     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
356   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
357      PetscFunctionReturn(0);
358   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
359     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
360     for (i=0; i<m; i++) {
361       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
362       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
363 #if defined(PETSC_USE_COMPLEX)
364         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
365           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
366         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
367           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
368         } else if (PetscRealPart(a->a[j]) != 0.0) {
369           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
370         }
371 #else
372         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);}
373 #endif
374       }
375       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
376     }
377     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
378   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
379     PetscInt nzd=0,fshift=1,*sptr;
380     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
381     ierr = PetscMalloc((m+1)*sizeof(PetscInt),&sptr);CHKERRQ(ierr);
382     for (i=0; i<m; i++) {
383       sptr[i] = nzd+1;
384       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
385         if (a->j[j] >= i) {
386 #if defined(PETSC_USE_COMPLEX)
387           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
388 #else
389           if (a->a[j] != 0.0) nzd++;
390 #endif
391         }
392       }
393     }
394     sptr[m] = nzd+1;
395     ierr = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
396     for (i=0; i<m+1; i+=6) {
397       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);}
398       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);}
399       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);}
400       else if (i+1<m) {ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);}
401       else if (i<m)   {ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);}
402       else            {ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);}
403     }
404     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
405     ierr = PetscFree(sptr);CHKERRQ(ierr);
406     for (i=0; i<m; i++) {
407       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
408         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
409       }
410       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
411     }
412     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
413     for (i=0; i<m; i++) {
414       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
415         if (a->j[j] >= i) {
416 #if defined(PETSC_USE_COMPLEX)
417           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
418             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
419           }
420 #else
421           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",a->a[j]);CHKERRQ(ierr);}
422 #endif
423         }
424       }
425       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
426     }
427     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
428   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
429     PetscInt         cnt = 0,jcnt;
430     PetscScalar value;
431 
432     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
433     for (i=0; i<m; i++) {
434       jcnt = 0;
435       for (j=0; j<A->cmap->n; j++) {
436         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
437           value = a->a[cnt++];
438           jcnt++;
439         } else {
440           value = 0.0;
441         }
442 #if defined(PETSC_USE_COMPLEX)
443         ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",PetscRealPart(value),PetscImaginaryPart(value));CHKERRQ(ierr);
444 #else
445         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",value);CHKERRQ(ierr);
446 #endif
447       }
448       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
449     }
450     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
451   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
452     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
453 #if defined(PETSC_USE_COMPLEX)
454     ierr = PetscViewerASCIIPrintf(viewer,"%%matrix complex general\n");CHKERRQ(ierr);
455 #else
456     ierr = PetscViewerASCIIPrintf(viewer,"%%matrix real general\n");CHKERRQ(ierr);
457 #endif
458     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
459     for (i=0; i<m; i++) {
460       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
461 #if defined(PETSC_USE_COMPLEX)
462         if (PetscImaginaryPart(a->a[j]) > 0.0) {
463           ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
464         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
465           ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G -%G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
466         } else {
467           ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
468         }
469 #else
470         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %G\n", i+shift, a->j[j]+shift, a->a[j]);CHKERRQ(ierr);
471 #endif
472       }
473     }
474     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
475   } else {
476     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
477     if (A->factortype){
478       for (i=0; i<m; i++) {
479         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
480         /* L part */
481 	for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
482 #if defined(PETSC_USE_COMPLEX)
483           if (PetscImaginaryPart(a->a[j]) > 0.0) {
484             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
485           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
486             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
487           } else {
488             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
489           }
490 #else
491           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);
492 #endif
493         }
494 	/* diagonal */
495 	j = a->diag[i];
496 #if defined(PETSC_USE_COMPLEX)
497         if (PetscImaginaryPart(a->a[j]) > 0.0) {
498             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
499           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
500             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
501           } else {
502             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
503           }
504 #else
505           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);
506 #endif
507 
508 	/* U part */
509 	for (j=a->diag[i+1]+1+shift; j<a->diag[i]+shift; j++) {
510 #if defined(PETSC_USE_COMPLEX)
511           if (PetscImaginaryPart(a->a[j]) > 0.0) {
512             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
513           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
514             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
515           } else {
516             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
517           }
518 #else
519           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);
520 #endif
521 }
522 	  ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
523         }
524     } else {
525       for (i=0; i<m; i++) {
526         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
527         for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
528 #if defined(PETSC_USE_COMPLEX)
529           if (PetscImaginaryPart(a->a[j]) > 0.0) {
530             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
531           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
532             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
533           } else {
534             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
535           }
536 #else
537           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);
538 #endif
539         }
540         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
541       }
542     }
543     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
544   }
545   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
546   PetscFunctionReturn(0);
547 }
548 
549 #undef __FUNCT__
550 #define __FUNCT__ "MatView_SeqAIJ_Draw_Zoom"
551 PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
552 {
553   Mat               A = (Mat) Aa;
554   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
555   PetscErrorCode    ierr;
556   PetscInt          i,j,m = A->rmap->n,color;
557   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r,maxv = 0.0;
558   PetscViewer       viewer;
559   PetscViewerFormat format;
560 
561   PetscFunctionBegin;
562   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
563   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
564 
565   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
566   /* loop over matrix elements drawing boxes */
567 
568   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
569     /* Blue for negative, Cyan for zero and  Red for positive */
570     color = PETSC_DRAW_BLUE;
571     for (i=0; i<m; i++) {
572       y_l = m - i - 1.0; y_r = y_l + 1.0;
573       for (j=a->i[i]; j<a->i[i+1]; j++) {
574         x_l = a->j[j] ; x_r = x_l + 1.0;
575 #if defined(PETSC_USE_COMPLEX)
576         if (PetscRealPart(a->a[j]) >=  0.) continue;
577 #else
578         if (a->a[j] >=  0.) continue;
579 #endif
580         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
581       }
582     }
583     color = PETSC_DRAW_CYAN;
584     for (i=0; i<m; i++) {
585       y_l = m - i - 1.0; y_r = y_l + 1.0;
586       for (j=a->i[i]; j<a->i[i+1]; j++) {
587         x_l = a->j[j]; x_r = x_l + 1.0;
588         if (a->a[j] !=  0.) continue;
589         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
590       }
591     }
592     color = PETSC_DRAW_RED;
593     for (i=0; i<m; i++) {
594       y_l = m - i - 1.0; y_r = y_l + 1.0;
595       for (j=a->i[i]; j<a->i[i+1]; j++) {
596         x_l = a->j[j]; x_r = x_l + 1.0;
597 #if defined(PETSC_USE_COMPLEX)
598         if (PetscRealPart(a->a[j]) <=  0.) continue;
599 #else
600         if (a->a[j] <=  0.) continue;
601 #endif
602         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
603       }
604     }
605   } else {
606     /* use contour shading to indicate magnitude of values */
607     /* first determine max of all nonzero values */
608     PetscInt    nz = a->nz,count;
609     PetscDraw   popup;
610     PetscReal scale;
611 
612     for (i=0; i<nz; i++) {
613       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
614     }
615     scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv;
616     ierr  = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
617     if (popup) {ierr  = PetscDrawScalePopup(popup,0.0,maxv);CHKERRQ(ierr);}
618     count = 0;
619     for (i=0; i<m; i++) {
620       y_l = m - i - 1.0; y_r = y_l + 1.0;
621       for (j=a->i[i]; j<a->i[i+1]; j++) {
622         x_l = a->j[j]; x_r = x_l + 1.0;
623         color = PETSC_DRAW_BASIC_COLORS + (PetscInt)(scale*PetscAbsScalar(a->a[count]));
624         ierr  = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
625         count++;
626       }
627     }
628   }
629   PetscFunctionReturn(0);
630 }
631 
632 #undef __FUNCT__
633 #define __FUNCT__ "MatView_SeqAIJ_Draw"
634 PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
635 {
636   PetscErrorCode ierr;
637   PetscDraw      draw;
638   PetscReal      xr,yr,xl,yl,h,w;
639   PetscTruth     isnull;
640 
641   PetscFunctionBegin;
642   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
643   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
644   if (isnull) PetscFunctionReturn(0);
645 
646   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
647   xr  = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0;
648   xr += w;    yr += h;  xl = -w;     yl = -h;
649   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
650   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
651   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
652   PetscFunctionReturn(0);
653 }
654 
655 #undef __FUNCT__
656 #define __FUNCT__ "MatView_SeqAIJ"
657 PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
658 {
659   PetscErrorCode ierr;
660   PetscTruth     iascii,isbinary,isdraw;
661 
662   PetscFunctionBegin;
663   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
664   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
665   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
666   if (iascii) {
667     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
668   } else if (isbinary) {
669     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
670   } else if (isdraw) {
671     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
672   } else {
673     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by SeqAIJ matrices",((PetscObject)viewer)->type_name);
674   }
675   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
676   PetscFunctionReturn(0);
677 }
678 
679 #undef __FUNCT__
680 #define __FUNCT__ "MatAssemblyEnd_SeqAIJ"
681 PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
682 {
683   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
684   PetscErrorCode ierr;
685   PetscInt       fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
686   PetscInt       m = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
687   MatScalar      *aa = a->a,*ap;
688   PetscReal      ratio=0.6;
689 
690   PetscFunctionBegin;
691   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
692 
693   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
694   for (i=1; i<m; i++) {
695     /* move each row back by the amount of empty slots (fshift) before it*/
696     fshift += imax[i-1] - ailen[i-1];
697     rmax   = PetscMax(rmax,ailen[i]);
698     if (fshift) {
699       ip = aj + ai[i] ;
700       ap = aa + ai[i] ;
701       N  = ailen[i];
702       for (j=0; j<N; j++) {
703         ip[j-fshift] = ip[j];
704         ap[j-fshift] = ap[j];
705       }
706     }
707     ai[i] = ai[i-1] + ailen[i-1];
708   }
709   if (m) {
710     fshift += imax[m-1] - ailen[m-1];
711     ai[m]  = ai[m-1] + ailen[m-1];
712   }
713   /* reset ilen and imax for each row */
714   for (i=0; i<m; i++) {
715     ailen[i] = imax[i] = ai[i+1] - ai[i];
716   }
717   a->nz = ai[m];
718   if (fshift && a->nounused == -1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D, %D unneeded", m, A->cmap->n, fshift);
719 
720   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
721   ierr = PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n,fshift,a->nz);CHKERRQ(ierr);
722   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
723   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
724   A->info.mallocs     += a->reallocs;
725   a->reallocs          = 0;
726   A->info.nz_unneeded  = (double)fshift;
727   a->rmax              = rmax;
728 
729   /* check for zero rows. If found a large number of zero rows, use CompressedRow functions */
730   ierr = Mat_CheckCompressedRow(A,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
731   A->same_nonzero = PETSC_TRUE;
732 
733   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
734 
735   a->idiagvalid = PETSC_FALSE;
736 
737 #if defined(PETSC_HAVE_CUDA)
738   a->GPUmatrix.resize(m,A->cmap->n,a->nz);
739   a->GPUmatrix.row_offsets.assign(a->i,a->i+m);
740   a->GPUmatrix.column_indices.assign(a->j,a->j+A->cmap->n);
741   a->GPUmatrix.values.assign(a->a,a->a+a->nz);
742 #endif
743   PetscFunctionReturn(0);
744 }
745 
746 #undef __FUNCT__
747 #define __FUNCT__ "MatRealPart_SeqAIJ"
748 PetscErrorCode MatRealPart_SeqAIJ(Mat A)
749 {
750   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
751   PetscInt       i,nz = a->nz;
752   MatScalar      *aa = a->a;
753 
754   PetscFunctionBegin;
755   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
756   PetscFunctionReturn(0);
757 }
758 
759 #undef __FUNCT__
760 #define __FUNCT__ "MatImaginaryPart_SeqAIJ"
761 PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
762 {
763   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
764   PetscInt       i,nz = a->nz;
765   MatScalar      *aa = a->a;
766 
767   PetscFunctionBegin;
768   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
769   PetscFunctionReturn(0);
770 }
771 
772 #undef __FUNCT__
773 #define __FUNCT__ "MatZeroEntries_SeqAIJ"
774 PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
775 {
776   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
777   PetscErrorCode ierr;
778 
779   PetscFunctionBegin;
780   ierr = PetscMemzero(a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));CHKERRQ(ierr);
781   PetscFunctionReturn(0);
782 }
783 
784 #undef __FUNCT__
785 #define __FUNCT__ "MatDestroy_SeqAIJ"
786 PetscErrorCode MatDestroy_SeqAIJ(Mat A)
787 {
788   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
789   PetscErrorCode ierr;
790 
791   PetscFunctionBegin;
792 #if defined(PETSC_USE_LOG)
793   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
794 #endif
795   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
796   if (a->row) {
797     ierr = ISDestroy(a->row);CHKERRQ(ierr);
798   }
799   if (a->col) {
800     ierr = ISDestroy(a->col);CHKERRQ(ierr);
801   }
802   ierr = PetscFree(a->diag);CHKERRQ(ierr);
803   ierr = PetscFree2(a->imax,a->ilen);CHKERRQ(ierr);
804   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
805   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
806   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);}
807   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
808   if (a->coloring) {ierr = ISColoringDestroy(a->coloring);CHKERRQ(ierr);}
809   ierr = PetscFree(a->xtoy);CHKERRQ(ierr);
810   if (a->XtoY) {ierr = MatDestroy(a->XtoY);CHKERRQ(ierr);}
811   if (a->compressedrow.checked && a->compressedrow.use){ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);}
812 
813   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
814 
815   ierr = PetscFree(a);CHKERRQ(ierr);
816 
817   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
818   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetColumnIndices_C","",PETSC_NULL);CHKERRQ(ierr);
819   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);CHKERRQ(ierr);
820   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);CHKERRQ(ierr);
821   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqsbaij_C","",PETSC_NULL);CHKERRQ(ierr);
822   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqbaij_C","",PETSC_NULL);CHKERRQ(ierr);
823   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqcsrperm_C","",PETSC_NULL);CHKERRQ(ierr);
824   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatIsTranspose_C","",PETSC_NULL);CHKERRQ(ierr);
825   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr);
826   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C","",PETSC_NULL);CHKERRQ(ierr);
827   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatReorderForNonzeroDiagonal_C","",PETSC_NULL);CHKERRQ(ierr);
828   PetscFunctionReturn(0);
829 }
830 
831 #undef __FUNCT__
832 #define __FUNCT__ "MatSetOption_SeqAIJ"
833 PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscTruth flg)
834 {
835   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
836   PetscErrorCode ierr;
837 
838   PetscFunctionBegin;
839   switch (op) {
840     case MAT_ROW_ORIENTED:
841       a->roworiented       = flg;
842       break;
843     case MAT_KEEP_NONZERO_PATTERN:
844       a->keepnonzeropattern    = flg;
845       break;
846     case MAT_NEW_NONZERO_LOCATIONS:
847       a->nonew             = (flg ? 0 : 1);
848       break;
849     case MAT_NEW_NONZERO_LOCATION_ERR:
850       a->nonew             = (flg ? -1 : 0);
851       break;
852     case MAT_NEW_NONZERO_ALLOCATION_ERR:
853       a->nonew             = (flg ? -2 : 0);
854       break;
855     case MAT_UNUSED_NONZERO_LOCATION_ERR:
856       a->nounused          = (flg ? -1 : 0);
857       break;
858     case MAT_IGNORE_ZERO_ENTRIES:
859       a->ignorezeroentries = flg;
860       break;
861     case MAT_USE_COMPRESSEDROW:
862       a->compressedrow.use = flg;
863       break;
864     case MAT_SYMMETRIC:
865     case MAT_STRUCTURALLY_SYMMETRIC:
866     case MAT_HERMITIAN:
867     case MAT_SYMMETRY_ETERNAL:
868     case MAT_NEW_DIAGONALS:
869     case MAT_IGNORE_OFF_PROC_ENTRIES:
870     case MAT_USE_HASH_TABLE:
871       ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
872       break;
873     case MAT_USE_INODES:
874       /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */
875       break;
876     default:
877       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
878   }
879   ierr = MatSetOption_SeqAIJ_Inode(A,op,flg);CHKERRQ(ierr);
880   PetscFunctionReturn(0);
881 }
882 
883 #undef __FUNCT__
884 #define __FUNCT__ "MatGetDiagonal_SeqAIJ"
885 PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
886 {
887   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
888   PetscErrorCode ierr;
889   PetscInt       i,j,n,*ai=a->i,*aj=a->j,nz;
890   PetscScalar    *aa=a->a,*x,zero=0.0;
891 
892   PetscFunctionBegin;
893   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
894   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
895 
896   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU){
897     PetscInt *diag=a->diag;
898     ierr = VecGetArray(v,&x);CHKERRQ(ierr);
899     for (i=0; i<n; i++) x[i] = aa[diag[i]];
900     ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
901     PetscFunctionReturn(0);
902   }
903 
904   ierr = VecSet(v,zero);CHKERRQ(ierr);
905   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
906   for (i=0; i<n; i++) {
907     nz = ai[i+1] - ai[i];
908     if (!nz) x[i] = 0.0;
909     for (j=ai[i]; j<ai[i+1]; j++){
910       if (aj[j] == i) {
911         x[i] = aa[j];
912         break;
913       }
914     }
915   }
916   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
917   PetscFunctionReturn(0);
918 }
919 
920 #include "../src/mat/impls/aij/seq/ftn-kernels/fmult.h"
921 #undef __FUNCT__
922 #define __FUNCT__ "MatMultTransposeAdd_SeqAIJ"
923 PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
924 {
925   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
926   PetscScalar       *x,*y;
927   PetscErrorCode    ierr;
928   PetscInt          m = A->rmap->n;
929 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
930   MatScalar         *v;
931   PetscScalar       alpha;
932   PetscInt          n,i,j,*idx,*ii,*ridx=PETSC_NULL;
933   Mat_CompressedRow cprow = a->compressedrow;
934   PetscTruth        usecprow = cprow.use;
935 #endif
936 
937   PetscFunctionBegin;
938   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
939   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
940   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
941 
942 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
943   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
944 #else
945   if (usecprow){
946     m    = cprow.nrows;
947     ii   = cprow.i;
948     ridx = cprow.rindex;
949   } else {
950     ii = a->i;
951   }
952   for (i=0; i<m; i++) {
953     idx   = a->j + ii[i] ;
954     v     = a->a + ii[i] ;
955     n     = ii[i+1] - ii[i];
956     if (usecprow){
957       alpha = x[ridx[i]];
958     } else {
959       alpha = x[i];
960     }
961     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
962   }
963 #endif
964   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
965   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
966   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
967   PetscFunctionReturn(0);
968 }
969 
970 #undef __FUNCT__
971 #define __FUNCT__ "MatMultTranspose_SeqAIJ"
972 PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
973 {
974   PetscErrorCode ierr;
975 
976   PetscFunctionBegin;
977   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
978   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
979   PetscFunctionReturn(0);
980 }
981 
982 #include "../src/mat/impls/aij/seq/ftn-kernels/fmult.h"
983 #undef __FUNCT__
984 #define __FUNCT__ "MatMult_SeqAIJ"
985 PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
986 {
987   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
988   PetscScalar       *y;
989   const PetscScalar *x;
990   const MatScalar   *aa;
991   PetscErrorCode    ierr;
992   PetscInt          m=A->rmap->n;
993   const PetscInt    *aj,*ii,*ridx=PETSC_NULL;
994   PetscInt          n,i,nonzerorow=0;
995   PetscScalar       sum;
996   PetscTruth        usecprow=a->compressedrow.use;
997 
998 #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
999 #pragma disjoint(*x,*y,*aa)
1000 #endif
1001 
1002   PetscFunctionBegin;
1003   /*#if defined(PETSC_HAVE_CUDA)
1004   ierr = VecCUDACopyToGPU(xx);CHKERRQ(ierr);
1005   cusp::multiply(a->GPUmatrix,xx->GPUarray,yy->GPUarray);
1006   yy->valid_GPU_array = PETSC_CUDA_GPU;
1007 #else*/
1008   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1009   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1010   aj  = a->j;
1011   aa  = a->a;
1012   ii  = a->i;
1013   if (usecprow){ /* use compressed row format */
1014     m    = a->compressedrow.nrows;
1015     ii   = a->compressedrow.i;
1016     ridx = a->compressedrow.rindex;
1017     for (i=0; i<m; i++){
1018       n   = ii[i+1] - ii[i];
1019       aj  = a->j + ii[i];
1020       aa  = a->a + ii[i];
1021       sum = 0.0;
1022       nonzerorow += (n>0);
1023       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1024       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1025       y[*ridx++] = sum;
1026     }
1027   } else { /* do not use compressed row format */
1028 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
1029     fortranmultaij_(&m,x,ii,aj,aa,y);
1030 #else
1031     for (i=0; i<m; i++) {
1032       n   = ii[i+1] - ii[i];
1033       aj  = a->j + ii[i];
1034       aa  = a->a + ii[i];
1035       sum  = 0.0;
1036       nonzerorow += (n>0);
1037       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1038       y[i] = sum;
1039     }
1040 #endif
1041   }
1042   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1043   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1044   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1045   /*#endif*/
1046   PetscFunctionReturn(0);
1047 }
1048 
1049 #include "../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h"
1050 #undef __FUNCT__
1051 #define __FUNCT__ "MatMultAdd_SeqAIJ"
1052 PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1053 {
1054   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
1055   PetscScalar     *x,*y,*z;
1056   const MatScalar *aa;
1057   PetscErrorCode  ierr;
1058   PetscInt        m = A->rmap->n,*aj,*ii;
1059 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
1060   PetscInt        n,i,jrow,j,*ridx=PETSC_NULL;
1061   PetscScalar     sum;
1062   PetscTruth      usecprow=a->compressedrow.use;
1063 #endif
1064 
1065   PetscFunctionBegin;
1066   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
1067   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1068   if (zz != yy) {
1069     ierr = VecGetArray(zz,&z);CHKERRQ(ierr);
1070   } else {
1071     z = y;
1072   }
1073 
1074   aj  = a->j;
1075   aa  = a->a;
1076   ii  = a->i;
1077 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
1078   fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1079 #else
1080   if (usecprow){ /* use compressed row format */
1081     if (zz != yy){
1082       ierr = PetscMemcpy(z,y,m*sizeof(PetscScalar));CHKERRQ(ierr);
1083     }
1084     m    = a->compressedrow.nrows;
1085     ii   = a->compressedrow.i;
1086     ridx = a->compressedrow.rindex;
1087     for (i=0; i<m; i++){
1088       n  = ii[i+1] - ii[i];
1089       aj  = a->j + ii[i];
1090       aa  = a->a + ii[i];
1091       sum = y[*ridx];
1092       for (j=0; j<n; j++) sum += (*aa++)*x[*aj++];
1093       z[*ridx++] = sum;
1094     }
1095   } else { /* do not use compressed row format */
1096     for (i=0; i<m; i++) {
1097       jrow = ii[i];
1098       n    = ii[i+1] - jrow;
1099       sum  = y[i];
1100       for (j=0; j<n; j++) {
1101         sum += aa[jrow]*x[aj[jrow]]; jrow++;
1102       }
1103       z[i] = sum;
1104     }
1105   }
1106 #endif
1107   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1108   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1109   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1110   if (zz != yy) {
1111     ierr = VecRestoreArray(zz,&z);CHKERRQ(ierr);
1112   }
1113   PetscFunctionReturn(0);
1114 }
1115 
1116 /*
1117      Adds diagonal pointers to sparse matrix structure.
1118 */
1119 #undef __FUNCT__
1120 #define __FUNCT__ "MatMarkDiagonal_SeqAIJ"
1121 PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
1122 {
1123   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1124   PetscErrorCode ierr;
1125   PetscInt       i,j,m = A->rmap->n;
1126 
1127   PetscFunctionBegin;
1128   if (!a->diag) {
1129     ierr = PetscMalloc(m*sizeof(PetscInt),&a->diag);CHKERRQ(ierr);
1130     ierr = PetscLogObjectMemory(A, m*sizeof(PetscInt));CHKERRQ(ierr);
1131   }
1132   for (i=0; i<A->rmap->n; i++) {
1133     a->diag[i] = a->i[i+1];
1134     for (j=a->i[i]; j<a->i[i+1]; j++) {
1135       if (a->j[j] == i) {
1136         a->diag[i] = j;
1137         break;
1138       }
1139     }
1140   }
1141   PetscFunctionReturn(0);
1142 }
1143 
1144 /*
1145      Checks for missing diagonals
1146 */
1147 #undef __FUNCT__
1148 #define __FUNCT__ "MatMissingDiagonal_SeqAIJ"
1149 PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscTruth *missing,PetscInt *d)
1150 {
1151   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1152   PetscInt       *diag,*jj = a->j,i;
1153 
1154   PetscFunctionBegin;
1155   *missing = PETSC_FALSE;
1156   if (A->rmap->n > 0 && !jj) {
1157     *missing  = PETSC_TRUE;
1158     if (d) *d = 0;
1159     PetscInfo(A,"Matrix has no entries therefor is missing diagonal");
1160   } else {
1161     diag = a->diag;
1162     for (i=0; i<A->rmap->n; i++) {
1163       if (jj[diag[i]] != i) {
1164 	*missing = PETSC_TRUE;
1165 	if (d) *d = i;
1166 	PetscInfo1(A,"Matrix is missing diagonal number %D",i);
1167       }
1168     }
1169   }
1170   PetscFunctionReturn(0);
1171 }
1172 
1173 EXTERN_C_BEGIN
1174 #undef __FUNCT__
1175 #define __FUNCT__ "MatInvertDiagonal_SeqAIJ"
1176 PetscErrorCode PETSCMAT_DLLEXPORT MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
1177 {
1178   Mat_SeqAIJ     *a = (Mat_SeqAIJ*) A->data;
1179   PetscErrorCode ierr;
1180   PetscInt       i,*diag,m = A->rmap->n;
1181   MatScalar      *v = a->a;
1182   PetscScalar    *idiag,*mdiag;
1183 
1184   PetscFunctionBegin;
1185   if (a->idiagvalid) PetscFunctionReturn(0);
1186   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1187   diag = a->diag;
1188   if (!a->idiag) {
1189     ierr     = PetscMalloc3(m,PetscScalar,&a->idiag,m,PetscScalar,&a->mdiag,m,PetscScalar,&a->ssor_work);CHKERRQ(ierr);
1190     ierr     = PetscLogObjectMemory(A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr);
1191     v        = a->a;
1192   }
1193   mdiag = a->mdiag;
1194   idiag = a->idiag;
1195 
1196   if (omega == 1.0 && !PetscAbsScalar(fshift)) {
1197     for (i=0; i<m; i++) {
1198       mdiag[i] = v[diag[i]];
1199       if (!PetscAbsScalar(mdiag[i])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1200       idiag[i] = 1.0/v[diag[i]];
1201     }
1202     ierr = PetscLogFlops(m);CHKERRQ(ierr);
1203   } else {
1204     for (i=0; i<m; i++) {
1205       mdiag[i] = v[diag[i]];
1206       idiag[i] = omega/(fshift + v[diag[i]]);
1207     }
1208     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
1209   }
1210   a->idiagvalid = PETSC_TRUE;
1211   PetscFunctionReturn(0);
1212 }
1213 EXTERN_C_END
1214 
1215 #include "../src/mat/impls/aij/seq/ftn-kernels/frelax.h"
1216 #undef __FUNCT__
1217 #define __FUNCT__ "MatSOR_SeqAIJ"
1218 PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
1219 {
1220   Mat_SeqAIJ         *a = (Mat_SeqAIJ*)A->data;
1221   PetscScalar        *x,d,sum,*t,scale;
1222   const MatScalar    *v = a->a,*idiag=0,*mdiag;
1223   const PetscScalar  *b, *bs,*xb, *ts;
1224   PetscErrorCode     ierr;
1225   PetscInt           n = A->cmap->n,m = A->rmap->n,i;
1226   const PetscInt     *idx,*diag;
1227 
1228   PetscFunctionBegin;
1229   its = its*lits;
1230 
1231   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
1232   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
1233   a->fshift = fshift;
1234   a->omega  = omega;
1235 
1236   diag = a->diag;
1237   t     = a->ssor_work;
1238   idiag = a->idiag;
1239   mdiag = a->mdiag;
1240 
1241   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
1242   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
1243   CHKMEMQ;
1244   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
1245   if (flag == SOR_APPLY_UPPER) {
1246    /* apply (U + D/omega) to the vector */
1247     bs = b;
1248     for (i=0; i<m; i++) {
1249         d    = fshift + mdiag[i];
1250         n    = a->i[i+1] - diag[i] - 1;
1251         idx  = a->j + diag[i] + 1;
1252         v    = a->a + diag[i] + 1;
1253         sum  = b[i]*d/omega;
1254         PetscSparseDensePlusDot(sum,bs,v,idx,n);
1255         x[i] = sum;
1256     }
1257     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1258     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1259     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
1260     PetscFunctionReturn(0);
1261   }
1262 
1263   if (flag == SOR_APPLY_LOWER) {
1264     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
1265   } else if (flag & SOR_EISENSTAT) {
1266     /* Let  A = L + U + D; where L is lower trianglar,
1267     U is upper triangular, E = D/omega; This routine applies
1268 
1269             (L + E)^{-1} A (U + E)^{-1}
1270 
1271     to a vector efficiently using Eisenstat's trick.
1272     */
1273     scale = (2.0/omega) - 1.0;
1274 
1275     /*  x = (E + U)^{-1} b */
1276     for (i=m-1; i>=0; i--) {
1277       n    = a->i[i+1] - diag[i] - 1;
1278       idx  = a->j + diag[i] + 1;
1279       v    = a->a + diag[i] + 1;
1280       sum  = b[i];
1281       PetscSparseDenseMinusDot(sum,x,v,idx,n);
1282       x[i] = sum*idiag[i];
1283     }
1284 
1285     /*  t = b - (2*E - D)x */
1286     v = a->a;
1287     for (i=0; i<m; i++) { t[i] = b[i] - scale*(v[*diag++])*x[i]; }
1288 
1289     /*  t = (E + L)^{-1}t */
1290     ts = t;
1291     diag = a->diag;
1292     for (i=0; i<m; i++) {
1293       n    = diag[i] - a->i[i];
1294       idx  = a->j + a->i[i];
1295       v    = a->a + a->i[i];
1296       sum  = t[i];
1297       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
1298       t[i] = sum*idiag[i];
1299       /*  x = x + t */
1300       x[i] += t[i];
1301     }
1302 
1303     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
1304     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1305     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1306     PetscFunctionReturn(0);
1307   }
1308   if (flag & SOR_ZERO_INITIAL_GUESS) {
1309     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1310       for (i=0; i<m; i++) {
1311         n    = diag[i] - a->i[i];
1312         idx  = a->j + a->i[i];
1313         v    = a->a + a->i[i];
1314         sum  = b[i];
1315         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1316         t[i] = sum;
1317         x[i] = sum*idiag[i];
1318       }
1319       xb = t;
1320       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
1321     } else xb = b;
1322     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1323       for (i=m-1; i>=0; i--) {
1324         n    = a->i[i+1] - diag[i] - 1;
1325         idx  = a->j + diag[i] + 1;
1326         v    = a->a + diag[i] + 1;
1327         sum  = xb[i];
1328         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1329         if (xb == b) {
1330           x[i] = sum*idiag[i];
1331         } else {
1332           x[i] = (1-omega)*x[i] + sum*idiag[i];
1333         }
1334       }
1335       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
1336     }
1337     its--;
1338   }
1339   while (its--) {
1340     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1341       for (i=0; i<m; i++) {
1342         n    = a->i[i+1] - a->i[i];
1343         idx  = a->j + a->i[i];
1344         v    = a->a + a->i[i];
1345         sum  = b[i];
1346         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1347         x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1348       }
1349       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1350     }
1351     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1352       for (i=m-1; i>=0; i--) {
1353         n    = a->i[i+1] - a->i[i];
1354         idx  = a->j + a->i[i];
1355         v    = a->a + a->i[i];
1356         sum  = b[i];
1357         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1358         x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1359       }
1360       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1361     }
1362   }
1363   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1364   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1365   CHKMEMQ;  PetscFunctionReturn(0);
1366 }
1367 
1368 
1369 #undef __FUNCT__
1370 #define __FUNCT__ "MatGetInfo_SeqAIJ"
1371 PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
1372 {
1373   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1374 
1375   PetscFunctionBegin;
1376   info->block_size     = 1.0;
1377   info->nz_allocated   = (double)a->maxnz;
1378   info->nz_used        = (double)a->nz;
1379   info->nz_unneeded    = (double)(a->maxnz - a->nz);
1380   info->assemblies     = (double)A->num_ass;
1381   info->mallocs        = (double)A->info.mallocs;
1382   info->memory         = ((PetscObject)A)->mem;
1383   if (A->factortype) {
1384     info->fill_ratio_given  = A->info.fill_ratio_given;
1385     info->fill_ratio_needed = A->info.fill_ratio_needed;
1386     info->factor_mallocs    = A->info.factor_mallocs;
1387   } else {
1388     info->fill_ratio_given  = 0;
1389     info->fill_ratio_needed = 0;
1390     info->factor_mallocs    = 0;
1391   }
1392   PetscFunctionReturn(0);
1393 }
1394 
1395 #undef __FUNCT__
1396 #define __FUNCT__ "MatZeroRows_SeqAIJ"
1397 PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag)
1398 {
1399   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1400   PetscInt       i,m = A->rmap->n - 1,d = 0;
1401   PetscErrorCode ierr;
1402   PetscTruth     missing;
1403 
1404   PetscFunctionBegin;
1405   if (a->keepnonzeropattern) {
1406     for (i=0; i<N; i++) {
1407       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1408       ierr = PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));CHKERRQ(ierr);
1409     }
1410     if (diag != 0.0) {
1411       ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
1412       if (missing) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d);
1413       for (i=0; i<N; i++) {
1414         a->a[a->diag[rows[i]]] = diag;
1415       }
1416     }
1417     A->same_nonzero = PETSC_TRUE;
1418   } else {
1419     if (diag != 0.0) {
1420       for (i=0; i<N; i++) {
1421         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1422         if (a->ilen[rows[i]] > 0) {
1423           a->ilen[rows[i]]          = 1;
1424           a->a[a->i[rows[i]]] = diag;
1425           a->j[a->i[rows[i]]] = rows[i];
1426         } else { /* in case row was completely empty */
1427           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
1428         }
1429       }
1430     } else {
1431       for (i=0; i<N; i++) {
1432         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1433         a->ilen[rows[i]] = 0;
1434       }
1435     }
1436     A->same_nonzero = PETSC_FALSE;
1437   }
1438   ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1439   PetscFunctionReturn(0);
1440 }
1441 
1442 #undef __FUNCT__
1443 #define __FUNCT__ "MatGetRow_SeqAIJ"
1444 PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1445 {
1446   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1447   PetscInt   *itmp;
1448 
1449   PetscFunctionBegin;
1450   if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row);
1451 
1452   *nz = a->i[row+1] - a->i[row];
1453   if (v) *v = a->a + a->i[row];
1454   if (idx) {
1455     itmp = a->j + a->i[row];
1456     if (*nz) {
1457       *idx = itmp;
1458     }
1459     else *idx = 0;
1460   }
1461   PetscFunctionReturn(0);
1462 }
1463 
1464 /* remove this function? */
1465 #undef __FUNCT__
1466 #define __FUNCT__ "MatRestoreRow_SeqAIJ"
1467 PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1468 {
1469   PetscFunctionBegin;
1470   PetscFunctionReturn(0);
1471 }
1472 
1473 #undef __FUNCT__
1474 #define __FUNCT__ "MatNorm_SeqAIJ"
1475 PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
1476 {
1477   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1478   MatScalar      *v = a->a;
1479   PetscReal      sum = 0.0;
1480   PetscErrorCode ierr;
1481   PetscInt       i,j;
1482 
1483   PetscFunctionBegin;
1484   if (type == NORM_FROBENIUS) {
1485     for (i=0; i<a->nz; i++) {
1486 #if defined(PETSC_USE_COMPLEX)
1487       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1488 #else
1489       sum += (*v)*(*v); v++;
1490 #endif
1491     }
1492     *nrm = sqrt(sum);
1493   } else if (type == NORM_1) {
1494     PetscReal *tmp;
1495     PetscInt    *jj = a->j;
1496     ierr = PetscMalloc((A->cmap->n+1)*sizeof(PetscReal),&tmp);CHKERRQ(ierr);
1497     ierr = PetscMemzero(tmp,A->cmap->n*sizeof(PetscReal));CHKERRQ(ierr);
1498     *nrm = 0.0;
1499     for (j=0; j<a->nz; j++) {
1500         tmp[*jj++] += PetscAbsScalar(*v);  v++;
1501     }
1502     for (j=0; j<A->cmap->n; j++) {
1503       if (tmp[j] > *nrm) *nrm = tmp[j];
1504     }
1505     ierr = PetscFree(tmp);CHKERRQ(ierr);
1506   } else if (type == NORM_INFINITY) {
1507     *nrm = 0.0;
1508     for (j=0; j<A->rmap->n; j++) {
1509       v = a->a + a->i[j];
1510       sum = 0.0;
1511       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
1512         sum += PetscAbsScalar(*v); v++;
1513       }
1514       if (sum > *nrm) *nrm = sum;
1515     }
1516   } else {
1517     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
1518   }
1519   PetscFunctionReturn(0);
1520 }
1521 
1522 #undef __FUNCT__
1523 #define __FUNCT__ "MatTranspose_SeqAIJ"
1524 PetscErrorCode MatTranspose_SeqAIJ(Mat A,MatReuse reuse,Mat *B)
1525 {
1526   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1527   Mat            C;
1528   PetscErrorCode ierr;
1529   PetscInt       i,*aj = a->j,*ai = a->i,m = A->rmap->n,len,*col;
1530   MatScalar      *array = a->a;
1531 
1532   PetscFunctionBegin;
1533   if (reuse == MAT_REUSE_MATRIX && A == *B && m != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Square matrix only for in-place");
1534 
1535   if (reuse == MAT_INITIAL_MATRIX || *B == A) {
1536     ierr = PetscMalloc((1+A->cmap->n)*sizeof(PetscInt),&col);CHKERRQ(ierr);
1537     ierr = PetscMemzero(col,(1+A->cmap->n)*sizeof(PetscInt));CHKERRQ(ierr);
1538 
1539     for (i=0; i<ai[m]; i++) col[aj[i]] += 1;
1540     ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
1541     ierr = MatSetSizes(C,A->cmap->n,m,A->cmap->n,m);CHKERRQ(ierr);
1542     ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
1543     ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,col);CHKERRQ(ierr);
1544     ierr = PetscFree(col);CHKERRQ(ierr);
1545   } else {
1546     C = *B;
1547   }
1548 
1549   for (i=0; i<m; i++) {
1550     len    = ai[i+1]-ai[i];
1551     ierr   = MatSetValues_SeqAIJ(C,len,aj,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1552     array += len;
1553     aj    += len;
1554   }
1555   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1556   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1557 
1558   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
1559     *B = C;
1560   } else {
1561     ierr = MatHeaderCopy(A,C);CHKERRQ(ierr);
1562   }
1563   PetscFunctionReturn(0);
1564 }
1565 
1566 EXTERN_C_BEGIN
1567 #undef __FUNCT__
1568 #define __FUNCT__ "MatIsTranspose_SeqAIJ"
1569 PetscErrorCode PETSCMAT_DLLEXPORT MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscTruth *f)
1570 {
1571   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1572   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
1573   MatScalar      *va,*vb;
1574   PetscErrorCode ierr;
1575   PetscInt       ma,na,mb,nb, i;
1576 
1577   PetscFunctionBegin;
1578   bij = (Mat_SeqAIJ *) B->data;
1579 
1580   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
1581   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
1582   if (ma!=nb || na!=mb){
1583     *f = PETSC_FALSE;
1584     PetscFunctionReturn(0);
1585   }
1586   aii = aij->i; bii = bij->i;
1587   adx = aij->j; bdx = bij->j;
1588   va  = aij->a; vb = bij->a;
1589   ierr = PetscMalloc(ma*sizeof(PetscInt),&aptr);CHKERRQ(ierr);
1590   ierr = PetscMalloc(mb*sizeof(PetscInt),&bptr);CHKERRQ(ierr);
1591   for (i=0; i<ma; i++) aptr[i] = aii[i];
1592   for (i=0; i<mb; i++) bptr[i] = bii[i];
1593 
1594   *f = PETSC_TRUE;
1595   for (i=0; i<ma; i++) {
1596     while (aptr[i]<aii[i+1]) {
1597       PetscInt         idc,idr;
1598       PetscScalar vc,vr;
1599       /* column/row index/value */
1600       idc = adx[aptr[i]];
1601       idr = bdx[bptr[idc]];
1602       vc  = va[aptr[i]];
1603       vr  = vb[bptr[idc]];
1604       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
1605 	*f = PETSC_FALSE;
1606         goto done;
1607       } else {
1608 	aptr[i]++;
1609         if (B || i!=idc) bptr[idc]++;
1610       }
1611     }
1612   }
1613  done:
1614   ierr = PetscFree(aptr);CHKERRQ(ierr);
1615   if (B) {
1616     ierr = PetscFree(bptr);CHKERRQ(ierr);
1617   }
1618   PetscFunctionReturn(0);
1619 }
1620 EXTERN_C_END
1621 
1622 EXTERN_C_BEGIN
1623 #undef __FUNCT__
1624 #define __FUNCT__ "MatIsHermitianTranspose_SeqAIJ"
1625 PetscErrorCode PETSCMAT_DLLEXPORT MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscTruth *f)
1626 {
1627   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1628   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
1629   MatScalar      *va,*vb;
1630   PetscErrorCode ierr;
1631   PetscInt       ma,na,mb,nb, i;
1632 
1633   PetscFunctionBegin;
1634   bij = (Mat_SeqAIJ *) B->data;
1635 
1636   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
1637   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
1638   if (ma!=nb || na!=mb){
1639     *f = PETSC_FALSE;
1640     PetscFunctionReturn(0);
1641   }
1642   aii = aij->i; bii = bij->i;
1643   adx = aij->j; bdx = bij->j;
1644   va  = aij->a; vb = bij->a;
1645   ierr = PetscMalloc(ma*sizeof(PetscInt),&aptr);CHKERRQ(ierr);
1646   ierr = PetscMalloc(mb*sizeof(PetscInt),&bptr);CHKERRQ(ierr);
1647   for (i=0; i<ma; i++) aptr[i] = aii[i];
1648   for (i=0; i<mb; i++) bptr[i] = bii[i];
1649 
1650   *f = PETSC_TRUE;
1651   for (i=0; i<ma; i++) {
1652     while (aptr[i]<aii[i+1]) {
1653       PetscInt         idc,idr;
1654       PetscScalar vc,vr;
1655       /* column/row index/value */
1656       idc = adx[aptr[i]];
1657       idr = bdx[bptr[idc]];
1658       vc  = va[aptr[i]];
1659       vr  = vb[bptr[idc]];
1660       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
1661 	*f = PETSC_FALSE;
1662         goto done;
1663       } else {
1664 	aptr[i]++;
1665         if (B || i!=idc) bptr[idc]++;
1666       }
1667     }
1668   }
1669  done:
1670   ierr = PetscFree(aptr);CHKERRQ(ierr);
1671   if (B) {
1672     ierr = PetscFree(bptr);CHKERRQ(ierr);
1673   }
1674   PetscFunctionReturn(0);
1675 }
1676 EXTERN_C_END
1677 
1678 #undef __FUNCT__
1679 #define __FUNCT__ "MatIsSymmetric_SeqAIJ"
1680 PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscTruth *f)
1681 {
1682   PetscErrorCode ierr;
1683   PetscFunctionBegin;
1684   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
1685   PetscFunctionReturn(0);
1686 }
1687 
1688 #undef __FUNCT__
1689 #define __FUNCT__ "MatIsHermitian_SeqAIJ"
1690 PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscTruth *f)
1691 {
1692   PetscErrorCode ierr;
1693   PetscFunctionBegin;
1694   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
1695   PetscFunctionReturn(0);
1696 }
1697 
1698 #undef __FUNCT__
1699 #define __FUNCT__ "MatDiagonalScale_SeqAIJ"
1700 PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
1701 {
1702   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1703   PetscScalar    *l,*r,x;
1704   MatScalar      *v;
1705   PetscErrorCode ierr;
1706   PetscInt       i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz,*jj;
1707 
1708   PetscFunctionBegin;
1709   if (ll) {
1710     /* The local size is used so that VecMPI can be passed to this routine
1711        by MatDiagonalScale_MPIAIJ */
1712     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
1713     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
1714     ierr = VecGetArray(ll,&l);CHKERRQ(ierr);
1715     v = a->a;
1716     for (i=0; i<m; i++) {
1717       x = l[i];
1718       M = a->i[i+1] - a->i[i];
1719       for (j=0; j<M; j++) { (*v++) *= x;}
1720     }
1721     ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr);
1722     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
1723   }
1724   if (rr) {
1725     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
1726     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
1727     ierr = VecGetArray(rr,&r);CHKERRQ(ierr);
1728     v = a->a; jj = a->j;
1729     for (i=0; i<nz; i++) {
1730       (*v++) *= r[*jj++];
1731     }
1732     ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr);
1733     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
1734   }
1735   PetscFunctionReturn(0);
1736 }
1737 
1738 #undef __FUNCT__
1739 #define __FUNCT__ "MatGetSubMatrix_SeqAIJ"
1740 PetscErrorCode MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
1741 {
1742   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*c;
1743   PetscErrorCode ierr;
1744   PetscInt       *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
1745   PetscInt       row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
1746   const PetscInt *irow,*icol;
1747   PetscInt       nrows,ncols;
1748   PetscInt       *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
1749   MatScalar      *a_new,*mat_a;
1750   Mat            C;
1751   PetscTruth     stride,sorted;
1752 
1753   PetscFunctionBegin;
1754   ierr = ISSorted(isrow,&sorted);CHKERRQ(ierr);
1755   if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted");
1756   ierr = ISSorted(iscol,&sorted);CHKERRQ(ierr);
1757   if (!sorted) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted");
1758 
1759   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
1760   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
1761   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
1762 
1763   ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
1764   ierr = ISStride(iscol,&stride);CHKERRQ(ierr);
1765   if (stride && step == 1) {
1766     /* special case of contiguous rows */
1767     ierr = PetscMalloc2(nrows,PetscInt,&lens,nrows,PetscInt,&starts);CHKERRQ(ierr);
1768     /* loop over new rows determining lens and starting points */
1769     for (i=0; i<nrows; i++) {
1770       kstart  = ai[irow[i]];
1771       kend    = kstart + ailen[irow[i]];
1772       for (k=kstart; k<kend; k++) {
1773         if (aj[k] >= first) {
1774           starts[i] = k;
1775           break;
1776 	}
1777       }
1778       sum = 0;
1779       while (k < kend) {
1780         if (aj[k++] >= first+ncols) break;
1781         sum++;
1782       }
1783       lens[i] = sum;
1784     }
1785     /* create submatrix */
1786     if (scall == MAT_REUSE_MATRIX) {
1787       PetscInt n_cols,n_rows;
1788       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
1789       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
1790       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
1791       C = *B;
1792     } else {
1793       ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
1794       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
1795       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
1796       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
1797     }
1798     c = (Mat_SeqAIJ*)C->data;
1799 
1800     /* loop over rows inserting into submatrix */
1801     a_new    = c->a;
1802     j_new    = c->j;
1803     i_new    = c->i;
1804 
1805     for (i=0; i<nrows; i++) {
1806       ii    = starts[i];
1807       lensi = lens[i];
1808       for (k=0; k<lensi; k++) {
1809         *j_new++ = aj[ii+k] - first;
1810       }
1811       ierr = PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));CHKERRQ(ierr);
1812       a_new      += lensi;
1813       i_new[i+1]  = i_new[i] + lensi;
1814       c->ilen[i]  = lensi;
1815     }
1816     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
1817   } else {
1818     ierr  = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
1819     ierr  = PetscMalloc(oldcols*sizeof(PetscInt),&smap);CHKERRQ(ierr);
1820     ierr  = PetscMemzero(smap,oldcols*sizeof(PetscInt));CHKERRQ(ierr);
1821     ierr  = PetscMalloc((1+nrows)*sizeof(PetscInt),&lens);CHKERRQ(ierr);
1822     for (i=0; i<ncols; i++) smap[icol[i]] = i+1;
1823     /* determine lens of each row */
1824     for (i=0; i<nrows; i++) {
1825       kstart  = ai[irow[i]];
1826       kend    = kstart + a->ilen[irow[i]];
1827       lens[i] = 0;
1828       for (k=kstart; k<kend; k++) {
1829         if (smap[aj[k]]) {
1830           lens[i]++;
1831         }
1832       }
1833     }
1834     /* Create and fill new matrix */
1835     if (scall == MAT_REUSE_MATRIX) {
1836       PetscTruth equal;
1837 
1838       c = (Mat_SeqAIJ *)((*B)->data);
1839       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
1840       ierr = PetscMemcmp(c->ilen,lens,(*B)->rmap->n*sizeof(PetscInt),&equal);CHKERRQ(ierr);
1841       if (!equal) {
1842         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
1843       }
1844       ierr = PetscMemzero(c->ilen,(*B)->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
1845       C = *B;
1846     } else {
1847       ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
1848       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
1849       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
1850       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
1851     }
1852     c = (Mat_SeqAIJ *)(C->data);
1853     for (i=0; i<nrows; i++) {
1854       row    = irow[i];
1855       kstart = ai[row];
1856       kend   = kstart + a->ilen[row];
1857       mat_i  = c->i[i];
1858       mat_j  = c->j + mat_i;
1859       mat_a  = c->a + mat_i;
1860       mat_ilen = c->ilen + i;
1861       for (k=kstart; k<kend; k++) {
1862         if ((tcol=smap[a->j[k]])) {
1863           *mat_j++ = tcol - 1;
1864           *mat_a++ = a->a[k];
1865           (*mat_ilen)++;
1866 
1867         }
1868       }
1869     }
1870     /* Free work space */
1871     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
1872     ierr = PetscFree(smap);CHKERRQ(ierr);
1873     ierr = PetscFree(lens);CHKERRQ(ierr);
1874   }
1875   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1876   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1877 
1878   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
1879   *B = C;
1880   PetscFunctionReturn(0);
1881 }
1882 
1883 #undef __FUNCT__
1884 #define __FUNCT__ "MatILUFactor_SeqAIJ"
1885 PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
1886 {
1887   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
1888   PetscErrorCode ierr;
1889   Mat            outA;
1890   PetscTruth     row_identity,col_identity;
1891 
1892   PetscFunctionBegin;
1893   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
1894 
1895   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
1896   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
1897 
1898   outA              = inA;
1899   outA->factortype  = MAT_FACTOR_LU;
1900   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
1901   if (a->row) { ierr = ISDestroy(a->row);CHKERRQ(ierr);}
1902   a->row = row;
1903   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
1904   if (a->col) { ierr = ISDestroy(a->col);CHKERRQ(ierr);}
1905   a->col = col;
1906 
1907   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
1908   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} /* need to remove old one */
1909   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
1910   ierr = PetscLogObjectParent(inA,a->icol);CHKERRQ(ierr);
1911 
1912   if (!a->solve_work) { /* this matrix may have been factored before */
1913      ierr = PetscMalloc((inA->rmap->n+1)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr);
1914      ierr = PetscLogObjectMemory(inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
1915   }
1916 
1917   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
1918   if (row_identity && col_identity) {
1919     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
1920   } else {
1921     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
1922   }
1923   PetscFunctionReturn(0);
1924 }
1925 
1926 #undef __FUNCT__
1927 #define __FUNCT__ "MatScale_SeqAIJ"
1928 PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
1929 {
1930   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
1931   PetscScalar    oalpha = alpha;
1932   PetscErrorCode ierr;
1933   PetscBLASInt   one = 1,bnz = PetscBLASIntCast(a->nz);
1934 
1935   PetscFunctionBegin;
1936   BLASscal_(&bnz,&oalpha,a->a,&one);
1937   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
1938   PetscFunctionReturn(0);
1939 }
1940 
1941 #undef __FUNCT__
1942 #define __FUNCT__ "MatGetSubMatrices_SeqAIJ"
1943 PetscErrorCode MatGetSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
1944 {
1945   PetscErrorCode ierr;
1946   PetscInt       i;
1947 
1948   PetscFunctionBegin;
1949   if (scall == MAT_INITIAL_MATRIX) {
1950     ierr = PetscMalloc((n+1)*sizeof(Mat),B);CHKERRQ(ierr);
1951   }
1952 
1953   for (i=0; i<n; i++) {
1954     ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
1955   }
1956   PetscFunctionReturn(0);
1957 }
1958 
1959 #undef __FUNCT__
1960 #define __FUNCT__ "MatIncreaseOverlap_SeqAIJ"
1961 PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
1962 {
1963   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1964   PetscErrorCode ierr;
1965   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
1966   const PetscInt *idx;
1967   PetscInt       start,end,*ai,*aj;
1968   PetscBT        table;
1969 
1970   PetscFunctionBegin;
1971   m     = A->rmap->n;
1972   ai    = a->i;
1973   aj    = a->j;
1974 
1975   if (ov < 0)  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
1976 
1977   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&nidx);CHKERRQ(ierr);
1978   ierr = PetscBTCreate(m,table);CHKERRQ(ierr);
1979 
1980   for (i=0; i<is_max; i++) {
1981     /* Initialize the two local arrays */
1982     isz  = 0;
1983     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
1984 
1985     /* Extract the indices, assume there can be duplicate entries */
1986     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
1987     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
1988 
1989     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
1990     for (j=0; j<n ; ++j){
1991       if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];}
1992     }
1993     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
1994     ierr = ISDestroy(is[i]);CHKERRQ(ierr);
1995 
1996     k = 0;
1997     for (j=0; j<ov; j++){ /* for each overlap */
1998       n = isz;
1999       for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
2000         row   = nidx[k];
2001         start = ai[row];
2002         end   = ai[row+1];
2003         for (l = start; l<end ; l++){
2004           val = aj[l] ;
2005           if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;}
2006         }
2007       }
2008     }
2009     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,(is+i));CHKERRQ(ierr);
2010   }
2011   ierr = PetscBTDestroy(table);CHKERRQ(ierr);
2012   ierr = PetscFree(nidx);CHKERRQ(ierr);
2013   PetscFunctionReturn(0);
2014 }
2015 
2016 /* -------------------------------------------------------------- */
2017 #undef __FUNCT__
2018 #define __FUNCT__ "MatPermute_SeqAIJ"
2019 PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
2020 {
2021   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2022   PetscErrorCode ierr;
2023   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
2024   const PetscInt *row,*col;
2025   PetscInt       *cnew,j,*lens;
2026   IS             icolp,irowp;
2027   PetscInt       *cwork = PETSC_NULL;
2028   PetscScalar    *vwork = PETSC_NULL;
2029 
2030   PetscFunctionBegin;
2031   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
2032   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
2033   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
2034   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
2035 
2036   /* determine lengths of permuted rows */
2037   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&lens);CHKERRQ(ierr);
2038   for (i=0; i<m; i++) {
2039     lens[row[i]] = a->i[i+1] - a->i[i];
2040   }
2041   ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr);
2042   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
2043   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2044   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
2045   ierr = PetscFree(lens);CHKERRQ(ierr);
2046 
2047   ierr = PetscMalloc(n*sizeof(PetscInt),&cnew);CHKERRQ(ierr);
2048   for (i=0; i<m; i++) {
2049     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
2050     for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];}
2051     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
2052     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
2053   }
2054   ierr = PetscFree(cnew);CHKERRQ(ierr);
2055   (*B)->assembled     = PETSC_FALSE;
2056   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2057   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2058   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
2059   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
2060   ierr = ISDestroy(irowp);CHKERRQ(ierr);
2061   ierr = ISDestroy(icolp);CHKERRQ(ierr);
2062   PetscFunctionReturn(0);
2063 }
2064 
2065 #undef __FUNCT__
2066 #define __FUNCT__ "MatCopy_SeqAIJ"
2067 PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
2068 {
2069   PetscErrorCode ierr;
2070 
2071   PetscFunctionBegin;
2072   /* If the two matrices have the same copy implementation, use fast copy. */
2073   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
2074     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2075     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
2076 
2077     if (a->i[A->rmap->n] != b->i[B->rmap->n]) {
2078       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
2079     }
2080     ierr = PetscMemcpy(b->a,a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));CHKERRQ(ierr);
2081   } else {
2082     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
2083   }
2084   PetscFunctionReturn(0);
2085 }
2086 
2087 #undef __FUNCT__
2088 #define __FUNCT__ "MatSetUpPreallocation_SeqAIJ"
2089 PetscErrorCode MatSetUpPreallocation_SeqAIJ(Mat A)
2090 {
2091   PetscErrorCode ierr;
2092 
2093   PetscFunctionBegin;
2094   ierr =  MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);CHKERRQ(ierr);
2095   PetscFunctionReturn(0);
2096 }
2097 
2098 #undef __FUNCT__
2099 #define __FUNCT__ "MatGetArray_SeqAIJ"
2100 PetscErrorCode MatGetArray_SeqAIJ(Mat A,PetscScalar *array[])
2101 {
2102   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2103   PetscFunctionBegin;
2104   *array = a->a;
2105   PetscFunctionReturn(0);
2106 }
2107 
2108 #undef __FUNCT__
2109 #define __FUNCT__ "MatRestoreArray_SeqAIJ"
2110 PetscErrorCode MatRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
2111 {
2112   PetscFunctionBegin;
2113   PetscFunctionReturn(0);
2114 }
2115 
2116 #undef __FUNCT__
2117 #define __FUNCT__ "MatFDColoringApply_SeqAIJ"
2118 PetscErrorCode MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
2119 {
2120   PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f;
2121   PetscErrorCode ierr;
2122   PetscInt       k,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
2123   PetscScalar    dx,*y,*xx,*w3_array;
2124   PetscScalar    *vscale_array;
2125   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin;
2126   Vec            w1,w2,w3;
2127   void           *fctx = coloring->fctx;
2128   PetscTruth     flg = PETSC_FALSE;
2129 
2130   PetscFunctionBegin;
2131   if (!coloring->w1) {
2132     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
2133     ierr = PetscLogObjectParent(coloring,coloring->w1);CHKERRQ(ierr);
2134     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
2135     ierr = PetscLogObjectParent(coloring,coloring->w2);CHKERRQ(ierr);
2136     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
2137     ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr);
2138   }
2139   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
2140 
2141   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
2142   ierr = PetscOptionsGetTruth(((PetscObject)coloring)->prefix,"-mat_fd_coloring_dont_rezero",&flg,PETSC_NULL);CHKERRQ(ierr);
2143   if (flg) {
2144     ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr);
2145   } else {
2146     PetscTruth assembled;
2147     ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
2148     if (assembled) {
2149       ierr = MatZeroEntries(J);CHKERRQ(ierr);
2150     }
2151   }
2152 
2153   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
2154   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
2155 
2156   /*
2157        This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets
2158      coloring->F for the coarser grids from the finest
2159   */
2160   if (coloring->F) {
2161     ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr);
2162     ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr);
2163     if (m1 != m2) {
2164       coloring->F = 0;
2165     }
2166   }
2167 
2168   if (coloring->F) {
2169     w1          = coloring->F;
2170     coloring->F = 0;
2171   } else {
2172     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2173     ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr);
2174     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2175   }
2176 
2177   /*
2178       Compute all the scale factors and share with other processors
2179   */
2180   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
2181   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
2182   for (k=0; k<coloring->ncolors; k++) {
2183     /*
2184        Loop over each column associated with color adding the
2185        perturbation to the vector w3.
2186     */
2187     for (l=0; l<coloring->ncolumns[k]; l++) {
2188       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
2189       dx  = xx[col];
2190       if (dx == 0.0) dx = 1.0;
2191 #if !defined(PETSC_USE_COMPLEX)
2192       if (dx < umin && dx >= 0.0)      dx = umin;
2193       else if (dx < 0.0 && dx > -umin) dx = -umin;
2194 #else
2195       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
2196       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2197 #endif
2198       dx                *= epsilon;
2199       vscale_array[col] = 1.0/dx;
2200     }
2201   }
2202   vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
2203   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2204   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2205 
2206   /*  ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
2207       ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/
2208 
2209   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
2210   else                        vscaleforrow = coloring->columnsforrow;
2211 
2212   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
2213   /*
2214       Loop over each color
2215   */
2216   for (k=0; k<coloring->ncolors; k++) {
2217     coloring->currentcolor = k;
2218     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
2219     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
2220     /*
2221        Loop over each column associated with color adding the
2222        perturbation to the vector w3.
2223     */
2224     for (l=0; l<coloring->ncolumns[k]; l++) {
2225       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
2226       dx  = xx[col];
2227       if (dx == 0.0) dx = 1.0;
2228 #if !defined(PETSC_USE_COMPLEX)
2229       if (dx < umin && dx >= 0.0)      dx = umin;
2230       else if (dx < 0.0 && dx > -umin) dx = -umin;
2231 #else
2232       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
2233       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2234 #endif
2235       dx            *= epsilon;
2236       if (!PetscAbsScalar(dx)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Computed 0 differencing parameter");
2237       w3_array[col] += dx;
2238     }
2239     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
2240 
2241     /*
2242        Evaluate function at x1 + dx (here dx is a vector of perturbations)
2243     */
2244 
2245     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2246     ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
2247     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2248     ierr = VecAXPY(w2,-1.0,w1);CHKERRQ(ierr);
2249 
2250     /*
2251        Loop over rows of vector, putting results into Jacobian matrix
2252     */
2253     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
2254     for (l=0; l<coloring->nrows[k]; l++) {
2255       row    = coloring->rows[k][l];
2256       col    = coloring->columnsforrow[k][l];
2257       y[row] *= vscale_array[vscaleforrow[k][l]];
2258       srow   = row + start;
2259       ierr   = MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
2260     }
2261     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
2262   }
2263   coloring->currentcolor = k;
2264   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
2265   xx = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
2266   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2267   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2268   PetscFunctionReturn(0);
2269 }
2270 
2271 #undef __FUNCT__
2272 #define __FUNCT__ "MatAXPY_SeqAIJ"
2273 PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
2274 {
2275   PetscErrorCode ierr;
2276   PetscInt       i;
2277   Mat_SeqAIJ     *x  = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data;
2278   PetscBLASInt   one=1,bnz = PetscBLASIntCast(x->nz);
2279 
2280   PetscFunctionBegin;
2281   if (str == SAME_NONZERO_PATTERN) {
2282     PetscScalar alpha = a;
2283     BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
2284   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2285     if (y->xtoy && y->XtoY != X) {
2286       ierr = PetscFree(y->xtoy);CHKERRQ(ierr);
2287       ierr = MatDestroy(y->XtoY);CHKERRQ(ierr);
2288     }
2289     if (!y->xtoy) { /* get xtoy */
2290       ierr = MatAXPYGetxtoy_Private(X->rmap->n,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr);
2291       y->XtoY = X;
2292       ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
2293     }
2294     for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += a*(x->a[i]);
2295     ierr = PetscInfo3(Y,"ratio of nnz(X)/nnz(Y): %d/%d = %G\n",x->nz,y->nz,(PetscReal)(x->nz)/y->nz);CHKERRQ(ierr);
2296   } else {
2297     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
2298   }
2299   PetscFunctionReturn(0);
2300 }
2301 
2302 #undef __FUNCT__
2303 #define __FUNCT__ "MatSetBlockSize_SeqAIJ"
2304 PetscErrorCode MatSetBlockSize_SeqAIJ(Mat A,PetscInt bs)
2305 {
2306   PetscErrorCode ierr;
2307 
2308   PetscFunctionBegin;
2309   ierr = PetscLayoutSetBlockSize(A->rmap,bs);CHKERRQ(ierr);
2310   ierr = PetscLayoutSetBlockSize(A->cmap,bs);CHKERRQ(ierr);
2311   PetscFunctionReturn(0);
2312 }
2313 
2314 #undef __FUNCT__
2315 #define __FUNCT__ "MatConjugate_SeqAIJ"
2316 PetscErrorCode PETSCMAT_DLLEXPORT MatConjugate_SeqAIJ(Mat mat)
2317 {
2318 #if defined(PETSC_USE_COMPLEX)
2319   Mat_SeqAIJ  *aij = (Mat_SeqAIJ *)mat->data;
2320   PetscInt    i,nz;
2321   PetscScalar *a;
2322 
2323   PetscFunctionBegin;
2324   nz = aij->nz;
2325   a  = aij->a;
2326   for (i=0; i<nz; i++) {
2327     a[i] = PetscConj(a[i]);
2328   }
2329 #else
2330   PetscFunctionBegin;
2331 #endif
2332   PetscFunctionReturn(0);
2333 }
2334 
2335 #undef __FUNCT__
2336 #define __FUNCT__ "MatGetRowMaxAbs_SeqAIJ"
2337 PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2338 {
2339   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2340   PetscErrorCode ierr;
2341   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2342   PetscReal      atmp;
2343   PetscScalar    *x;
2344   MatScalar      *aa;
2345 
2346   PetscFunctionBegin;
2347   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2348   aa   = a->a;
2349   ai   = a->i;
2350   aj   = a->j;
2351 
2352   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2353   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2354   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
2355   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2356   for (i=0; i<m; i++) {
2357     ncols = ai[1] - ai[0]; ai++;
2358     x[i] = 0.0;
2359     for (j=0; j<ncols; j++){
2360       atmp = PetscAbsScalar(*aa);
2361       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
2362       aa++; aj++;
2363     }
2364   }
2365   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2366   PetscFunctionReturn(0);
2367 }
2368 
2369 #undef __FUNCT__
2370 #define __FUNCT__ "MatGetRowMax_SeqAIJ"
2371 PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2372 {
2373   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2374   PetscErrorCode ierr;
2375   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2376   PetscScalar    *x;
2377   MatScalar      *aa;
2378 
2379   PetscFunctionBegin;
2380   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2381   aa   = a->a;
2382   ai   = a->i;
2383   aj   = a->j;
2384 
2385   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2386   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2387   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
2388   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2389   for (i=0; i<m; i++) {
2390     ncols = ai[1] - ai[0]; ai++;
2391     if (ncols == A->cmap->n) { /* row is dense */
2392       x[i] = *aa; if (idx) idx[i] = 0;
2393     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
2394       x[i] = 0.0;
2395       if (idx) {
2396         idx[i] = 0; /* in case ncols is zero */
2397         for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */
2398           if (aj[j] > j) {
2399             idx[i] = j;
2400             break;
2401           }
2402         }
2403       }
2404     }
2405     for (j=0; j<ncols; j++){
2406       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
2407       aa++; aj++;
2408     }
2409   }
2410   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2411   PetscFunctionReturn(0);
2412 }
2413 
2414 #undef __FUNCT__
2415 #define __FUNCT__ "MatGetRowMinAbs_SeqAIJ"
2416 PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2417 {
2418   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2419   PetscErrorCode ierr;
2420   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2421   PetscReal      atmp;
2422   PetscScalar    *x;
2423   MatScalar      *aa;
2424 
2425   PetscFunctionBegin;
2426   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2427   aa   = a->a;
2428   ai   = a->i;
2429   aj   = a->j;
2430 
2431   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2432   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2433   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
2434   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2435   for (i=0; i<m; i++) {
2436     ncols = ai[1] - ai[0]; ai++;
2437     if (ncols) {
2438       /* Get first nonzero */
2439       for(j = 0; j < ncols; j++) {
2440         atmp = PetscAbsScalar(aa[j]);
2441         if (atmp > 1.0e-12) {x[i] = atmp; if (idx) idx[i] = aj[j]; break;}
2442       }
2443       if (j == ncols) {x[i] = *aa; if (idx) idx[i] = *aj;}
2444     } else {
2445       x[i] = 0.0; if (idx) idx[i] = 0;
2446     }
2447     for(j = 0; j < ncols; j++) {
2448       atmp = PetscAbsScalar(*aa);
2449       if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
2450       aa++; aj++;
2451     }
2452   }
2453   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2454   PetscFunctionReturn(0);
2455 }
2456 
2457 #undef __FUNCT__
2458 #define __FUNCT__ "MatGetRowMin_SeqAIJ"
2459 PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2460 {
2461   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2462   PetscErrorCode ierr;
2463   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2464   PetscScalar    *x;
2465   MatScalar      *aa;
2466 
2467   PetscFunctionBegin;
2468   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2469   aa   = a->a;
2470   ai   = a->i;
2471   aj   = a->j;
2472 
2473   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2474   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2475   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
2476   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2477   for (i=0; i<m; i++) {
2478     ncols = ai[1] - ai[0]; ai++;
2479     if (ncols == A->cmap->n) { /* row is dense */
2480       x[i] = *aa; if (idx) idx[i] = 0;
2481     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
2482       x[i] = 0.0;
2483       if (idx) {   /* find first implicit 0.0 in the row */
2484         idx[i] = 0; /* in case ncols is zero */
2485         for (j=0;j<ncols;j++) {
2486           if (aj[j] > j) {
2487             idx[i] = j;
2488             break;
2489           }
2490         }
2491       }
2492     }
2493     for (j=0; j<ncols; j++){
2494       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
2495       aa++; aj++;
2496     }
2497   }
2498   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2499   PetscFunctionReturn(0);
2500 }
2501 extern PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringApply_AIJ(Mat,MatFDColoring,Vec,MatStructure*,void*);
2502 /* -------------------------------------------------------------------*/
2503 static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
2504        MatGetRow_SeqAIJ,
2505        MatRestoreRow_SeqAIJ,
2506        MatMult_SeqAIJ,
2507 /* 4*/ MatMultAdd_SeqAIJ,
2508        MatMultTranspose_SeqAIJ,
2509        MatMultTransposeAdd_SeqAIJ,
2510        0,
2511        0,
2512        0,
2513 /*10*/ 0,
2514        MatLUFactor_SeqAIJ,
2515        0,
2516        MatSOR_SeqAIJ,
2517        MatTranspose_SeqAIJ,
2518 /*15*/ MatGetInfo_SeqAIJ,
2519        MatEqual_SeqAIJ,
2520        MatGetDiagonal_SeqAIJ,
2521        MatDiagonalScale_SeqAIJ,
2522        MatNorm_SeqAIJ,
2523 /*20*/ 0,
2524        MatAssemblyEnd_SeqAIJ,
2525        MatSetOption_SeqAIJ,
2526        MatZeroEntries_SeqAIJ,
2527 /*24*/ MatZeroRows_SeqAIJ,
2528        0,
2529        0,
2530        0,
2531        0,
2532 /*29*/ MatSetUpPreallocation_SeqAIJ,
2533        0,
2534        0,
2535        MatGetArray_SeqAIJ,
2536        MatRestoreArray_SeqAIJ,
2537 /*34*/ MatDuplicate_SeqAIJ,
2538        0,
2539        0,
2540        MatILUFactor_SeqAIJ,
2541        0,
2542 /*39*/ MatAXPY_SeqAIJ,
2543        MatGetSubMatrices_SeqAIJ,
2544        MatIncreaseOverlap_SeqAIJ,
2545        MatGetValues_SeqAIJ,
2546        MatCopy_SeqAIJ,
2547 /*44*/ MatGetRowMax_SeqAIJ,
2548        MatScale_SeqAIJ,
2549        0,
2550        MatDiagonalSet_SeqAIJ,
2551        0,
2552 /*49*/ MatSetBlockSize_SeqAIJ,
2553        MatGetRowIJ_SeqAIJ,
2554        MatRestoreRowIJ_SeqAIJ,
2555        MatGetColumnIJ_SeqAIJ,
2556        MatRestoreColumnIJ_SeqAIJ,
2557 /*54*/ MatFDColoringCreate_SeqAIJ,
2558        0,
2559        0,
2560        MatPermute_SeqAIJ,
2561        0,
2562 /*59*/ 0,
2563        MatDestroy_SeqAIJ,
2564        MatView_SeqAIJ,
2565        0,
2566        0,
2567 /*64*/ 0,
2568        0,
2569        0,
2570        0,
2571        0,
2572 /*69*/ MatGetRowMaxAbs_SeqAIJ,
2573        MatGetRowMinAbs_SeqAIJ,
2574        0,
2575        MatSetColoring_SeqAIJ,
2576 #if defined(PETSC_HAVE_ADIC)
2577        MatSetValuesAdic_SeqAIJ,
2578 #else
2579        0,
2580 #endif
2581 /*74*/ MatSetValuesAdifor_SeqAIJ,
2582        MatFDColoringApply_AIJ,
2583        0,
2584        0,
2585        0,
2586 /*79*/ 0,
2587        0,
2588        0,
2589        0,
2590        MatLoad_SeqAIJ,
2591 /*84*/ MatIsSymmetric_SeqAIJ,
2592        MatIsHermitian_SeqAIJ,
2593        0,
2594        0,
2595        0,
2596 /*89*/ MatMatMult_SeqAIJ_SeqAIJ,
2597        MatMatMultSymbolic_SeqAIJ_SeqAIJ,
2598        MatMatMultNumeric_SeqAIJ_SeqAIJ,
2599        MatPtAP_Basic,
2600        MatPtAPSymbolic_SeqAIJ,
2601 /*94*/ MatPtAPNumeric_SeqAIJ,
2602        MatMatMultTranspose_SeqAIJ_SeqAIJ,
2603        MatMatMultTransposeSymbolic_SeqAIJ_SeqAIJ,
2604        MatMatMultTransposeNumeric_SeqAIJ_SeqAIJ,
2605        MatPtAPSymbolic_SeqAIJ_SeqAIJ,
2606 /*99*/ MatPtAPNumeric_SeqAIJ_SeqAIJ,
2607        0,
2608        0,
2609        MatConjugate_SeqAIJ,
2610        0,
2611 /*104*/MatSetValuesRow_SeqAIJ,
2612        MatRealPart_SeqAIJ,
2613        MatImaginaryPart_SeqAIJ,
2614        0,
2615        0,
2616 /*109*/0,
2617        0,
2618        MatGetRowMin_SeqAIJ,
2619        0,
2620        MatMissingDiagonal_SeqAIJ,
2621 /*114*/0,
2622        0,
2623        0,
2624        0,
2625        0,
2626 /*119*/0,
2627        0,
2628        0,
2629        0,
2630        MatLoadnew_SeqAIJ
2631 };
2632 
2633 EXTERN_C_BEGIN
2634 #undef __FUNCT__
2635 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ"
2636 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
2637 {
2638   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2639   PetscInt   i,nz,n;
2640 
2641   PetscFunctionBegin;
2642 
2643   nz = aij->maxnz;
2644   n  = mat->rmap->n;
2645   for (i=0; i<nz; i++) {
2646     aij->j[i] = indices[i];
2647   }
2648   aij->nz = nz;
2649   for (i=0; i<n; i++) {
2650     aij->ilen[i] = aij->imax[i];
2651   }
2652 
2653   PetscFunctionReturn(0);
2654 }
2655 EXTERN_C_END
2656 
2657 #undef __FUNCT__
2658 #define __FUNCT__ "MatSeqAIJSetColumnIndices"
2659 /*@
2660     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
2661        in the matrix.
2662 
2663   Input Parameters:
2664 +  mat - the SeqAIJ matrix
2665 -  indices - the column indices
2666 
2667   Level: advanced
2668 
2669   Notes:
2670     This can be called if you have precomputed the nonzero structure of the
2671   matrix and want to provide it to the matrix object to improve the performance
2672   of the MatSetValues() operation.
2673 
2674     You MUST have set the correct numbers of nonzeros per row in the call to
2675   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
2676 
2677     MUST be called before any calls to MatSetValues();
2678 
2679     The indices should start with zero, not one.
2680 
2681 @*/
2682 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
2683 {
2684   PetscErrorCode ierr,(*f)(Mat,PetscInt *);
2685 
2686   PetscFunctionBegin;
2687   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2688   PetscValidPointer(indices,2);
2689   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr);
2690   if (f) {
2691     ierr = (*f)(mat,indices);CHKERRQ(ierr);
2692   } else {
2693     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Wrong type of matrix to set column indices");
2694   }
2695   PetscFunctionReturn(0);
2696 }
2697 
2698 /* ----------------------------------------------------------------------------------------*/
2699 
2700 EXTERN_C_BEGIN
2701 #undef __FUNCT__
2702 #define __FUNCT__ "MatStoreValues_SeqAIJ"
2703 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues_SeqAIJ(Mat mat)
2704 {
2705   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
2706   PetscErrorCode ierr;
2707   size_t         nz = aij->i[mat->rmap->n];
2708 
2709   PetscFunctionBegin;
2710   if (aij->nonew != 1) {
2711     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
2712   }
2713 
2714   /* allocate space for values if not already there */
2715   if (!aij->saved_values) {
2716     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
2717     ierr = PetscLogObjectMemory(mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
2718   }
2719 
2720   /* copy values over */
2721   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2722   PetscFunctionReturn(0);
2723 }
2724 EXTERN_C_END
2725 
2726 #undef __FUNCT__
2727 #define __FUNCT__ "MatStoreValues"
2728 /*@
2729     MatStoreValues - Stashes a copy of the matrix values; this allows, for
2730        example, reuse of the linear part of a Jacobian, while recomputing the
2731        nonlinear portion.
2732 
2733    Collect on Mat
2734 
2735   Input Parameters:
2736 .  mat - the matrix (currently only AIJ matrices support this option)
2737 
2738   Level: advanced
2739 
2740   Common Usage, with SNESSolve():
2741 $    Create Jacobian matrix
2742 $    Set linear terms into matrix
2743 $    Apply boundary conditions to matrix, at this time matrix must have
2744 $      final nonzero structure (i.e. setting the nonlinear terms and applying
2745 $      boundary conditions again will not change the nonzero structure
2746 $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
2747 $    ierr = MatStoreValues(mat);
2748 $    Call SNESSetJacobian() with matrix
2749 $    In your Jacobian routine
2750 $      ierr = MatRetrieveValues(mat);
2751 $      Set nonlinear terms in matrix
2752 
2753   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
2754 $    // build linear portion of Jacobian
2755 $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
2756 $    ierr = MatStoreValues(mat);
2757 $    loop over nonlinear iterations
2758 $       ierr = MatRetrieveValues(mat);
2759 $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
2760 $       // call MatAssemblyBegin/End() on matrix
2761 $       Solve linear system with Jacobian
2762 $    endloop
2763 
2764   Notes:
2765     Matrix must already be assemblied before calling this routine
2766     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
2767     calling this routine.
2768 
2769     When this is called multiple times it overwrites the previous set of stored values
2770     and does not allocated additional space.
2771 
2772 .seealso: MatRetrieveValues()
2773 
2774 @*/
2775 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues(Mat mat)
2776 {
2777   PetscErrorCode ierr,(*f)(Mat);
2778 
2779   PetscFunctionBegin;
2780   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2781   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2782   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2783 
2784   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatStoreValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2785   if (f) {
2786     ierr = (*f)(mat);CHKERRQ(ierr);
2787   } else {
2788     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Wrong type of matrix to store values");
2789   }
2790   PetscFunctionReturn(0);
2791 }
2792 
2793 EXTERN_C_BEGIN
2794 #undef __FUNCT__
2795 #define __FUNCT__ "MatRetrieveValues_SeqAIJ"
2796 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues_SeqAIJ(Mat mat)
2797 {
2798   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
2799   PetscErrorCode ierr;
2800   PetscInt       nz = aij->i[mat->rmap->n];
2801 
2802   PetscFunctionBegin;
2803   if (aij->nonew != 1) {
2804     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
2805   }
2806   if (!aij->saved_values) {
2807     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
2808   }
2809   /* copy values over */
2810   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2811   PetscFunctionReturn(0);
2812 }
2813 EXTERN_C_END
2814 
2815 #undef __FUNCT__
2816 #define __FUNCT__ "MatRetrieveValues"
2817 /*@
2818     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
2819        example, reuse of the linear part of a Jacobian, while recomputing the
2820        nonlinear portion.
2821 
2822    Collect on Mat
2823 
2824   Input Parameters:
2825 .  mat - the matrix (currently on AIJ matrices support this option)
2826 
2827   Level: advanced
2828 
2829 .seealso: MatStoreValues()
2830 
2831 @*/
2832 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues(Mat mat)
2833 {
2834   PetscErrorCode ierr,(*f)(Mat);
2835 
2836   PetscFunctionBegin;
2837   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2838   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2839   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2840 
2841   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatRetrieveValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2842   if (f) {
2843     ierr = (*f)(mat);CHKERRQ(ierr);
2844   } else {
2845     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Wrong type of matrix to retrieve values");
2846   }
2847   PetscFunctionReturn(0);
2848 }
2849 
2850 
2851 /* --------------------------------------------------------------------------------*/
2852 #undef __FUNCT__
2853 #define __FUNCT__ "MatCreateSeqAIJ"
2854 /*@C
2855    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
2856    (the default parallel PETSc format).  For good matrix assembly performance
2857    the user should preallocate the matrix storage by setting the parameter nz
2858    (or the array nnz).  By setting these parameters accurately, performance
2859    during matrix assembly can be increased by more than a factor of 50.
2860 
2861    Collective on MPI_Comm
2862 
2863    Input Parameters:
2864 +  comm - MPI communicator, set to PETSC_COMM_SELF
2865 .  m - number of rows
2866 .  n - number of columns
2867 .  nz - number of nonzeros per row (same for all rows)
2868 -  nnz - array containing the number of nonzeros in the various rows
2869          (possibly different for each row) or PETSC_NULL
2870 
2871    Output Parameter:
2872 .  A - the matrix
2873 
2874    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
2875    MatXXXXSetPreallocation() paradgm instead of this routine directly.
2876    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
2877 
2878    Notes:
2879    If nnz is given then nz is ignored
2880 
2881    The AIJ format (also called the Yale sparse matrix format or
2882    compressed row storage), is fully compatible with standard Fortran 77
2883    storage.  That is, the stored row and column indices can begin at
2884    either one (as in Fortran) or zero.  See the users' manual for details.
2885 
2886    Specify the preallocated storage with either nz or nnz (not both).
2887    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2888    allocation.  For large problems you MUST preallocate memory or you
2889    will get TERRIBLE performance, see the users' manual chapter on matrices.
2890 
2891    By default, this format uses inodes (identical nodes) when possible, to
2892    improve numerical efficiency of matrix-vector products and solves. We
2893    search for consecutive rows with the same nonzero structure, thereby
2894    reusing matrix information to achieve increased efficiency.
2895 
2896    Options Database Keys:
2897 +  -mat_no_inode  - Do not use inodes
2898 .  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
2899 -  -mat_aij_oneindex - Internally use indexing starting at 1
2900         rather than 0.  Note that when calling MatSetValues(),
2901         the user still MUST index entries starting at 0!
2902 
2903    Level: intermediate
2904 
2905 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
2906 
2907 @*/
2908 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
2909 {
2910   PetscErrorCode ierr;
2911 
2912   PetscFunctionBegin;
2913   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2914   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
2915   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
2916   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,(PetscInt*)nnz);CHKERRQ(ierr);
2917   PetscFunctionReturn(0);
2918 }
2919 
2920 #undef __FUNCT__
2921 #define __FUNCT__ "MatSeqAIJSetPreallocation"
2922 /*@C
2923    MatSeqAIJSetPreallocation - For good matrix assembly performance
2924    the user should preallocate the matrix storage by setting the parameter nz
2925    (or the array nnz).  By setting these parameters accurately, performance
2926    during matrix assembly can be increased by more than a factor of 50.
2927 
2928    Collective on MPI_Comm
2929 
2930    Input Parameters:
2931 +  B - The matrix-free
2932 .  nz - number of nonzeros per row (same for all rows)
2933 -  nnz - array containing the number of nonzeros in the various rows
2934          (possibly different for each row) or PETSC_NULL
2935 
2936    Notes:
2937      If nnz is given then nz is ignored
2938 
2939     The AIJ format (also called the Yale sparse matrix format or
2940    compressed row storage), is fully compatible with standard Fortran 77
2941    storage.  That is, the stored row and column indices can begin at
2942    either one (as in Fortran) or zero.  See the users' manual for details.
2943 
2944    Specify the preallocated storage with either nz or nnz (not both).
2945    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2946    allocation.  For large problems you MUST preallocate memory or you
2947    will get TERRIBLE performance, see the users' manual chapter on matrices.
2948 
2949    You can call MatGetInfo() to get information on how effective the preallocation was;
2950    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
2951    You can also run with the option -info and look for messages with the string
2952    malloc in them to see if additional memory allocation was needed.
2953 
2954    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
2955    entries or columns indices
2956 
2957    By default, this format uses inodes (identical nodes) when possible, to
2958    improve numerical efficiency of matrix-vector products and solves. We
2959    search for consecutive rows with the same nonzero structure, thereby
2960    reusing matrix information to achieve increased efficiency.
2961 
2962    Options Database Keys:
2963 +  -mat_no_inode  - Do not use inodes
2964 .  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
2965 -  -mat_aij_oneindex - Internally use indexing starting at 1
2966         rather than 0.  Note that when calling MatSetValues(),
2967         the user still MUST index entries starting at 0!
2968 
2969    Level: intermediate
2970 
2971 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo()
2972 
2973 @*/
2974 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
2975 {
2976   PetscErrorCode ierr,(*f)(Mat,PetscInt,const PetscInt[]);
2977 
2978   PetscFunctionBegin;
2979   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
2980   if (f) {
2981     ierr = (*f)(B,nz,nnz);CHKERRQ(ierr);
2982   }
2983   PetscFunctionReturn(0);
2984 }
2985 
2986 EXTERN_C_BEGIN
2987 #undef __FUNCT__
2988 #define __FUNCT__ "MatSeqAIJSetPreallocation_SeqAIJ"
2989 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,PetscInt *nnz)
2990 {
2991   Mat_SeqAIJ     *b;
2992   PetscTruth     skipallocation = PETSC_FALSE;
2993   PetscErrorCode ierr;
2994   PetscInt       i;
2995 
2996   PetscFunctionBegin;
2997 
2998   if (nz == MAT_SKIP_ALLOCATION) {
2999     skipallocation = PETSC_TRUE;
3000     nz             = 0;
3001   }
3002 
3003   ierr = PetscLayoutSetBlockSize(B->rmap,1);CHKERRQ(ierr);
3004   ierr = PetscLayoutSetBlockSize(B->cmap,1);CHKERRQ(ierr);
3005   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
3006   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
3007 
3008   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
3009   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
3010   if (nnz) {
3011     for (i=0; i<B->rmap->n; i++) {
3012       if (nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
3013       if (nnz[i] > B->cmap->n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %d value %d rowlength %d",i,nnz[i],B->cmap->n);
3014     }
3015   }
3016 
3017   B->preallocated = PETSC_TRUE;
3018   b = (Mat_SeqAIJ*)B->data;
3019 
3020   if (!skipallocation) {
3021     if (!b->imax) {
3022       ierr = PetscMalloc2(B->rmap->n,PetscInt,&b->imax,B->rmap->n,PetscInt,&b->ilen);CHKERRQ(ierr);
3023       ierr = PetscLogObjectMemory(B,2*B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3024     }
3025     if (!nnz) {
3026       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
3027       else if (nz <= 0)        nz = 1;
3028       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
3029       nz = nz*B->rmap->n;
3030     } else {
3031       nz = 0;
3032       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
3033     }
3034     /* b->ilen will count nonzeros in each row so far. */
3035     for (i=0; i<B->rmap->n; i++) { b->ilen[i] = 0; }
3036 
3037     /* allocate the matrix space */
3038     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
3039     ierr = PetscMalloc3(nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->n+1,PetscInt,&b->i);CHKERRQ(ierr);
3040     ierr = PetscLogObjectMemory(B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
3041     b->i[0] = 0;
3042     for (i=1; i<B->rmap->n+1; i++) {
3043       b->i[i] = b->i[i-1] + b->imax[i-1];
3044     }
3045     b->singlemalloc = PETSC_TRUE;
3046     b->free_a       = PETSC_TRUE;
3047     b->free_ij      = PETSC_TRUE;
3048   } else {
3049     b->free_a       = PETSC_FALSE;
3050     b->free_ij      = PETSC_FALSE;
3051   }
3052 
3053   b->nz                = 0;
3054   b->maxnz             = nz;
3055   B->info.nz_unneeded  = (double)b->maxnz;
3056   PetscFunctionReturn(0);
3057 }
3058 EXTERN_C_END
3059 
3060 #undef  __FUNCT__
3061 #define __FUNCT__  "MatSeqAIJSetPreallocationCSR"
3062 /*@
3063    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
3064 
3065    Input Parameters:
3066 +  B - the matrix
3067 .  i - the indices into j for the start of each row (starts with zero)
3068 .  j - the column indices for each row (starts with zero) these must be sorted for each row
3069 -  v - optional values in the matrix
3070 
3071    Level: developer
3072 
3073    The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
3074 
3075 .keywords: matrix, aij, compressed row, sparse, sequential
3076 
3077 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), SeqAIJ
3078 @*/
3079 PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
3080 {
3081   PetscErrorCode (*f)(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]);
3082   PetscErrorCode ierr;
3083 
3084   PetscFunctionBegin;
3085   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
3086   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",(void (**)(void))&f);CHKERRQ(ierr);
3087   if (f) {
3088     ierr = (*f)(B,i,j,v);CHKERRQ(ierr);
3089   }
3090   PetscFunctionReturn(0);
3091 }
3092 
3093 EXTERN_C_BEGIN
3094 #undef  __FUNCT__
3095 #define __FUNCT__  "MatSeqAIJSetPreallocationCSR_SeqAIJ"
3096 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
3097 {
3098   PetscInt       i;
3099   PetscInt       m,n;
3100   PetscInt       nz;
3101   PetscInt       *nnz, nz_max = 0;
3102   PetscScalar    *values;
3103   PetscErrorCode ierr;
3104 
3105   PetscFunctionBegin;
3106   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
3107 
3108   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
3109   ierr = PetscMalloc((m+1) * sizeof(PetscInt), &nnz);CHKERRQ(ierr);
3110   for(i = 0; i < m; i++) {
3111     nz     = Ii[i+1]- Ii[i];
3112     nz_max = PetscMax(nz_max, nz);
3113     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
3114     nnz[i] = nz;
3115   }
3116   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
3117   ierr = PetscFree(nnz);CHKERRQ(ierr);
3118 
3119   if (v) {
3120     values = (PetscScalar*) v;
3121   } else {
3122     ierr = PetscMalloc(nz_max*sizeof(PetscScalar), &values);CHKERRQ(ierr);
3123     ierr = PetscMemzero(values, nz_max*sizeof(PetscScalar));CHKERRQ(ierr);
3124   }
3125 
3126   for(i = 0; i < m; i++) {
3127     nz  = Ii[i+1] - Ii[i];
3128     ierr = MatSetValues_SeqAIJ(B, 1, &i, nz, J+Ii[i], values + (v ? Ii[i] : 0), INSERT_VALUES);CHKERRQ(ierr);
3129   }
3130 
3131   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3132   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3133 
3134   if (!v) {
3135     ierr = PetscFree(values);CHKERRQ(ierr);
3136   }
3137   PetscFunctionReturn(0);
3138 }
3139 EXTERN_C_END
3140 
3141 #include "../src/mat/impls/dense/seq/dense.h"
3142 #include "private/petscaxpy.h"
3143 
3144 #undef __FUNCT__
3145 #define __FUNCT__ "MatMatMultNumeric_SeqDense_SeqAIJ"
3146 /*
3147     Computes (B'*A')' since computing B*A directly is untenable
3148 
3149                n                       p                          p
3150         (              )       (              )         (                  )
3151       m (      A       )  *  n (       B      )   =   m (         C        )
3152         (              )       (              )         (                  )
3153 
3154 */
3155 PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
3156 {
3157   PetscErrorCode     ierr;
3158   Mat_SeqDense       *sub_a = (Mat_SeqDense*)A->data;
3159   Mat_SeqAIJ         *sub_b = (Mat_SeqAIJ*)B->data;
3160   Mat_SeqDense       *sub_c = (Mat_SeqDense*)C->data;
3161   PetscInt           i,n,m,q,p;
3162   const PetscInt     *ii,*idx;
3163   const PetscScalar  *b,*a,*a_q;
3164   PetscScalar        *c,*c_q;
3165 
3166   PetscFunctionBegin;
3167   m = A->rmap->n;
3168   n = A->cmap->n;
3169   p = B->cmap->n;
3170   a = sub_a->v;
3171   b = sub_b->a;
3172   c = sub_c->v;
3173   ierr = PetscMemzero(c,m*p*sizeof(PetscScalar));CHKERRQ(ierr);
3174 
3175   ii  = sub_b->i;
3176   idx = sub_b->j;
3177   for (i=0; i<n; i++) {
3178     q = ii[i+1] - ii[i];
3179     while (q-->0) {
3180       c_q = c + m*(*idx);
3181       a_q = a + m*i;
3182       PetscAXPY(c_q,*b,a_q,m);
3183       idx++;
3184       b++;
3185     }
3186   }
3187   PetscFunctionReturn(0);
3188 }
3189 
3190 #undef __FUNCT__
3191 #define __FUNCT__ "MatMatMultSymbolic_SeqDense_SeqAIJ"
3192 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C)
3193 {
3194   PetscErrorCode ierr;
3195   PetscInt       m=A->rmap->n,n=B->cmap->n;
3196   Mat            Cmat;
3197 
3198   PetscFunctionBegin;
3199   if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->rmap->n %d\n",A->cmap->n,B->rmap->n);
3200   ierr = MatCreate(((PetscObject)A)->comm,&Cmat);CHKERRQ(ierr);
3201   ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr);
3202   ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr);
3203   ierr = MatSeqDenseSetPreallocation(Cmat,PETSC_NULL);CHKERRQ(ierr);
3204   Cmat->assembled = PETSC_TRUE;
3205   *C = Cmat;
3206   PetscFunctionReturn(0);
3207 }
3208 
3209 /* ----------------------------------------------------------------*/
3210 #undef __FUNCT__
3211 #define __FUNCT__ "MatMatMult_SeqDense_SeqAIJ"
3212 PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
3213 {
3214   PetscErrorCode ierr;
3215 
3216   PetscFunctionBegin;
3217   if (scall == MAT_INITIAL_MATRIX){
3218     ierr = MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);CHKERRQ(ierr);
3219   }
3220   ierr = MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);CHKERRQ(ierr);
3221   PetscFunctionReturn(0);
3222 }
3223 
3224 
3225 /*MC
3226    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
3227    based on compressed sparse row format.
3228 
3229    Options Database Keys:
3230 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
3231 
3232   Level: beginner
3233 
3234 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
3235 M*/
3236 
3237 EXTERN_C_BEGIN
3238 #if defined(PETSC_HAVE_PASTIX)
3239 extern PetscErrorCode MatGetFactor_seqaij_pastix(Mat,MatFactorType,Mat*);
3240 #endif
3241 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SCALAR_SINGLE) && !defined(PETSC_USE_SCALAR_MAT_SINGLE)
3242 extern PetscErrorCode MatGetFactor_seqaij_essl(Mat,MatFactorType,Mat *);
3243 #endif
3244 extern PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_SeqCRL(Mat,MatType,MatReuse,Mat*);
3245 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_petsc(Mat,MatFactorType,Mat*);
3246 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_bas(Mat,MatFactorType,Mat*);
3247 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactorAvailable_seqaij_petsc(Mat,MatFactorType,PetscTruth *);
3248 #if defined(PETSC_HAVE_MUMPS)
3249 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_aij_mumps(Mat,MatFactorType,Mat*);
3250 #endif
3251 #if defined(PETSC_HAVE_SUPERLU)
3252 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_superlu(Mat,MatFactorType,Mat*);
3253 #endif
3254 #if defined(PETSC_HAVE_SUPERLU_DIST)
3255 extern PetscErrorCode MatGetFactor_seqaij_superlu_dist(Mat,MatFactorType,Mat*);
3256 #endif
3257 #if defined(PETSC_HAVE_SPOOLES)
3258 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_spooles(Mat,MatFactorType,Mat*);
3259 #endif
3260 #if defined(PETSC_HAVE_UMFPACK)
3261 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_umfpack(Mat,MatFactorType,Mat*);
3262 #endif
3263 #if defined(PETSC_HAVE_CHOLMOD)
3264 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_cholmod(Mat,MatFactorType,Mat*);
3265 #endif
3266 #if defined(PETSC_HAVE_LUSOL)
3267 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_lusol(Mat,MatFactorType,Mat*);
3268 #endif
3269 #if defined(PETSC_HAVE_MATLAB_ENGINE)
3270 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_matlab(Mat,MatFactorType,Mat*);
3271 extern PetscErrorCode PETSCMAT_DLLEXPORT MatlabEnginePut_SeqAIJ(PetscObject,void*);
3272 extern PetscErrorCode PETSCMAT_DLLEXPORT MatlabEngineGet_SeqAIJ(PetscObject,void*);
3273 #endif
3274 EXTERN_C_END
3275 
3276 
3277 EXTERN_C_BEGIN
3278 #undef __FUNCT__
3279 #define __FUNCT__ "MatCreate_SeqAIJ"
3280 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqAIJ(Mat B)
3281 {
3282   Mat_SeqAIJ     *b;
3283   PetscErrorCode ierr;
3284   PetscMPIInt    size;
3285 
3286   PetscFunctionBegin;
3287   ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr);
3288   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
3289 
3290   ierr = PetscNewLog(B,Mat_SeqAIJ,&b);CHKERRQ(ierr);
3291   B->data             = (void*)b;
3292   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
3293   B->mapping          = 0;
3294   b->row              = 0;
3295   b->col              = 0;
3296   b->icol             = 0;
3297   b->reallocs         = 0;
3298   b->ignorezeroentries = PETSC_FALSE;
3299   b->roworiented       = PETSC_TRUE;
3300   b->nonew             = 0;
3301   b->diag              = 0;
3302   b->solve_work        = 0;
3303   B->spptr             = 0;
3304   b->saved_values      = 0;
3305   b->idiag             = 0;
3306   b->mdiag             = 0;
3307   b->ssor_work         = 0;
3308   b->omega             = 1.0;
3309   b->fshift            = 0.0;
3310   b->idiagvalid        = PETSC_FALSE;
3311   b->keepnonzeropattern    = PETSC_FALSE;
3312   b->xtoy              = 0;
3313   b->XtoY              = 0;
3314   b->compressedrow.use     = PETSC_FALSE;
3315   b->compressedrow.nrows   = B->rmap->n;
3316   b->compressedrow.i       = PETSC_NULL;
3317   b->compressedrow.rindex  = PETSC_NULL;
3318   b->compressedrow.checked = PETSC_FALSE;
3319   B->same_nonzero          = PETSC_FALSE;
3320 
3321   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
3322 #if defined(PETSC_HAVE_MATLAB_ENGINE)
3323   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_matlab_C",
3324 					   "MatGetFactor_seqaij_matlab",
3325 					   MatGetFactor_seqaij_matlab);CHKERRQ(ierr);
3326   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEnginePut_C","MatlabEnginePut_SeqAIJ",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
3327   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEngineGet_C","MatlabEngineGet_SeqAIJ",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
3328 #endif
3329 #if defined(PETSC_HAVE_PASTIX)
3330   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_pastix_C",
3331 					   "MatGetFactor_seqaij_pastix",
3332 					   MatGetFactor_seqaij_pastix);CHKERRQ(ierr);
3333 #endif
3334 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SCALAR_SINGLE) && !defined(PETSC_USE_SCALAR_MAT_SINGLE)
3335   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_essl_C",
3336                                      "MatGetFactor_seqaij_essl",
3337                                      MatGetFactor_seqaij_essl);CHKERRQ(ierr);
3338 #endif
3339 #if defined(PETSC_HAVE_SUPERLU)
3340   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_C",
3341                                      "MatGetFactor_seqaij_superlu",
3342                                      MatGetFactor_seqaij_superlu);CHKERRQ(ierr);
3343 #endif
3344 #if defined(PETSC_HAVE_SUPERLU_DIST)
3345   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_dist_C",
3346                                      "MatGetFactor_seqaij_superlu_dist",
3347                                      MatGetFactor_seqaij_superlu_dist);CHKERRQ(ierr);
3348 #endif
3349 #if defined(PETSC_HAVE_SPOOLES)
3350   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_spooles_C",
3351                                      "MatGetFactor_seqaij_spooles",
3352                                      MatGetFactor_seqaij_spooles);CHKERRQ(ierr);
3353 #endif
3354 #if defined(PETSC_HAVE_MUMPS)
3355   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_mumps_C",
3356                                      "MatGetFactor_aij_mumps",
3357                                      MatGetFactor_aij_mumps);CHKERRQ(ierr);
3358 #endif
3359 #if defined(PETSC_HAVE_UMFPACK)
3360     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_umfpack_C",
3361                                      "MatGetFactor_seqaij_umfpack",
3362                                      MatGetFactor_seqaij_umfpack);CHKERRQ(ierr);
3363 #endif
3364 #if defined(PETSC_HAVE_CHOLMOD)
3365     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_cholmod_C",
3366                                      "MatGetFactor_seqaij_cholmod",
3367                                      MatGetFactor_seqaij_cholmod);CHKERRQ(ierr);
3368 #endif
3369 #if defined(PETSC_HAVE_LUSOL)
3370     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_lusol_C",
3371                                      "MatGetFactor_seqaij_lusol",
3372                                      MatGetFactor_seqaij_lusol);CHKERRQ(ierr);
3373 #endif
3374   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_petsc_C",
3375                                      "MatGetFactor_seqaij_petsc",
3376                                      MatGetFactor_seqaij_petsc);CHKERRQ(ierr);
3377   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_petsc_C",
3378                                      "MatGetFactorAvailable_seqaij_petsc",
3379                                      MatGetFactorAvailable_seqaij_petsc);CHKERRQ(ierr);
3380   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_bas_C",
3381                                      "MatGetFactor_seqaij_bas",
3382                                      MatGetFactor_seqaij_bas);
3383   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C",
3384                                      "MatSeqAIJSetColumnIndices_SeqAIJ",
3385                                      MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
3386   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
3387                                      "MatStoreValues_SeqAIJ",
3388                                      MatStoreValues_SeqAIJ);CHKERRQ(ierr);
3389   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
3390                                      "MatRetrieveValues_SeqAIJ",
3391                                      MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
3392   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",
3393                                      "MatConvert_SeqAIJ_SeqSBAIJ",
3394                                       MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
3395   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C",
3396                                      "MatConvert_SeqAIJ_SeqBAIJ",
3397                                       MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
3398   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqcsrperm_C",
3399                                      "MatConvert_SeqAIJ_SeqCSRPERM",
3400                                       MatConvert_SeqAIJ_SeqCSRPERM);CHKERRQ(ierr);
3401   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqcrl_C",
3402                                      "MatConvert_SeqAIJ_SeqCRL",
3403                                       MatConvert_SeqAIJ_SeqCRL);CHKERRQ(ierr);
3404   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C",
3405                                      "MatIsTranspose_SeqAIJ",
3406                                       MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
3407   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsHermitianTranspose_C",
3408                                      "MatIsHermitianTranspose_SeqAIJ",
3409                                       MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
3410   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C",
3411                                      "MatSeqAIJSetPreallocation_SeqAIJ",
3412                                       MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
3413   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",
3414 				     "MatSeqAIJSetPreallocationCSR_SeqAIJ",
3415 				      MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
3416   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C",
3417                                      "MatReorderForNonzeroDiagonal_SeqAIJ",
3418                                       MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
3419   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMult_seqdense_seqaij_C",
3420                                      "MatMatMult_SeqDense_SeqAIJ",
3421                                       MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr);
3422   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C",
3423                                      "MatMatMultSymbolic_SeqDense_SeqAIJ",
3424                                       MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr);
3425   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C",
3426                                      "MatMatMultNumeric_SeqDense_SeqAIJ",
3427                                       MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr);
3428   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
3429   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
3430   PetscFunctionReturn(0);
3431 }
3432 EXTERN_C_END
3433 
3434 #undef __FUNCT__
3435 #define __FUNCT__ "MatDuplicateNoCreate_SeqAIJ"
3436 /*
3437     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
3438 */
3439 PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscTruth mallocmatspace)
3440 {
3441   Mat_SeqAIJ     *c,*a = (Mat_SeqAIJ*)A->data;
3442   PetscErrorCode ierr;
3443   PetscInt       i,m = A->rmap->n;
3444 
3445   PetscFunctionBegin;
3446   c = (Mat_SeqAIJ*)C->data;
3447 
3448   C->factortype     = A->factortype;
3449   c->row            = 0;
3450   c->col            = 0;
3451   c->icol           = 0;
3452   c->reallocs       = 0;
3453 
3454   C->assembled      = PETSC_TRUE;
3455 
3456   ierr = PetscLayoutSetBlockSize(C->rmap,1);CHKERRQ(ierr);
3457   ierr = PetscLayoutSetBlockSize(C->cmap,1);CHKERRQ(ierr);
3458   ierr = PetscLayoutSetUp(C->rmap);CHKERRQ(ierr);
3459   ierr = PetscLayoutSetUp(C->cmap);CHKERRQ(ierr);
3460 
3461   ierr = PetscMalloc2(m,PetscInt,&c->imax,m,PetscInt,&c->ilen);CHKERRQ(ierr);
3462   ierr = PetscLogObjectMemory(C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
3463   for (i=0; i<m; i++) {
3464     c->imax[i] = a->imax[i];
3465     c->ilen[i] = a->ilen[i];
3466   }
3467 
3468   /* allocate the matrix space */
3469   if (mallocmatspace){
3470     ierr = PetscMalloc3(a->i[m],PetscScalar,&c->a,a->i[m],PetscInt,&c->j,m+1,PetscInt,&c->i);CHKERRQ(ierr);
3471     ierr = PetscLogObjectMemory(C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
3472     c->singlemalloc = PETSC_TRUE;
3473     ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
3474     if (m > 0) {
3475       ierr = PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));CHKERRQ(ierr);
3476       if (cpvalues == MAT_COPY_VALUES) {
3477         ierr = PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
3478       } else {
3479         ierr = PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
3480       }
3481     }
3482   }
3483 
3484   c->ignorezeroentries = a->ignorezeroentries;
3485   c->roworiented       = a->roworiented;
3486   c->nonew             = a->nonew;
3487   if (a->diag) {
3488     ierr = PetscMalloc((m+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr);
3489     ierr = PetscLogObjectMemory(C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
3490     for (i=0; i<m; i++) {
3491       c->diag[i] = a->diag[i];
3492     }
3493   } else c->diag           = 0;
3494   c->solve_work            = 0;
3495   c->saved_values          = 0;
3496   c->idiag                 = 0;
3497   c->ssor_work             = 0;
3498   c->keepnonzeropattern    = a->keepnonzeropattern;
3499   c->free_a                = PETSC_TRUE;
3500   c->free_ij               = PETSC_TRUE;
3501   c->xtoy                  = 0;
3502   c->XtoY                  = 0;
3503 
3504   c->nz                 = a->nz;
3505   c->maxnz              = a->nz; /* Since we allocate exactly the right amount */
3506   C->preallocated       = PETSC_TRUE;
3507 
3508   c->compressedrow.use     = a->compressedrow.use;
3509   c->compressedrow.nrows   = a->compressedrow.nrows;
3510   c->compressedrow.checked = a->compressedrow.checked;
3511   if (a->compressedrow.checked && a->compressedrow.use){
3512     i = a->compressedrow.nrows;
3513     ierr = PetscMalloc2(i+1,PetscInt,&c->compressedrow.i,i,PetscInt,&c->compressedrow.rindex);CHKERRQ(ierr);
3514     ierr = PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));CHKERRQ(ierr);
3515     ierr = PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));CHKERRQ(ierr);
3516   } else {
3517     c->compressedrow.use    = PETSC_FALSE;
3518     c->compressedrow.i      = PETSC_NULL;
3519     c->compressedrow.rindex = PETSC_NULL;
3520   }
3521   C->same_nonzero = A->same_nonzero;
3522   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
3523 
3524   ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
3525   PetscFunctionReturn(0);
3526 }
3527 
3528 #undef __FUNCT__
3529 #define __FUNCT__ "MatDuplicate_SeqAIJ"
3530 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
3531 {
3532   PetscErrorCode ierr;
3533 
3534   PetscFunctionBegin;
3535   ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr);
3536   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
3537   ierr = MatSetType(*B,MATSEQAIJ);CHKERRQ(ierr);
3538   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
3539   PetscFunctionReturn(0);
3540 }
3541 
3542 #undef __FUNCT__
3543 #define __FUNCT__ "MatLoad_SeqAIJ"
3544 PetscErrorCode MatLoad_SeqAIJ(PetscViewer viewer, const MatType type,Mat *A)
3545 {
3546   Mat_SeqAIJ     *a;
3547   Mat            B;
3548   PetscErrorCode ierr;
3549   PetscInt       i,sum,nz,header[4],*rowlengths = 0,M,N;
3550   int            fd;
3551   PetscMPIInt    size;
3552   MPI_Comm       comm;
3553 
3554   PetscFunctionBegin;
3555   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
3556   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
3557   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor");
3558   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
3559   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
3560   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
3561   M = header[1]; N = header[2]; nz = header[3];
3562 
3563   if (nz < 0) {
3564     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
3565   }
3566 
3567   /* read in row lengths */
3568   ierr = PetscMalloc(M*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
3569   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
3570 
3571   /* check if sum of rowlengths is same as nz */
3572   for (i=0,sum=0; i< M; i++) sum +=rowlengths[i];
3573   if (sum != nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Inconsistant matrix data in file. no-nonzeros = %d, sum-row-lengths = %d\n",nz,sum);
3574 
3575   /* create our matrix */
3576   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
3577   ierr = MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
3578   ierr = MatSetType(B,type);CHKERRQ(ierr);
3579   ierr = MatSeqAIJSetPreallocation_SeqAIJ(B,0,rowlengths);CHKERRQ(ierr);
3580   a = (Mat_SeqAIJ*)B->data;
3581 
3582   ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr);
3583 
3584   /* read in nonzero values */
3585   ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr);
3586 
3587   /* set matrix "i" values */
3588   a->i[0] = 0;
3589   for (i=1; i<= M; i++) {
3590     a->i[i]      = a->i[i-1] + rowlengths[i-1];
3591     a->ilen[i-1] = rowlengths[i-1];
3592   }
3593   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
3594 
3595   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3596   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3597   *A = B;
3598   PetscFunctionReturn(0);
3599 }
3600 
3601 #undef __FUNCT__
3602 #define __FUNCT__ "MatLoadnew_SeqAIJ"
3603 PetscErrorCode MatLoadnew_SeqAIJ(PetscViewer viewer,Mat newMat)
3604 {
3605   Mat_SeqAIJ     *a;
3606   PetscErrorCode ierr;
3607   PetscInt       i,sum,nz,header[4],*rowlengths = 0,M,N,rows,cols;
3608   int            fd;
3609   PetscMPIInt    size;
3610   MPI_Comm       comm;
3611 
3612   PetscFunctionBegin;
3613   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
3614   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
3615   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor");
3616   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
3617   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
3618   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
3619   M = header[1]; N = header[2]; nz = header[3];
3620 
3621   if (nz < 0) {
3622     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
3623   }
3624 
3625   /* read in row lengths */
3626   ierr = PetscMalloc(M*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
3627   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
3628 
3629   /* check if sum of rowlengths is same as nz */
3630   for (i=0,sum=0; i< M; i++) sum +=rowlengths[i];
3631   if (sum != nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Inconsistant matrix data in file. no-nonzeros = %d, sum-row-lengths = %d\n",nz,sum);
3632 
3633   /* set global size if not set already*/
3634   if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) {
3635     ierr = MatSetSizes(newMat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
3636   } else {
3637     /* if sizes and type are already set, check if the vector global sizes are correct */
3638     ierr = MatGetSize(newMat,&rows,&cols);CHKERRQ(ierr);
3639     if (M != rows ||  N != cols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%d, %d) than the input matrix (%d, %d)",M,N,rows,cols);
3640   }
3641   ierr = MatSeqAIJSetPreallocation_SeqAIJ(newMat,0,rowlengths);CHKERRQ(ierr);
3642   a = (Mat_SeqAIJ*)newMat->data;
3643 
3644   ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr);
3645 
3646   /* read in nonzero values */
3647   ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr);
3648 
3649   /* set matrix "i" values */
3650   a->i[0] = 0;
3651   for (i=1; i<= M; i++) {
3652     a->i[i]      = a->i[i-1] + rowlengths[i-1];
3653     a->ilen[i-1] = rowlengths[i-1];
3654   }
3655   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
3656 
3657   ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3658   ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3659   PetscFunctionReturn(0);
3660 }
3661 
3662 #undef __FUNCT__
3663 #define __FUNCT__ "MatEqual_SeqAIJ"
3664 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg)
3665 {
3666   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data;
3667   PetscErrorCode ierr;
3668 #if defined(PETSC_USE_COMPLEX)
3669   PetscInt k;
3670 #endif
3671 
3672   PetscFunctionBegin;
3673   /* If the  matrix dimensions are not equal,or no of nonzeros */
3674   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
3675     *flg = PETSC_FALSE;
3676     PetscFunctionReturn(0);
3677   }
3678 
3679   /* if the a->i are the same */
3680   ierr = PetscMemcmp(a->i,b->i,(A->rmap->n+1)*sizeof(PetscInt),flg);CHKERRQ(ierr);
3681   if (!*flg) PetscFunctionReturn(0);
3682 
3683   /* if a->j are the same */
3684   ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);CHKERRQ(ierr);
3685   if (!*flg) PetscFunctionReturn(0);
3686 
3687   /* if a->a are the same */
3688 #if defined(PETSC_USE_COMPLEX)
3689   for (k=0; k<a->nz; k++){
3690     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])){
3691       *flg = PETSC_FALSE;
3692       PetscFunctionReturn(0);
3693     }
3694   }
3695 #else
3696   ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr);
3697 #endif
3698   PetscFunctionReturn(0);
3699 }
3700 
3701 #undef __FUNCT__
3702 #define __FUNCT__ "MatCreateSeqAIJWithArrays"
3703 /*@
3704      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
3705               provided by the user.
3706 
3707       Collective on MPI_Comm
3708 
3709    Input Parameters:
3710 +   comm - must be an MPI communicator of size 1
3711 .   m - number of rows
3712 .   n - number of columns
3713 .   i - row indices
3714 .   j - column indices
3715 -   a - matrix values
3716 
3717    Output Parameter:
3718 .   mat - the matrix
3719 
3720    Level: intermediate
3721 
3722    Notes:
3723        The i, j, and a arrays are not copied by this routine, the user must free these arrays
3724     once the matrix is destroyed
3725 
3726        You cannot set new nonzero locations into this matrix, that will generate an error.
3727 
3728        The i and j indices are 0 based
3729 
3730        The format which is used for the sparse matrix input, is equivalent to a
3731     row-major ordering.. i.e for the following matrix, the input data expected is
3732     as shown:
3733 
3734         1 0 0
3735         2 0 3
3736         4 5 6
3737 
3738         i =  {0,1,3,6}  [size = nrow+1  = 3+1]
3739         j =  {0,0,2,0,1,2}  [size = nz = 6]; values must be sorted for each row
3740         v =  {1,2,3,4,5,6}  [size = nz = 6]
3741 
3742 
3743 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
3744 
3745 @*/
3746 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
3747 {
3748   PetscErrorCode ierr;
3749   PetscInt       ii;
3750   Mat_SeqAIJ     *aij;
3751 #if defined(PETSC_USE_DEBUG)
3752   PetscInt       jj;
3753 #endif
3754 
3755   PetscFunctionBegin;
3756   if (i[0]) {
3757     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
3758   }
3759   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
3760   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
3761   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
3762   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr);
3763   aij  = (Mat_SeqAIJ*)(*mat)->data;
3764   ierr = PetscMalloc2(m,PetscInt,&aij->imax,m,PetscInt,&aij->ilen);CHKERRQ(ierr);
3765 
3766   aij->i = i;
3767   aij->j = j;
3768   aij->a = a;
3769   aij->singlemalloc = PETSC_FALSE;
3770   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
3771   aij->free_a       = PETSC_FALSE;
3772   aij->free_ij      = PETSC_FALSE;
3773 
3774   for (ii=0; ii<m; ii++) {
3775     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
3776 #if defined(PETSC_USE_DEBUG)
3777     if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]);
3778     for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
3779       if (j[jj] < j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is not sorted",jj-i[ii],j[jj],ii);
3780       if (j[jj] == j[jj]-1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is identical to previous entry",jj-i[ii],j[jj],ii);
3781     }
3782 #endif
3783   }
3784 #if defined(PETSC_USE_DEBUG)
3785   for (ii=0; ii<aij->i[m]; ii++) {
3786     if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
3787     if (j[ii] > n - 1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]);
3788   }
3789 #endif
3790 
3791   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3792   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3793   PetscFunctionReturn(0);
3794 }
3795 
3796 #undef __FUNCT__
3797 #define __FUNCT__ "MatSetColoring_SeqAIJ"
3798 PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring)
3799 {
3800   PetscErrorCode ierr;
3801   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3802 
3803   PetscFunctionBegin;
3804   if (coloring->ctype == IS_COLORING_GLOBAL) {
3805     ierr        = ISColoringReference(coloring);CHKERRQ(ierr);
3806     a->coloring = coloring;
3807   } else if (coloring->ctype == IS_COLORING_GHOSTED) {
3808     PetscInt             i,*larray;
3809     ISColoring      ocoloring;
3810     ISColoringValue *colors;
3811 
3812     /* set coloring for diagonal portion */
3813     ierr = PetscMalloc(A->cmap->n*sizeof(PetscInt),&larray);CHKERRQ(ierr);
3814     for (i=0; i<A->cmap->n; i++) {
3815       larray[i] = i;
3816     }
3817     ierr = ISGlobalToLocalMappingApply(A->mapping,IS_GTOLM_MASK,A->cmap->n,larray,PETSC_NULL,larray);CHKERRQ(ierr);
3818     ierr = PetscMalloc(A->cmap->n*sizeof(ISColoringValue),&colors);CHKERRQ(ierr);
3819     for (i=0; i<A->cmap->n; i++) {
3820       colors[i] = coloring->colors[larray[i]];
3821     }
3822     ierr = PetscFree(larray);CHKERRQ(ierr);
3823     ierr = ISColoringCreate(PETSC_COMM_SELF,coloring->n,A->cmap->n,colors,&ocoloring);CHKERRQ(ierr);
3824     a->coloring = ocoloring;
3825   }
3826   PetscFunctionReturn(0);
3827 }
3828 
3829 #if defined(PETSC_HAVE_ADIC)
3830 EXTERN_C_BEGIN
3831 #include "adic/ad_utils.h"
3832 EXTERN_C_END
3833 
3834 #undef __FUNCT__
3835 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ"
3836 PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
3837 {
3838   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3839   PetscInt        m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j,nlen;
3840   PetscScalar     *v = a->a,*values = ((PetscScalar*)advalues)+1;
3841   ISColoringValue *color;
3842 
3843   PetscFunctionBegin;
3844   if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
3845   nlen  = PetscADGetDerivTypeSize()/sizeof(PetscScalar);
3846   color = a->coloring->colors;
3847   /* loop over rows */
3848   for (i=0; i<m; i++) {
3849     nz = ii[i+1] - ii[i];
3850     /* loop over columns putting computed value into matrix */
3851     for (j=0; j<nz; j++) {
3852       *v++ = values[color[*jj++]];
3853     }
3854     values += nlen; /* jump to next row of derivatives */
3855   }
3856   PetscFunctionReturn(0);
3857 }
3858 #endif
3859 
3860 #undef __FUNCT__
3861 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ"
3862 PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues)
3863 {
3864   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3865   PetscInt         m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j;
3866   MatScalar       *v = a->a;
3867   PetscScalar     *values = (PetscScalar *)advalues;
3868   ISColoringValue *color;
3869 
3870   PetscFunctionBegin;
3871   if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
3872   color = a->coloring->colors;
3873   /* loop over rows */
3874   for (i=0; i<m; i++) {
3875     nz = ii[i+1] - ii[i];
3876     /* loop over columns putting computed value into matrix */
3877     for (j=0; j<nz; j++) {
3878       *v++ = values[color[*jj++]];
3879     }
3880     values += nl; /* jump to next row of derivatives */
3881   }
3882   PetscFunctionReturn(0);
3883 }
3884 
3885 /*
3886     Special version for direct calls from Fortran
3887 */
3888 #if defined(PETSC_HAVE_FORTRAN_CAPS)
3889 #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
3890 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
3891 #define matsetvaluesseqaij_ matsetvaluesseqaij
3892 #endif
3893 
3894 /* Change these macros so can be used in void function */
3895 #undef CHKERRQ
3896 #define CHKERRQ(ierr) CHKERRABORT(((PetscObject)A)->comm,ierr)
3897 #undef SETERRQ2
3898 #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
3899 
3900 EXTERN_C_BEGIN
3901 #undef __FUNCT__
3902 #define __FUNCT__ "matsetvaluesseqaij_"
3903 void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
3904 {
3905   Mat            A = *AA;
3906   PetscInt       m = *mm, n = *nn;
3907   InsertMode     is = *isis;
3908   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3909   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
3910   PetscInt       *imax,*ai,*ailen;
3911   PetscErrorCode ierr;
3912   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
3913   MatScalar      *ap,value,*aa;
3914   PetscTruth     ignorezeroentries = a->ignorezeroentries;
3915   PetscTruth     roworiented = a->roworiented;
3916 
3917   PetscFunctionBegin;
3918   ierr = MatPreallocated(A);CHKERRQ(ierr);
3919   imax = a->imax;
3920   ai = a->i;
3921   ailen = a->ilen;
3922   aj = a->j;
3923   aa = a->a;
3924 
3925   for (k=0; k<m; k++) { /* loop over added rows */
3926     row  = im[k];
3927     if (row < 0) continue;
3928 #if defined(PETSC_USE_DEBUG)
3929     if (row >= A->rmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
3930 #endif
3931     rp   = aj + ai[row]; ap = aa + ai[row];
3932     rmax = imax[row]; nrow = ailen[row];
3933     low  = 0;
3934     high = nrow;
3935     for (l=0; l<n; l++) { /* loop over added columns */
3936       if (in[l] < 0) continue;
3937 #if defined(PETSC_USE_DEBUG)
3938       if (in[l] >= A->cmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
3939 #endif
3940       col = in[l];
3941       if (roworiented) {
3942         value = v[l + k*n];
3943       } else {
3944         value = v[k + l*m];
3945       }
3946       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
3947 
3948       if (col <= lastcol) low = 0; else high = nrow;
3949       lastcol = col;
3950       while (high-low > 5) {
3951         t = (low+high)/2;
3952         if (rp[t] > col) high = t;
3953         else             low  = t;
3954       }
3955       for (i=low; i<high; i++) {
3956         if (rp[i] > col) break;
3957         if (rp[i] == col) {
3958           if (is == ADD_VALUES) ap[i] += value;
3959           else                  ap[i] = value;
3960           goto noinsert;
3961         }
3962       }
3963       if (value == 0.0 && ignorezeroentries) goto noinsert;
3964       if (nonew == 1) goto noinsert;
3965       if (nonew == -1) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
3966       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
3967       N = nrow++ - 1; a->nz++; high++;
3968       /* shift up all the later entries in this row */
3969       for (ii=N; ii>=i; ii--) {
3970         rp[ii+1] = rp[ii];
3971         ap[ii+1] = ap[ii];
3972       }
3973       rp[i] = col;
3974       ap[i] = value;
3975       noinsert:;
3976       low = i + 1;
3977     }
3978     ailen[row] = nrow;
3979   }
3980   A->same_nonzero = PETSC_FALSE;
3981   PetscFunctionReturnVoid();
3982 }
3983 EXTERN_C_END
3984