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