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