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