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