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