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