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