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