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