xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 592a1db9fdb3ea8a96be80ac744553e5e2c822c6)
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 #include <../src/mat/blocktranspose.h>
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         ierr  = Kernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
2966 	diag  += 4;
2967       }
2968       break;
2969     case 3:
2970       for (i=0; i<mbs; i++) {
2971         ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
2972         ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
2973         ierr  = Kernel_A_gets_inverse_A_3(diag,shift);CHKERRQ(ierr);
2974         ierr  = Kernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
2975 	diag    += 9;
2976       }
2977       break;
2978     case 4:
2979       for (i=0; i<mbs; i++) {
2980         ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
2981         ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
2982         ierr  = Kernel_A_gets_inverse_A_4(diag,shift);CHKERRQ(ierr);
2983         ierr  = Kernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
2984 	diag  += 16;
2985       }
2986       break;
2987     case 5:
2988       for (i=0; i<mbs; i++) {
2989         ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4;
2990         ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
2991         ierr  = Kernel_A_gets_inverse_A_5(diag,ipvt,work,shift);CHKERRQ(ierr);
2992         ierr  = Kernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
2993 	diag  += 25;
2994       }
2995       break;
2996     case 6:
2997       for (i=0; i<mbs; i++) {
2998         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;
2999         ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3000         ierr  = Kernel_A_gets_inverse_A_6(diag,shift);CHKERRQ(ierr);
3001         ierr  = Kernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3002 	diag  += 36;
3003       }
3004       break;
3005     case 7:
3006       for (i=0; i<mbs; i++) {
3007         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;
3008         ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3009         ierr  = Kernel_A_gets_inverse_A_7(diag,shift);CHKERRQ(ierr);
3010         ierr  = Kernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3011 	diag  += 49;
3012       }
3013       break;
3014     default:
3015       ierr = PetscMalloc3(bs,MatScalar,&v_work,bs,PetscInt,&v_pivots,bs,PetscInt,&IJ);CHKERRQ(ierr);
3016       for (i=0; i<mbs; i++) {
3017         for (j=0; j<bs; j++) {
3018           IJ[j] = bs*i + j;
3019         }
3020         ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
3021         ierr  = Kernel_A_gets_inverse_A(bs,diag,v_pivots,v_work);CHKERRQ(ierr);
3022         ierr  = Kernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3023 	diag  += bs2;
3024       }
3025       ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3026   }
3027   a->ibdiagvalid = PETSC_TRUE;
3028   PetscFunctionReturn(0);
3029 }
3030 
3031 extern PetscErrorCode  MatFDColoringApply_AIJ(Mat,MatFDColoring,Vec,MatStructure*,void*);
3032 /* -------------------------------------------------------------------*/
3033 static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
3034        MatGetRow_SeqAIJ,
3035        MatRestoreRow_SeqAIJ,
3036        MatMult_SeqAIJ,
3037 /* 4*/ MatMultAdd_SeqAIJ,
3038        MatMultTranspose_SeqAIJ,
3039        MatMultTransposeAdd_SeqAIJ,
3040        0,
3041        0,
3042        0,
3043 /*10*/ 0,
3044        MatLUFactor_SeqAIJ,
3045        0,
3046        MatSOR_SeqAIJ,
3047        MatTranspose_SeqAIJ,
3048 /*15*/ MatGetInfo_SeqAIJ,
3049        MatEqual_SeqAIJ,
3050        MatGetDiagonal_SeqAIJ,
3051        MatDiagonalScale_SeqAIJ,
3052        MatNorm_SeqAIJ,
3053 /*20*/ 0,
3054        MatAssemblyEnd_SeqAIJ,
3055        MatSetOption_SeqAIJ,
3056        MatZeroEntries_SeqAIJ,
3057 /*24*/ MatZeroRows_SeqAIJ,
3058        0,
3059        0,
3060        0,
3061        0,
3062 /*29*/ MatSetUpPreallocation_SeqAIJ,
3063        0,
3064        0,
3065        MatGetArray_SeqAIJ,
3066        MatRestoreArray_SeqAIJ,
3067 /*34*/ MatDuplicate_SeqAIJ,
3068        0,
3069        0,
3070        MatILUFactor_SeqAIJ,
3071        0,
3072 /*39*/ MatAXPY_SeqAIJ,
3073        MatGetSubMatrices_SeqAIJ,
3074        MatIncreaseOverlap_SeqAIJ,
3075        MatGetValues_SeqAIJ,
3076        MatCopy_SeqAIJ,
3077 /*44*/ MatGetRowMax_SeqAIJ,
3078        MatScale_SeqAIJ,
3079        0,
3080        MatDiagonalSet_SeqAIJ,
3081        MatZeroRowsColumns_SeqAIJ,
3082 /*49*/ MatSetBlockSize_SeqAIJ,
3083        MatGetRowIJ_SeqAIJ,
3084        MatRestoreRowIJ_SeqAIJ,
3085        MatGetColumnIJ_SeqAIJ,
3086        MatRestoreColumnIJ_SeqAIJ,
3087 /*54*/ MatFDColoringCreate_SeqAIJ,
3088        0,
3089        0,
3090        MatPermute_SeqAIJ,
3091        0,
3092 /*59*/ 0,
3093        MatDestroy_SeqAIJ,
3094        MatView_SeqAIJ,
3095        0,
3096        0,
3097 /*64*/ 0,
3098        0,
3099        0,
3100        0,
3101        0,
3102 /*69*/ MatGetRowMaxAbs_SeqAIJ,
3103        MatGetRowMinAbs_SeqAIJ,
3104        0,
3105        MatSetColoring_SeqAIJ,
3106 #if defined(PETSC_HAVE_ADIC)
3107        MatSetValuesAdic_SeqAIJ,
3108 #else
3109        0,
3110 #endif
3111 /*74*/ MatSetValuesAdifor_SeqAIJ,
3112        MatFDColoringApply_AIJ,
3113        0,
3114        0,
3115        0,
3116 /*79*/ MatFindZeroDiagonals_SeqAIJ,
3117        0,
3118        0,
3119        0,
3120        MatLoad_SeqAIJ,
3121 /*84*/ MatIsSymmetric_SeqAIJ,
3122        MatIsHermitian_SeqAIJ,
3123        0,
3124        0,
3125        0,
3126 /*89*/ MatMatMult_SeqAIJ_SeqAIJ,
3127        MatMatMultSymbolic_SeqAIJ_SeqAIJ,
3128        MatMatMultNumeric_SeqAIJ_SeqAIJ,
3129        MatPtAP_Basic,
3130        MatPtAPSymbolic_SeqAIJ,
3131 /*94*/ MatPtAPNumeric_SeqAIJ,
3132        MatMatMultTranspose_SeqAIJ_SeqAIJ,
3133        MatMatMultTransposeSymbolic_SeqAIJ_SeqAIJ,
3134        MatMatMultTransposeNumeric_SeqAIJ_SeqAIJ,
3135        MatPtAPSymbolic_SeqAIJ_SeqAIJ,
3136 /*99*/ MatPtAPNumeric_SeqAIJ_SeqAIJ,
3137        0,
3138        0,
3139        MatConjugate_SeqAIJ,
3140        0,
3141 /*104*/MatSetValuesRow_SeqAIJ,
3142        MatRealPart_SeqAIJ,
3143        MatImaginaryPart_SeqAIJ,
3144        0,
3145        0,
3146 /*109*/MatMatSolve_SeqAIJ,
3147        0,
3148        MatGetRowMin_SeqAIJ,
3149        0,
3150        MatMissingDiagonal_SeqAIJ,
3151 /*114*/0,
3152        0,
3153        0,
3154        0,
3155        0,
3156 /*119*/0,
3157        0,
3158        0,
3159        0,
3160        MatGetMultiProcBlock_SeqAIJ,
3161 /*124*/MatFindNonzeroRows_SeqAIJ,
3162        MatGetColumnNorms_SeqAIJ,
3163        MatInvertBlockDiagonal_SeqAIJ,
3164        0,
3165        0,
3166 /*129*/0,
3167        MatMatTransposeMult_SeqAIJ_SeqAIJ,
3168        MatMatTransposeMultSymbolic_SeqAIJ_SeqAIJ,
3169        MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3170        MatMultTransposeColoringCreate_SeqAIJ,
3171 /*134*/MatMultTransposeColoringApply_SeqAIJ,
3172        MatMultTransColoringApplyDenToSp_SeqAIJ
3173 };
3174 
3175 EXTERN_C_BEGIN
3176 #undef __FUNCT__
3177 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ"
3178 PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3179 {
3180   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
3181   PetscInt   i,nz,n;
3182 
3183   PetscFunctionBegin;
3184 
3185   nz = aij->maxnz;
3186   n  = mat->rmap->n;
3187   for (i=0; i<nz; i++) {
3188     aij->j[i] = indices[i];
3189   }
3190   aij->nz = nz;
3191   for (i=0; i<n; i++) {
3192     aij->ilen[i] = aij->imax[i];
3193   }
3194 
3195   PetscFunctionReturn(0);
3196 }
3197 EXTERN_C_END
3198 
3199 #undef __FUNCT__
3200 #define __FUNCT__ "MatSeqAIJSetColumnIndices"
3201 /*@
3202     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3203        in the matrix.
3204 
3205   Input Parameters:
3206 +  mat - the SeqAIJ matrix
3207 -  indices - the column indices
3208 
3209   Level: advanced
3210 
3211   Notes:
3212     This can be called if you have precomputed the nonzero structure of the
3213   matrix and want to provide it to the matrix object to improve the performance
3214   of the MatSetValues() operation.
3215 
3216     You MUST have set the correct numbers of nonzeros per row in the call to
3217   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3218 
3219     MUST be called before any calls to MatSetValues();
3220 
3221     The indices should start with zero, not one.
3222 
3223 @*/
3224 PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3225 {
3226   PetscErrorCode ierr;
3227 
3228   PetscFunctionBegin;
3229   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3230   PetscValidPointer(indices,2);
3231   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt *),(mat,indices));CHKERRQ(ierr);
3232   PetscFunctionReturn(0);
3233 }
3234 
3235 /* ----------------------------------------------------------------------------------------*/
3236 
3237 EXTERN_C_BEGIN
3238 #undef __FUNCT__
3239 #define __FUNCT__ "MatStoreValues_SeqAIJ"
3240 PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3241 {
3242   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
3243   PetscErrorCode ierr;
3244   size_t         nz = aij->i[mat->rmap->n];
3245 
3246   PetscFunctionBegin;
3247   if (aij->nonew != 1) {
3248     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3249   }
3250 
3251   /* allocate space for values if not already there */
3252   if (!aij->saved_values) {
3253     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
3254     ierr = PetscLogObjectMemory(mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3255   }
3256 
3257   /* copy values over */
3258   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
3259   PetscFunctionReturn(0);
3260 }
3261 EXTERN_C_END
3262 
3263 #undef __FUNCT__
3264 #define __FUNCT__ "MatStoreValues"
3265 /*@
3266     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3267        example, reuse of the linear part of a Jacobian, while recomputing the
3268        nonlinear portion.
3269 
3270    Collect on Mat
3271 
3272   Input Parameters:
3273 .  mat - the matrix (currently only AIJ matrices support this option)
3274 
3275   Level: advanced
3276 
3277   Common Usage, with SNESSolve():
3278 $    Create Jacobian matrix
3279 $    Set linear terms into matrix
3280 $    Apply boundary conditions to matrix, at this time matrix must have
3281 $      final nonzero structure (i.e. setting the nonlinear terms and applying
3282 $      boundary conditions again will not change the nonzero structure
3283 $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3284 $    ierr = MatStoreValues(mat);
3285 $    Call SNESSetJacobian() with matrix
3286 $    In your Jacobian routine
3287 $      ierr = MatRetrieveValues(mat);
3288 $      Set nonlinear terms in matrix
3289 
3290   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3291 $    // build linear portion of Jacobian
3292 $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3293 $    ierr = MatStoreValues(mat);
3294 $    loop over nonlinear iterations
3295 $       ierr = MatRetrieveValues(mat);
3296 $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3297 $       // call MatAssemblyBegin/End() on matrix
3298 $       Solve linear system with Jacobian
3299 $    endloop
3300 
3301   Notes:
3302     Matrix must already be assemblied before calling this routine
3303     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3304     calling this routine.
3305 
3306     When this is called multiple times it overwrites the previous set of stored values
3307     and does not allocated additional space.
3308 
3309 .seealso: MatRetrieveValues()
3310 
3311 @*/
3312 PetscErrorCode  MatStoreValues(Mat mat)
3313 {
3314   PetscErrorCode ierr;
3315 
3316   PetscFunctionBegin;
3317   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3318   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3319   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3320   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3321   PetscFunctionReturn(0);
3322 }
3323 
3324 EXTERN_C_BEGIN
3325 #undef __FUNCT__
3326 #define __FUNCT__ "MatRetrieveValues_SeqAIJ"
3327 PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3328 {
3329   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
3330   PetscErrorCode ierr;
3331   PetscInt       nz = aij->i[mat->rmap->n];
3332 
3333   PetscFunctionBegin;
3334   if (aij->nonew != 1) {
3335     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3336   }
3337   if (!aij->saved_values) {
3338     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3339   }
3340   /* copy values over */
3341   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
3342   PetscFunctionReturn(0);
3343 }
3344 EXTERN_C_END
3345 
3346 #undef __FUNCT__
3347 #define __FUNCT__ "MatRetrieveValues"
3348 /*@
3349     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3350        example, reuse of the linear part of a Jacobian, while recomputing the
3351        nonlinear portion.
3352 
3353    Collect on Mat
3354 
3355   Input Parameters:
3356 .  mat - the matrix (currently on AIJ matrices support this option)
3357 
3358   Level: advanced
3359 
3360 .seealso: MatStoreValues()
3361 
3362 @*/
3363 PetscErrorCode  MatRetrieveValues(Mat mat)
3364 {
3365   PetscErrorCode ierr;
3366 
3367   PetscFunctionBegin;
3368   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3369   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3370   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3371   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3372   PetscFunctionReturn(0);
3373 }
3374 
3375 
3376 /* --------------------------------------------------------------------------------*/
3377 #undef __FUNCT__
3378 #define __FUNCT__ "MatCreateSeqAIJ"
3379 /*@C
3380    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
3381    (the default parallel PETSc format).  For good matrix assembly performance
3382    the user should preallocate the matrix storage by setting the parameter nz
3383    (or the array nnz).  By setting these parameters accurately, performance
3384    during matrix assembly can be increased by more than a factor of 50.
3385 
3386    Collective on MPI_Comm
3387 
3388    Input Parameters:
3389 +  comm - MPI communicator, set to PETSC_COMM_SELF
3390 .  m - number of rows
3391 .  n - number of columns
3392 .  nz - number of nonzeros per row (same for all rows)
3393 -  nnz - array containing the number of nonzeros in the various rows
3394          (possibly different for each row) or PETSC_NULL
3395 
3396    Output Parameter:
3397 .  A - the matrix
3398 
3399    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3400    MatXXXXSetPreallocation() paradgm instead of this routine directly.
3401    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3402 
3403    Notes:
3404    If nnz is given then nz is ignored
3405 
3406    The AIJ format (also called the Yale sparse matrix format or
3407    compressed row storage), is fully compatible with standard Fortran 77
3408    storage.  That is, the stored row and column indices can begin at
3409    either one (as in Fortran) or zero.  See the users' manual for details.
3410 
3411    Specify the preallocated storage with either nz or nnz (not both).
3412    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
3413    allocation.  For large problems you MUST preallocate memory or you
3414    will get TERRIBLE performance, see the users' manual chapter on matrices.
3415 
3416    By default, this format uses inodes (identical nodes) when possible, to
3417    improve numerical efficiency of matrix-vector products and solves. We
3418    search for consecutive rows with the same nonzero structure, thereby
3419    reusing matrix information to achieve increased efficiency.
3420 
3421    Options Database Keys:
3422 +  -mat_no_inode  - Do not use inodes
3423 -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3424 
3425    Level: intermediate
3426 
3427 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
3428 
3429 @*/
3430 PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
3431 {
3432   PetscErrorCode ierr;
3433 
3434   PetscFunctionBegin;
3435   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3436   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3437   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
3438   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
3439   PetscFunctionReturn(0);
3440 }
3441 
3442 #undef __FUNCT__
3443 #define __FUNCT__ "MatSeqAIJSetPreallocation"
3444 /*@C
3445    MatSeqAIJSetPreallocation - For good matrix assembly performance
3446    the user should preallocate the matrix storage by setting the parameter nz
3447    (or the array nnz).  By setting these parameters accurately, performance
3448    during matrix assembly can be increased by more than a factor of 50.
3449 
3450    Collective on MPI_Comm
3451 
3452    Input Parameters:
3453 +  B - The matrix-free
3454 .  nz - number of nonzeros per row (same for all rows)
3455 -  nnz - array containing the number of nonzeros in the various rows
3456          (possibly different for each row) or PETSC_NULL
3457 
3458    Notes:
3459      If nnz is given then nz is ignored
3460 
3461     The AIJ format (also called the Yale sparse matrix format or
3462    compressed row storage), is fully compatible with standard Fortran 77
3463    storage.  That is, the stored row and column indices can begin at
3464    either one (as in Fortran) or zero.  See the users' manual for details.
3465 
3466    Specify the preallocated storage with either nz or nnz (not both).
3467    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
3468    allocation.  For large problems you MUST preallocate memory or you
3469    will get TERRIBLE performance, see the users' manual chapter on matrices.
3470 
3471    You can call MatGetInfo() to get information on how effective the preallocation was;
3472    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3473    You can also run with the option -info and look for messages with the string
3474    malloc in them to see if additional memory allocation was needed.
3475 
3476    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
3477    entries or columns indices
3478 
3479    By default, this format uses inodes (identical nodes) when possible, to
3480    improve numerical efficiency of matrix-vector products and solves. We
3481    search for consecutive rows with the same nonzero structure, thereby
3482    reusing matrix information to achieve increased efficiency.
3483 
3484    Options Database Keys:
3485 +  -mat_no_inode  - Do not use inodes
3486 .  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3487 -  -mat_aij_oneindex - Internally use indexing starting at 1
3488         rather than 0.  Note that when calling MatSetValues(),
3489         the user still MUST index entries starting at 0!
3490 
3491    Level: intermediate
3492 
3493 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo()
3494 
3495 @*/
3496 PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
3497 {
3498   PetscErrorCode ierr;
3499 
3500   PetscFunctionBegin;
3501   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
3502   PetscFunctionReturn(0);
3503 }
3504 
3505 EXTERN_C_BEGIN
3506 #undef __FUNCT__
3507 #define __FUNCT__ "MatSeqAIJSetPreallocation_SeqAIJ"
3508 PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
3509 {
3510   Mat_SeqAIJ     *b;
3511   PetscBool      skipallocation = PETSC_FALSE;
3512   PetscErrorCode ierr;
3513   PetscInt       i;
3514 
3515   PetscFunctionBegin;
3516 
3517   if (nz == MAT_SKIP_ALLOCATION) {
3518     skipallocation = PETSC_TRUE;
3519     nz             = 0;
3520   }
3521 
3522   ierr = PetscLayoutSetBlockSize(B->rmap,1);CHKERRQ(ierr);
3523   ierr = PetscLayoutSetBlockSize(B->cmap,1);CHKERRQ(ierr);
3524   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
3525   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
3526 
3527   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
3528   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
3529   if (nnz) {
3530     for (i=0; i<B->rmap->n; i++) {
3531       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]);
3532       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);
3533     }
3534   }
3535 
3536   B->preallocated = PETSC_TRUE;
3537   b = (Mat_SeqAIJ*)B->data;
3538 
3539   if (!skipallocation) {
3540     if (!b->imax) {
3541       ierr = PetscMalloc2(B->rmap->n,PetscInt,&b->imax,B->rmap->n,PetscInt,&b->ilen);CHKERRQ(ierr);
3542       ierr = PetscLogObjectMemory(B,2*B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3543     }
3544     if (!nnz) {
3545       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
3546       else if (nz < 0) nz = 1;
3547       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
3548       nz = nz*B->rmap->n;
3549     } else {
3550       nz = 0;
3551       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
3552     }
3553     /* b->ilen will count nonzeros in each row so far. */
3554     for (i=0; i<B->rmap->n; i++) { b->ilen[i] = 0; }
3555 
3556     /* allocate the matrix space */
3557     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
3558     ierr = PetscMalloc3(nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->n+1,PetscInt,&b->i);CHKERRQ(ierr);
3559     ierr = PetscLogObjectMemory(B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
3560     b->i[0] = 0;
3561     for (i=1; i<B->rmap->n+1; i++) {
3562       b->i[i] = b->i[i-1] + b->imax[i-1];
3563     }
3564     b->singlemalloc = PETSC_TRUE;
3565     b->free_a       = PETSC_TRUE;
3566     b->free_ij      = PETSC_TRUE;
3567   } else {
3568     b->free_a       = PETSC_FALSE;
3569     b->free_ij      = PETSC_FALSE;
3570   }
3571 
3572   b->nz                = 0;
3573   b->maxnz             = nz;
3574   B->info.nz_unneeded  = (double)b->maxnz;
3575   PetscFunctionReturn(0);
3576 }
3577 EXTERN_C_END
3578 
3579 #undef  __FUNCT__
3580 #define __FUNCT__  "MatSeqAIJSetPreallocationCSR"
3581 /*@
3582    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
3583 
3584    Input Parameters:
3585 +  B - the matrix
3586 .  i - the indices into j for the start of each row (starts with zero)
3587 .  j - the column indices for each row (starts with zero) these must be sorted for each row
3588 -  v - optional values in the matrix
3589 
3590    Level: developer
3591 
3592    The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
3593 
3594 .keywords: matrix, aij, compressed row, sparse, sequential
3595 
3596 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), SeqAIJ
3597 @*/
3598 PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
3599 {
3600   PetscErrorCode ierr;
3601 
3602   PetscFunctionBegin;
3603   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
3604   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
3605   PetscFunctionReturn(0);
3606 }
3607 
3608 EXTERN_C_BEGIN
3609 #undef  __FUNCT__
3610 #define __FUNCT__  "MatSeqAIJSetPreallocationCSR_SeqAIJ"
3611 PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
3612 {
3613   PetscInt       i;
3614   PetscInt       m,n;
3615   PetscInt       nz;
3616   PetscInt       *nnz, nz_max = 0;
3617   PetscScalar    *values;
3618   PetscErrorCode ierr;
3619 
3620   PetscFunctionBegin;
3621   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
3622 
3623   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
3624   ierr = PetscMalloc((m+1) * sizeof(PetscInt), &nnz);CHKERRQ(ierr);
3625   for(i = 0; i < m; i++) {
3626     nz     = Ii[i+1]- Ii[i];
3627     nz_max = PetscMax(nz_max, nz);
3628     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
3629     nnz[i] = nz;
3630   }
3631   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
3632   ierr = PetscFree(nnz);CHKERRQ(ierr);
3633 
3634   if (v) {
3635     values = (PetscScalar*) v;
3636   } else {
3637     ierr = PetscMalloc(nz_max*sizeof(PetscScalar), &values);CHKERRQ(ierr);
3638     ierr = PetscMemzero(values, nz_max*sizeof(PetscScalar));CHKERRQ(ierr);
3639   }
3640 
3641   for(i = 0; i < m; i++) {
3642     nz  = Ii[i+1] - Ii[i];
3643     ierr = MatSetValues_SeqAIJ(B, 1, &i, nz, J+Ii[i], values + (v ? Ii[i] : 0), INSERT_VALUES);CHKERRQ(ierr);
3644   }
3645 
3646   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3647   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3648 
3649   if (!v) {
3650     ierr = PetscFree(values);CHKERRQ(ierr);
3651   }
3652   PetscFunctionReturn(0);
3653 }
3654 EXTERN_C_END
3655 
3656 #include <../src/mat/impls/dense/seq/dense.h>
3657 #include <private/petscaxpy.h>
3658 
3659 #undef __FUNCT__
3660 #define __FUNCT__ "MatMatMultNumeric_SeqDense_SeqAIJ"
3661 /*
3662     Computes (B'*A')' since computing B*A directly is untenable
3663 
3664                n                       p                          p
3665         (              )       (              )         (                  )
3666       m (      A       )  *  n (       B      )   =   m (         C        )
3667         (              )       (              )         (                  )
3668 
3669 */
3670 PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
3671 {
3672   PetscErrorCode     ierr;
3673   Mat_SeqDense       *sub_a = (Mat_SeqDense*)A->data;
3674   Mat_SeqAIJ         *sub_b = (Mat_SeqAIJ*)B->data;
3675   Mat_SeqDense       *sub_c = (Mat_SeqDense*)C->data;
3676   PetscInt           i,n,m,q,p;
3677   const PetscInt     *ii,*idx;
3678   const PetscScalar  *b,*a,*a_q;
3679   PetscScalar        *c,*c_q;
3680 
3681   PetscFunctionBegin;
3682   m = A->rmap->n;
3683   n = A->cmap->n;
3684   p = B->cmap->n;
3685   a = sub_a->v;
3686   b = sub_b->a;
3687   c = sub_c->v;
3688   ierr = PetscMemzero(c,m*p*sizeof(PetscScalar));CHKERRQ(ierr);
3689 
3690   ii  = sub_b->i;
3691   idx = sub_b->j;
3692   for (i=0; i<n; i++) {
3693     q = ii[i+1] - ii[i];
3694     while (q-->0) {
3695       c_q = c + m*(*idx);
3696       a_q = a + m*i;
3697       PetscAXPY(c_q,*b,a_q,m);
3698       idx++;
3699       b++;
3700     }
3701   }
3702   PetscFunctionReturn(0);
3703 }
3704 
3705 #undef __FUNCT__
3706 #define __FUNCT__ "MatMatMultSymbolic_SeqDense_SeqAIJ"
3707 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C)
3708 {
3709   PetscErrorCode ierr;
3710   PetscInt       m=A->rmap->n,n=B->cmap->n;
3711   Mat            Cmat;
3712 
3713   PetscFunctionBegin;
3714   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);
3715   ierr = MatCreate(((PetscObject)A)->comm,&Cmat);CHKERRQ(ierr);
3716   ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr);
3717   ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr);
3718   ierr = MatSeqDenseSetPreallocation(Cmat,PETSC_NULL);CHKERRQ(ierr);
3719   Cmat->assembled = PETSC_TRUE;
3720   *C = Cmat;
3721   PetscFunctionReturn(0);
3722 }
3723 
3724 /* ----------------------------------------------------------------*/
3725 #undef __FUNCT__
3726 #define __FUNCT__ "MatMatMult_SeqDense_SeqAIJ"
3727 PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
3728 {
3729   PetscErrorCode ierr;
3730 
3731   PetscFunctionBegin;
3732   if (scall == MAT_INITIAL_MATRIX){
3733     ierr = MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);CHKERRQ(ierr);
3734   }
3735   ierr = MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);CHKERRQ(ierr);
3736   PetscFunctionReturn(0);
3737 }
3738 
3739 
3740 /*MC
3741    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
3742    based on compressed sparse row format.
3743 
3744    Options Database Keys:
3745 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
3746 
3747   Level: beginner
3748 
3749 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
3750 M*/
3751 
3752 EXTERN_C_BEGIN
3753 #if defined(PETSC_HAVE_PASTIX)
3754 extern PetscErrorCode MatGetFactor_seqaij_pastix(Mat,MatFactorType,Mat*);
3755 #endif
3756 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128)
3757 extern PetscErrorCode MatGetFactor_seqaij_essl(Mat,MatFactorType,Mat *);
3758 #endif
3759 extern PetscErrorCode  MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
3760 extern PetscErrorCode  MatGetFactor_seqaij_petsc(Mat,MatFactorType,Mat*);
3761 extern PetscErrorCode  MatGetFactor_seqaij_bas(Mat,MatFactorType,Mat*);
3762 extern PetscErrorCode  MatGetFactorAvailable_seqaij_petsc(Mat,MatFactorType,PetscBool  *);
3763 #if defined(PETSC_HAVE_MUMPS)
3764 extern PetscErrorCode  MatGetFactor_aij_mumps(Mat,MatFactorType,Mat*);
3765 #endif
3766 #if defined(PETSC_HAVE_SUPERLU)
3767 extern PetscErrorCode  MatGetFactor_seqaij_superlu(Mat,MatFactorType,Mat*);
3768 #endif
3769 #if defined(PETSC_HAVE_SUPERLU_DIST)
3770 extern PetscErrorCode MatGetFactor_seqaij_superlu_dist(Mat,MatFactorType,Mat*);
3771 #endif
3772 #if defined(PETSC_HAVE_SPOOLES)
3773 extern PetscErrorCode  MatGetFactor_seqaij_spooles(Mat,MatFactorType,Mat*);
3774 #endif
3775 #if defined(PETSC_HAVE_UMFPACK)
3776 extern PetscErrorCode  MatGetFactor_seqaij_umfpack(Mat,MatFactorType,Mat*);
3777 #endif
3778 #if defined(PETSC_HAVE_CHOLMOD)
3779 extern PetscErrorCode  MatGetFactor_seqaij_cholmod(Mat,MatFactorType,Mat*);
3780 #endif
3781 #if defined(PETSC_HAVE_LUSOL)
3782 extern PetscErrorCode  MatGetFactor_seqaij_lusol(Mat,MatFactorType,Mat*);
3783 #endif
3784 #if defined(PETSC_HAVE_MATLAB_ENGINE)
3785 extern PetscErrorCode  MatGetFactor_seqaij_matlab(Mat,MatFactorType,Mat*);
3786 extern PetscErrorCode  MatlabEnginePut_SeqAIJ(PetscObject,void*);
3787 extern PetscErrorCode  MatlabEngineGet_SeqAIJ(PetscObject,void*);
3788 #endif
3789 EXTERN_C_END
3790 
3791 EXTERN_C_BEGIN
3792 #undef __FUNCT__
3793 #define __FUNCT__ "MatCreate_SeqAIJ"
3794 PetscErrorCode  MatCreate_SeqAIJ(Mat B)
3795 {
3796   Mat_SeqAIJ     *b;
3797   PetscErrorCode ierr;
3798   PetscMPIInt    size;
3799 
3800   PetscFunctionBegin;
3801   ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr);
3802   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
3803 
3804   ierr = PetscNewLog(B,Mat_SeqAIJ,&b);CHKERRQ(ierr);
3805   B->data             = (void*)b;
3806   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
3807   b->row              = 0;
3808   b->col              = 0;
3809   b->icol             = 0;
3810   b->reallocs         = 0;
3811   b->ignorezeroentries = PETSC_FALSE;
3812   b->roworiented       = PETSC_TRUE;
3813   b->nonew             = 0;
3814   b->diag              = 0;
3815   b->solve_work        = 0;
3816   B->spptr             = 0;
3817   b->saved_values      = 0;
3818   b->idiag             = 0;
3819   b->mdiag             = 0;
3820   b->ssor_work         = 0;
3821   b->omega             = 1.0;
3822   b->fshift            = 0.0;
3823   b->idiagvalid        = PETSC_FALSE;
3824   b->ibdiagvalid       = PETSC_FALSE;
3825   b->keepnonzeropattern    = PETSC_FALSE;
3826   b->xtoy              = 0;
3827   b->XtoY              = 0;
3828   B->same_nonzero          = PETSC_FALSE;
3829 
3830   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
3831 #if defined(PETSC_HAVE_MATLAB_ENGINE)
3832   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_matlab_C","MatGetFactor_seqaij_matlab",MatGetFactor_seqaij_matlab);CHKERRQ(ierr);
3833   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEnginePut_C","MatlabEnginePut_SeqAIJ",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
3834   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEngineGet_C","MatlabEngineGet_SeqAIJ",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
3835 #endif
3836 #if defined(PETSC_HAVE_PASTIX)
3837   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_pastix_C","MatGetFactor_seqaij_pastix",MatGetFactor_seqaij_pastix);CHKERRQ(ierr);
3838 #endif
3839 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128)
3840   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_essl_C","MatGetFactor_seqaij_essl",MatGetFactor_seqaij_essl);CHKERRQ(ierr);
3841 #endif
3842 #if defined(PETSC_HAVE_SUPERLU)
3843   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_C","MatGetFactor_seqaij_superlu",MatGetFactor_seqaij_superlu);CHKERRQ(ierr);
3844 #endif
3845 #if defined(PETSC_HAVE_SUPERLU_DIST)
3846   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_dist_C","MatGetFactor_seqaij_superlu_dist",MatGetFactor_seqaij_superlu_dist);CHKERRQ(ierr);
3847 #endif
3848 #if defined(PETSC_HAVE_SPOOLES)
3849   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_spooles_C","MatGetFactor_seqaij_spooles",MatGetFactor_seqaij_spooles);CHKERRQ(ierr);
3850 #endif
3851 #if defined(PETSC_HAVE_MUMPS)
3852   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_mumps_C","MatGetFactor_aij_mumps",MatGetFactor_aij_mumps);CHKERRQ(ierr);
3853 #endif
3854 #if defined(PETSC_HAVE_UMFPACK)
3855     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_umfpack_C","MatGetFactor_seqaij_umfpack",MatGetFactor_seqaij_umfpack);CHKERRQ(ierr);
3856 #endif
3857 #if defined(PETSC_HAVE_CHOLMOD)
3858     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_cholmod_C","MatGetFactor_seqaij_cholmod",MatGetFactor_seqaij_cholmod);CHKERRQ(ierr);
3859 #endif
3860 #if defined(PETSC_HAVE_LUSOL)
3861     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_lusol_C","MatGetFactor_seqaij_lusol",MatGetFactor_seqaij_lusol);CHKERRQ(ierr);
3862 #endif
3863   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_petsc_C","MatGetFactor_seqaij_petsc",MatGetFactor_seqaij_petsc);CHKERRQ(ierr);
3864   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_petsc_C","MatGetFactorAvailable_seqaij_petsc",MatGetFactorAvailable_seqaij_petsc);CHKERRQ(ierr);
3865   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_bas_C","MatGetFactor_seqaij_bas",MatGetFactor_seqaij_bas);CHKERRQ(ierr);
3866   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C","MatSeqAIJSetColumnIndices_SeqAIJ",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
3867   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C","MatStoreValues_SeqAIJ",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
3868   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C","MatRetrieveValues_SeqAIJ",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
3869   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C","MatConvert_SeqAIJ_SeqSBAIJ",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
3870   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C","MatConvert_SeqAIJ_SeqBAIJ",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
3871   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqaijperm_C","MatConvert_SeqAIJ_SeqAIJPERM",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
3872   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C","MatConvert_SeqAIJ_SeqAIJCRL",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
3873   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C","MatIsTranspose_SeqAIJ",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
3874   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsHermitianTranspose_C","MatIsHermitianTranspose_SeqAIJ",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
3875   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C","MatSeqAIJSetPreallocation_SeqAIJ",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
3876   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C","MatSeqAIJSetPreallocationCSR_SeqAIJ",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
3877   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C","MatReorderForNonzeroDiagonal_SeqAIJ",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
3878   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMult_seqdense_seqaij_C","MatMatMult_SeqDense_SeqAIJ",MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr);
3879   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C","MatMatMultSymbolic_SeqDense_SeqAIJ",MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr);
3880   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C","MatMatMultNumeric_SeqDense_SeqAIJ",MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr);
3881   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
3882   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
3883   PetscFunctionReturn(0);
3884 }
3885 EXTERN_C_END
3886 
3887 #if defined(PETSC_HAVE_PTHREADCLASSES)
3888 EXTERN_C_BEGIN
3889 #undef __FUNCT__
3890 #define __FUNCT__ "MatCreate_SeqAIJPThread"
3891 PetscErrorCode  MatCreate_SeqAIJPThread(Mat B)
3892 {
3893   PetscErrorCode ierr;
3894 
3895   PetscFunctionBegin;
3896   ierr = MatCreate_SeqAIJ(B);
3897   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
3898   B->ops->mult = MatMult_SeqAIJPThread;
3899   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJPTHREAD);CHKERRQ(ierr);
3900   PetscFunctionReturn(0);
3901 }
3902 EXTERN_C_END
3903 #endif
3904 
3905 #undef __FUNCT__
3906 #define __FUNCT__ "MatDuplicateNoCreate_SeqAIJ"
3907 /*
3908     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
3909 */
3910 PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool  mallocmatspace)
3911 {
3912   Mat_SeqAIJ     *c,*a = (Mat_SeqAIJ*)A->data;
3913   PetscErrorCode ierr;
3914   PetscInt       i,m = A->rmap->n;
3915 
3916   PetscFunctionBegin;
3917   c = (Mat_SeqAIJ*)C->data;
3918 
3919   C->factortype     = A->factortype;
3920   c->row            = 0;
3921   c->col            = 0;
3922   c->icol           = 0;
3923   c->reallocs       = 0;
3924 
3925   C->assembled      = PETSC_TRUE;
3926 
3927   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
3928   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
3929 
3930   ierr = PetscMalloc2(m,PetscInt,&c->imax,m,PetscInt,&c->ilen);CHKERRQ(ierr);
3931   ierr = PetscLogObjectMemory(C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
3932   for (i=0; i<m; i++) {
3933     c->imax[i] = a->imax[i];
3934     c->ilen[i] = a->ilen[i];
3935   }
3936 
3937   /* allocate the matrix space */
3938   if (mallocmatspace){
3939     ierr = PetscMalloc3(a->i[m],PetscScalar,&c->a,a->i[m],PetscInt,&c->j,m+1,PetscInt,&c->i);CHKERRQ(ierr);
3940     ierr = PetscLogObjectMemory(C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
3941     c->singlemalloc = PETSC_TRUE;
3942     ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
3943     if (m > 0) {
3944       ierr = PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));CHKERRQ(ierr);
3945       if (cpvalues == MAT_COPY_VALUES) {
3946         ierr = PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
3947       } else {
3948         ierr = PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
3949       }
3950     }
3951   }
3952 
3953   c->ignorezeroentries = a->ignorezeroentries;
3954   c->roworiented       = a->roworiented;
3955   c->nonew             = a->nonew;
3956   if (a->diag) {
3957     ierr = PetscMalloc((m+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr);
3958     ierr = PetscLogObjectMemory(C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
3959     for (i=0; i<m; i++) {
3960       c->diag[i] = a->diag[i];
3961     }
3962   } else c->diag           = 0;
3963   c->solve_work            = 0;
3964   c->saved_values          = 0;
3965   c->idiag                 = 0;
3966   c->ssor_work             = 0;
3967   c->keepnonzeropattern    = a->keepnonzeropattern;
3968   c->free_a                = PETSC_TRUE;
3969   c->free_ij               = PETSC_TRUE;
3970   c->xtoy                  = 0;
3971   c->XtoY                  = 0;
3972 
3973   c->nz                 = a->nz;
3974   c->maxnz              = a->nz; /* Since we allocate exactly the right amount */
3975   C->preallocated       = PETSC_TRUE;
3976 
3977   c->compressedrow.use     = a->compressedrow.use;
3978   c->compressedrow.nrows   = a->compressedrow.nrows;
3979   c->compressedrow.check   = a->compressedrow.check;
3980   if (a->compressedrow.use){
3981     i = a->compressedrow.nrows;
3982     ierr = PetscMalloc2(i+1,PetscInt,&c->compressedrow.i,i,PetscInt,&c->compressedrow.rindex);CHKERRQ(ierr);
3983     ierr = PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));CHKERRQ(ierr);
3984     ierr = PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));CHKERRQ(ierr);
3985   } else {
3986     c->compressedrow.use    = PETSC_FALSE;
3987     c->compressedrow.i      = PETSC_NULL;
3988     c->compressedrow.rindex = PETSC_NULL;
3989   }
3990   C->same_nonzero = A->same_nonzero;
3991   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
3992 
3993   ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
3994   PetscFunctionReturn(0);
3995 }
3996 
3997 #undef __FUNCT__
3998 #define __FUNCT__ "MatDuplicate_SeqAIJ"
3999 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4000 {
4001   PetscErrorCode ierr;
4002 
4003   PetscFunctionBegin;
4004   ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr);
4005   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4006   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4007   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4008   PetscFunctionReturn(0);
4009 }
4010 
4011 #undef __FUNCT__
4012 #define __FUNCT__ "MatLoad_SeqAIJ"
4013 PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4014 {
4015   Mat_SeqAIJ     *a;
4016   PetscErrorCode ierr;
4017   PetscInt       i,sum,nz,header[4],*rowlengths = 0,M,N,rows,cols;
4018   int            fd;
4019   PetscMPIInt    size;
4020   MPI_Comm       comm;
4021   PetscInt       bs = 1;
4022 
4023   PetscFunctionBegin;
4024   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
4025   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
4026   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor");
4027 
4028   ierr = PetscOptionsBegin(comm,PETSC_NULL,"Options for loading SEQAIJ matrix","Mat");CHKERRQ(ierr);
4029   ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);CHKERRQ(ierr);
4030   ierr = PetscOptionsEnd();CHKERRQ(ierr);
4031 
4032   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
4033   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
4034   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
4035   M = header[1]; N = header[2]; nz = header[3];
4036 
4037   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
4038 
4039   /* read in row lengths */
4040   ierr = PetscMalloc(M*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
4041   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
4042 
4043   /* check if sum of rowlengths is same as nz */
4044   for (i=0,sum=0; i< M; i++) sum +=rowlengths[i];
4045   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);
4046 
4047   /* set global size if not set already*/
4048   if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) {
4049     ierr = MatSetSizes(newMat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
4050   } else {
4051     /* if sizes and type are already set, check if the vector global sizes are correct */
4052     ierr = MatGetSize(newMat,&rows,&cols);CHKERRQ(ierr);
4053     if (rows < 0 && cols < 0){ /* user might provide local size instead of global size */
4054       ierr = MatGetLocalSize(newMat,&rows,&cols);CHKERRQ(ierr);
4055     }
4056     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);
4057   }
4058   ierr = MatSeqAIJSetPreallocation_SeqAIJ(newMat,0,rowlengths);CHKERRQ(ierr);
4059   a = (Mat_SeqAIJ*)newMat->data;
4060 
4061   ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr);
4062 
4063   /* read in nonzero values */
4064   ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr);
4065 
4066   /* set matrix "i" values */
4067   a->i[0] = 0;
4068   for (i=1; i<= M; i++) {
4069     a->i[i]      = a->i[i-1] + rowlengths[i-1];
4070     a->ilen[i-1] = rowlengths[i-1];
4071   }
4072   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
4073 
4074   ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4075   ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4076   if (bs > 1) {ierr = MatSetBlockSize(newMat,bs);CHKERRQ(ierr);}
4077   PetscFunctionReturn(0);
4078 }
4079 
4080 #undef __FUNCT__
4081 #define __FUNCT__ "MatEqual_SeqAIJ"
4082 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
4083 {
4084   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data;
4085   PetscErrorCode ierr;
4086 #if defined(PETSC_USE_COMPLEX)
4087   PetscInt k;
4088 #endif
4089 
4090   PetscFunctionBegin;
4091   /* If the  matrix dimensions are not equal,or no of nonzeros */
4092   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4093     *flg = PETSC_FALSE;
4094     PetscFunctionReturn(0);
4095   }
4096 
4097   /* if the a->i are the same */
4098   ierr = PetscMemcmp(a->i,b->i,(A->rmap->n+1)*sizeof(PetscInt),flg);CHKERRQ(ierr);
4099   if (!*flg) PetscFunctionReturn(0);
4100 
4101   /* if a->j are the same */
4102   ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);CHKERRQ(ierr);
4103   if (!*flg) PetscFunctionReturn(0);
4104 
4105   /* if a->a are the same */
4106 #if defined(PETSC_USE_COMPLEX)
4107   for (k=0; k<a->nz; k++){
4108     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])){
4109       *flg = PETSC_FALSE;
4110       PetscFunctionReturn(0);
4111     }
4112   }
4113 #else
4114   ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr);
4115 #endif
4116   PetscFunctionReturn(0);
4117 }
4118 
4119 #undef __FUNCT__
4120 #define __FUNCT__ "MatCreateSeqAIJWithArrays"
4121 /*@
4122      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
4123               provided by the user.
4124 
4125       Collective on MPI_Comm
4126 
4127    Input Parameters:
4128 +   comm - must be an MPI communicator of size 1
4129 .   m - number of rows
4130 .   n - number of columns
4131 .   i - row indices
4132 .   j - column indices
4133 -   a - matrix values
4134 
4135    Output Parameter:
4136 .   mat - the matrix
4137 
4138    Level: intermediate
4139 
4140    Notes:
4141        The i, j, and a arrays are not copied by this routine, the user must free these arrays
4142     once the matrix is destroyed and not before
4143 
4144        You cannot set new nonzero locations into this matrix, that will generate an error.
4145 
4146        The i and j indices are 0 based
4147 
4148        The format which is used for the sparse matrix input, is equivalent to a
4149     row-major ordering.. i.e for the following matrix, the input data expected is
4150     as shown:
4151 
4152         1 0 0
4153         2 0 3
4154         4 5 6
4155 
4156         i =  {0,1,3,6}  [size = nrow+1  = 3+1]
4157         j =  {0,0,2,0,1,2}  [size = nz = 6]; values must be sorted for each row
4158         v =  {1,2,3,4,5,6}  [size = nz = 6]
4159 
4160 
4161 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
4162 
4163 @*/
4164 PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
4165 {
4166   PetscErrorCode ierr;
4167   PetscInt       ii;
4168   Mat_SeqAIJ     *aij;
4169 #if defined(PETSC_USE_DEBUG)
4170   PetscInt       jj;
4171 #endif
4172 
4173   PetscFunctionBegin;
4174   if (i[0]) {
4175     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4176   }
4177   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
4178   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
4179   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
4180   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr);
4181   aij  = (Mat_SeqAIJ*)(*mat)->data;
4182   ierr = PetscMalloc2(m,PetscInt,&aij->imax,m,PetscInt,&aij->ilen);CHKERRQ(ierr);
4183 
4184   aij->i = i;
4185   aij->j = j;
4186   aij->a = a;
4187   aij->singlemalloc = PETSC_FALSE;
4188   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4189   aij->free_a       = PETSC_FALSE;
4190   aij->free_ij      = PETSC_FALSE;
4191 
4192   for (ii=0; ii<m; ii++) {
4193     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
4194 #if defined(PETSC_USE_DEBUG)
4195     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]);
4196     for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4197       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);
4198       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);
4199     }
4200 #endif
4201   }
4202 #if defined(PETSC_USE_DEBUG)
4203   for (ii=0; ii<aij->i[m]; ii++) {
4204     if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
4205     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]);
4206   }
4207 #endif
4208 
4209   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4210   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4211   PetscFunctionReturn(0);
4212 }
4213 #undef __FUNCT__
4214 #define __FUNCT__ "MatCreateSeqAIJFromTriple"
4215 /*@C
4216      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
4217               provided by the user.
4218 
4219       Collective on MPI_Comm
4220 
4221    Input Parameters:
4222 +   comm - must be an MPI communicator of size 1
4223 .   m   - number of rows
4224 .   n   - number of columns
4225 .   i   - row indices
4226 .   j   - column indices
4227 .   a   - matrix values
4228 .   nz  - number of nonzeros
4229 -   idx - 0 or 1 based
4230 
4231    Output Parameter:
4232 .   mat - the matrix
4233 
4234    Level: intermediate
4235 
4236    Notes:
4237        The i and j indices are 0 based
4238 
4239        The format which is used for the sparse matrix input, is equivalent to a
4240     row-major ordering.. i.e for the following matrix, the input data expected is
4241     as shown:
4242 
4243         1 0 0
4244         2 0 3
4245         4 5 6
4246 
4247         i =  {0,1,1,2,2,2}
4248         j =  {0,0,2,0,1,2}
4249         v =  {1,2,3,4,5,6}
4250 
4251 
4252 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
4253 
4254 @*/
4255 PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat,PetscInt nz,PetscBool idx)
4256 {
4257   PetscErrorCode ierr;
4258   PetscInt       ii, *nnz, one = 1,row,col;
4259 
4260 
4261   PetscFunctionBegin;
4262   ierr = PetscMalloc(m*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
4263   ierr = PetscMemzero(nnz,m*sizeof(PetscInt));CHKERRQ(ierr);
4264   for (ii = 0; ii < nz; ii++){
4265     nnz[i[ii]] += 1;
4266   }
4267   //ierr = MatSeqAIJCreate(comm,m,n,0,nnz,mat);CHKERRQ(ierr);
4268   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
4269   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
4270   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
4271   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
4272   for (ii = 0; ii < nz; ii++){
4273     if (idx){
4274       row = i[ii] - 1;
4275       col = j[ii] - 1;
4276     } else {
4277       row = i[ii];
4278       col = j[ii];
4279     }
4280     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
4281   }
4282   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4283   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4284   ierr = PetscFree(nnz);CHKERRQ(ierr);
4285   PetscFunctionReturn(0);
4286 }
4287 
4288 #undef __FUNCT__
4289 #define __FUNCT__ "MatSetColoring_SeqAIJ"
4290 PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring)
4291 {
4292   PetscErrorCode ierr;
4293   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4294 
4295   PetscFunctionBegin;
4296   if (coloring->ctype == IS_COLORING_GLOBAL) {
4297     ierr        = ISColoringReference(coloring);CHKERRQ(ierr);
4298     a->coloring = coloring;
4299   } else if (coloring->ctype == IS_COLORING_GHOSTED) {
4300     PetscInt             i,*larray;
4301     ISColoring      ocoloring;
4302     ISColoringValue *colors;
4303 
4304     /* set coloring for diagonal portion */
4305     ierr = PetscMalloc(A->cmap->n*sizeof(PetscInt),&larray);CHKERRQ(ierr);
4306     for (i=0; i<A->cmap->n; i++) {
4307       larray[i] = i;
4308     }
4309     ierr = ISGlobalToLocalMappingApply(A->cmap->mapping,IS_GTOLM_MASK,A->cmap->n,larray,PETSC_NULL,larray);CHKERRQ(ierr);
4310     ierr = PetscMalloc(A->cmap->n*sizeof(ISColoringValue),&colors);CHKERRQ(ierr);
4311     for (i=0; i<A->cmap->n; i++) {
4312       colors[i] = coloring->colors[larray[i]];
4313     }
4314     ierr = PetscFree(larray);CHKERRQ(ierr);
4315     ierr = ISColoringCreate(PETSC_COMM_SELF,coloring->n,A->cmap->n,colors,&ocoloring);CHKERRQ(ierr);
4316     a->coloring = ocoloring;
4317   }
4318   PetscFunctionReturn(0);
4319 }
4320 
4321 #if defined(PETSC_HAVE_ADIC)
4322 EXTERN_C_BEGIN
4323 #include <adic/ad_utils.h>
4324 EXTERN_C_END
4325 
4326 #undef __FUNCT__
4327 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ"
4328 PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
4329 {
4330   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
4331   PetscInt        m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j,nlen;
4332   PetscScalar     *v = a->a,*values = ((PetscScalar*)advalues)+1;
4333   ISColoringValue *color;
4334 
4335   PetscFunctionBegin;
4336   if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
4337   nlen  = PetscADGetDerivTypeSize()/sizeof(PetscScalar);
4338   color = a->coloring->colors;
4339   /* loop over rows */
4340   for (i=0; i<m; i++) {
4341     nz = ii[i+1] - ii[i];
4342     /* loop over columns putting computed value into matrix */
4343     for (j=0; j<nz; j++) {
4344       *v++ = values[color[*jj++]];
4345     }
4346     values += nlen; /* jump to next row of derivatives */
4347   }
4348   PetscFunctionReturn(0);
4349 }
4350 #endif
4351 
4352 #undef __FUNCT__
4353 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ"
4354 PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues)
4355 {
4356   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
4357   PetscInt         m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j;
4358   MatScalar       *v = a->a;
4359   PetscScalar     *values = (PetscScalar *)advalues;
4360   ISColoringValue *color;
4361 
4362   PetscFunctionBegin;
4363   if (!a->coloring) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
4364   color = a->coloring->colors;
4365   /* loop over rows */
4366   for (i=0; i<m; i++) {
4367     nz = ii[i+1] - ii[i];
4368     /* loop over columns putting computed value into matrix */
4369     for (j=0; j<nz; j++) {
4370       *v++ = values[color[*jj++]];
4371     }
4372     values += nl; /* jump to next row of derivatives */
4373   }
4374   PetscFunctionReturn(0);
4375 }
4376 
4377 /*
4378     Special version for direct calls from Fortran
4379 */
4380 #include <private/fortranimpl.h>
4381 #if defined(PETSC_HAVE_FORTRAN_CAPS)
4382 #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
4383 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
4384 #define matsetvaluesseqaij_ matsetvaluesseqaij
4385 #endif
4386 
4387 /* Change these macros so can be used in void function */
4388 #undef CHKERRQ
4389 #define CHKERRQ(ierr) CHKERRABORT(((PetscObject)A)->comm,ierr)
4390 #undef SETERRQ2
4391 #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
4392 
4393 EXTERN_C_BEGIN
4394 #undef __FUNCT__
4395 #define __FUNCT__ "matsetvaluesseqaij_"
4396 void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
4397 {
4398   Mat            A = *AA;
4399   PetscInt       m = *mm, n = *nn;
4400   InsertMode     is = *isis;
4401   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4402   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
4403   PetscInt       *imax,*ai,*ailen;
4404   PetscErrorCode ierr;
4405   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
4406   MatScalar      *ap,value,*aa;
4407   PetscBool      ignorezeroentries = a->ignorezeroentries;
4408   PetscBool      roworiented = a->roworiented;
4409 
4410   PetscFunctionBegin;
4411   ierr = MatPreallocated(A);CHKERRQ(ierr);
4412   imax = a->imax;
4413   ai = a->i;
4414   ailen = a->ilen;
4415   aj = a->j;
4416   aa = a->a;
4417 
4418   for (k=0; k<m; k++) { /* loop over added rows */
4419     row  = im[k];
4420     if (row < 0) continue;
4421 #if defined(PETSC_USE_DEBUG)
4422     if (row >= A->rmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
4423 #endif
4424     rp   = aj + ai[row]; ap = aa + ai[row];
4425     rmax = imax[row]; nrow = ailen[row];
4426     low  = 0;
4427     high = nrow;
4428     for (l=0; l<n; l++) { /* loop over added columns */
4429       if (in[l] < 0) continue;
4430 #if defined(PETSC_USE_DEBUG)
4431       if (in[l] >= A->cmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
4432 #endif
4433       col = in[l];
4434       if (roworiented) {
4435         value = v[l + k*n];
4436       } else {
4437         value = v[k + l*m];
4438       }
4439       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
4440 
4441       if (col <= lastcol) low = 0; else high = nrow;
4442       lastcol = col;
4443       while (high-low > 5) {
4444         t = (low+high)/2;
4445         if (rp[t] > col) high = t;
4446         else             low  = t;
4447       }
4448       for (i=low; i<high; i++) {
4449         if (rp[i] > col) break;
4450         if (rp[i] == col) {
4451           if (is == ADD_VALUES) ap[i] += value;
4452           else                  ap[i] = value;
4453           goto noinsert;
4454         }
4455       }
4456       if (value == 0.0 && ignorezeroentries) goto noinsert;
4457       if (nonew == 1) goto noinsert;
4458       if (nonew == -1) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
4459       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
4460       N = nrow++ - 1; a->nz++; high++;
4461       /* shift up all the later entries in this row */
4462       for (ii=N; ii>=i; ii--) {
4463         rp[ii+1] = rp[ii];
4464         ap[ii+1] = ap[ii];
4465       }
4466       rp[i] = col;
4467       ap[i] = value;
4468       noinsert:;
4469       low = i + 1;
4470     }
4471     ailen[row] = nrow;
4472   }
4473   A->same_nonzero = PETSC_FALSE;
4474   PetscFunctionReturnVoid();
4475 }
4476 EXTERN_C_END
4477 
4478