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