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