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