xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 8ebe3e4e9e00d86ece2e9fcd0cc84910b0ad437c) !
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     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRQ2(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       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRQ2(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       if (nonew == -1) SETERRQ2(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   if (A->was_assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
529   if (m*n+a->nz > a->maxnz) SETERRQ1(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     if (PetscUnlikelyDebug(n > a->imax[row])) SETERRQ1(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;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %" PetscInt_FMT,row); */
662     if (row >= A->rmap->n) SETERRQ2(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;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %" PetscInt_FMT,in[l]); */
667       if (in[l] >= A->cmap->n) SETERRQ2(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   if (fshift && a->nounused == -1) SETERRQ3(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 = PetscInfo4(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 = PetscInfo1(A,"Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n",a->reallocs);CHKERRQ(ierr);
1194   ierr = PetscInfo1(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 = PetscInfo1(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     SETERRQ1(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   if (n != A->rmap->n) SETERRQ(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 = PetscInfo1(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   if (ncnt != n) SETERRQ2(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 = PetscInfo1(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 SETERRQ1(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   if (flag == SOR_APPLY_LOWER) SETERRQ(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       if (rows[i] < 0 || rows[i] > m) SETERRQ1(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       if (rows[i] < 0 || rows[i] > m) SETERRQ1(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         if (a->diag[d] >= a->i[d+1]) SETERRQ1(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         if (rows[i] < 0 || rows[i] > m) SETERRQ1(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         if (rows[i] < 0 || rows[i] > m) SETERRQ1(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     if (rows[i] < 0 || rows[i] > m) SETERRQ1(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         if (a->nonew && rows[i] >= d) SETERRQ2(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     if (m != A->rmap->n) SETERRQ(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     if (n != A->cmap->n) SETERRQ(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       if (n_rows != nrows || n_cols != ncols) SETERRQ(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       if (PetscUnlikelyDebug(icol[i] >= oldcols)) SETERRQ3(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       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(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       if (!equal) SETERRQ(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   if (info->levels != 0) SETERRQ(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   if (ov < 0) SETERRQ(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     if (a->i[A->rmap->n] != b->i[B->rmap->n]) SETERRQ2(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 && x->nz == y->nz) {
3138     PetscBool e;
3139     ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
3140     if (e) {
3141       ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
3142       if (e) {
3143         str = SAME_NONZERO_PATTERN;
3144       }
3145     }
3146   }
3147   if (str == SAME_NONZERO_PATTERN) {
3148     const PetscScalar *xa;
3149     PetscScalar       *ya,alpha = a;
3150     PetscBLASInt      one = 1,bnz;
3151 
3152     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
3153     ierr = MatSeqAIJGetArray(Y,&ya);CHKERRQ(ierr);
3154     ierr = MatSeqAIJGetArrayRead(X,&xa);CHKERRQ(ierr);
3155     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one));
3156     ierr = MatSeqAIJRestoreArrayRead(X,&xa);CHKERRQ(ierr);
3157     ierr = MatSeqAIJRestoreArray(Y,&ya);CHKERRQ(ierr);
3158     ierr = PetscLogFlops(2.0*bnz);CHKERRQ(ierr);
3159     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3160     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
3161   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3162     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3163   } else {
3164     Mat      B;
3165     PetscInt *nnz;
3166     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3167     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3168     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
3169     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
3170     ierr = MatSetType(B,((PetscObject)Y)->type_name);CHKERRQ(ierr);
3171     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3172     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3173     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
3174     ierr = MatHeaderMerge(Y,&B);CHKERRQ(ierr);
3175     ierr = PetscFree(nnz);CHKERRQ(ierr);
3176   }
3177   PetscFunctionReturn(0);
3178 }
3179 
3180 PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
3181 {
3182 #if defined(PETSC_USE_COMPLEX)
3183   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3184   PetscInt       i,nz;
3185   PetscScalar    *a;
3186   PetscErrorCode ierr;
3187 
3188   PetscFunctionBegin;
3189   nz = aij->nz;
3190   ierr = MatSeqAIJGetArray(mat,&a);CHKERRQ(ierr);
3191   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
3192   ierr = MatSeqAIJRestoreArray(mat,&a);CHKERRQ(ierr);
3193 #else
3194   PetscFunctionBegin;
3195 #endif
3196   PetscFunctionReturn(0);
3197 }
3198 
3199 PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3200 {
3201   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3202   PetscErrorCode  ierr;
3203   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3204   PetscReal       atmp;
3205   PetscScalar     *x;
3206   const MatScalar *aa,*av;
3207 
3208   PetscFunctionBegin;
3209   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3210   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3211   aa = av;
3212   ai = a->i;
3213   aj = a->j;
3214 
3215   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3216   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3217   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3218   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3219   for (i=0; i<m; i++) {
3220     ncols = ai[1] - ai[0]; ai++;
3221     for (j=0; j<ncols; j++) {
3222       atmp = PetscAbsScalar(*aa);
3223       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3224       aa++; aj++;
3225     }
3226   }
3227   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3228   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3229   PetscFunctionReturn(0);
3230 }
3231 
3232 PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3233 {
3234   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3235   PetscErrorCode  ierr;
3236   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3237   PetscScalar     *x;
3238   const MatScalar *aa,*av;
3239 
3240   PetscFunctionBegin;
3241   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3242   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3243   aa = av;
3244   ai = a->i;
3245   aj = a->j;
3246 
3247   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3248   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3249   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3250   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3251   for (i=0; i<m; i++) {
3252     ncols = ai[1] - ai[0]; ai++;
3253     if (ncols == A->cmap->n) { /* row is dense */
3254       x[i] = *aa; if (idx) idx[i] = 0;
3255     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3256       x[i] = 0.0;
3257       if (idx) {
3258         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3259           if (aj[j] > j) {
3260             idx[i] = j;
3261             break;
3262           }
3263         }
3264         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3265         if (j==ncols && j < A->cmap->n) idx[i] = j;
3266       }
3267     }
3268     for (j=0; j<ncols; j++) {
3269       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3270       aa++; aj++;
3271     }
3272   }
3273   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3274   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3275   PetscFunctionReturn(0);
3276 }
3277 
3278 PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3279 {
3280   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3281   PetscErrorCode  ierr;
3282   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3283   PetscScalar     *x;
3284   const MatScalar *aa,*av;
3285 
3286   PetscFunctionBegin;
3287   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3288   aa = av;
3289   ai = a->i;
3290   aj = a->j;
3291 
3292   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3293   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3294   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3295   if (n != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n);
3296   for (i=0; i<m; i++) {
3297     ncols = ai[1] - ai[0]; ai++;
3298     if (ncols == A->cmap->n) { /* row is dense */
3299       x[i] = *aa; if (idx) idx[i] = 0;
3300     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3301       x[i] = 0.0;
3302       if (idx) {   /* find first implicit 0.0 in the row */
3303         for (j=0; j<ncols; j++) {
3304           if (aj[j] > j) {
3305             idx[i] = j;
3306             break;
3307           }
3308         }
3309         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3310         if (j==ncols && j < A->cmap->n) idx[i] = j;
3311       }
3312     }
3313     for (j=0; j<ncols; j++) {
3314       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3315       aa++; aj++;
3316     }
3317   }
3318   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3319   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3320   PetscFunctionReturn(0);
3321 }
3322 
3323 PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3324 {
3325   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3326   PetscErrorCode  ierr;
3327   PetscInt        i,j,m = A->rmap->n,ncols,n;
3328   const PetscInt  *ai,*aj;
3329   PetscScalar     *x;
3330   const MatScalar *aa,*av;
3331 
3332   PetscFunctionBegin;
3333   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3334   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3335   aa = av;
3336   ai = a->i;
3337   aj = a->j;
3338 
3339   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3340   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3341   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3342   if (n != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3343   for (i=0; i<m; i++) {
3344     ncols = ai[1] - ai[0]; ai++;
3345     if (ncols == A->cmap->n) { /* row is dense */
3346       x[i] = *aa; if (idx) idx[i] = 0;
3347     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3348       x[i] = 0.0;
3349       if (idx) {   /* find first implicit 0.0 in the row */
3350         for (j=0; j<ncols; j++) {
3351           if (aj[j] > j) {
3352             idx[i] = j;
3353             break;
3354           }
3355         }
3356         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3357         if (j==ncols && j < A->cmap->n) idx[i] = j;
3358       }
3359     }
3360     for (j=0; j<ncols; j++) {
3361       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3362       aa++; aj++;
3363     }
3364   }
3365   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3366   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3367   PetscFunctionReturn(0);
3368 }
3369 
3370 PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3371 {
3372   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3373   PetscErrorCode  ierr;
3374   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3375   MatScalar       *diag,work[25],*v_work;
3376   const PetscReal shift = 0.0;
3377   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3378 
3379   PetscFunctionBegin;
3380   allowzeropivot = PetscNot(A->erroriffailure);
3381   if (a->ibdiagvalid) {
3382     if (values) *values = a->ibdiag;
3383     PetscFunctionReturn(0);
3384   }
3385   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3386   if (!a->ibdiag) {
3387     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
3388     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3389   }
3390   diag = a->ibdiag;
3391   if (values) *values = a->ibdiag;
3392   /* factor and invert each block */
3393   switch (bs) {
3394   case 1:
3395     for (i=0; i<mbs; i++) {
3396       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3397       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3398         if (allowzeropivot) {
3399           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3400           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
3401           A->factorerror_zeropivot_row   = i;
3402           ierr = PetscInfo3(A,"Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
3403         } else SETERRQ3(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);
3404       }
3405       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3406     }
3407     break;
3408   case 2:
3409     for (i=0; i<mbs; i++) {
3410       ij[0] = 2*i; ij[1] = 2*i + 1;
3411       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3412       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
3413       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3414       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3415       diag += 4;
3416     }
3417     break;
3418   case 3:
3419     for (i=0; i<mbs; i++) {
3420       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3421       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3422       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
3423       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3424       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3425       diag += 9;
3426     }
3427     break;
3428   case 4:
3429     for (i=0; i<mbs; i++) {
3430       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3431       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3432       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
3433       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3434       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3435       diag += 16;
3436     }
3437     break;
3438   case 5:
3439     for (i=0; i<mbs; i++) {
3440       ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4;
3441       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3442       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
3443       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3444       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3445       diag += 25;
3446     }
3447     break;
3448   case 6:
3449     for (i=0; i<mbs; i++) {
3450       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;
3451       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3452       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
3453       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3454       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3455       diag += 36;
3456     }
3457     break;
3458   case 7:
3459     for (i=0; i<mbs; i++) {
3460       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;
3461       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3462       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
3463       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3464       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3465       diag += 49;
3466     }
3467     break;
3468   default:
3469     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3470     for (i=0; i<mbs; i++) {
3471       for (j=0; j<bs; j++) {
3472         IJ[j] = bs*i + j;
3473       }
3474       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
3475       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
3476       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
3477       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3478       diag += bs2;
3479     }
3480     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3481   }
3482   a->ibdiagvalid = PETSC_TRUE;
3483   PetscFunctionReturn(0);
3484 }
3485 
3486 static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
3487 {
3488   PetscErrorCode ierr;
3489   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3490   PetscScalar    a,*aa;
3491   PetscInt       m,n,i,j,col;
3492 
3493   PetscFunctionBegin;
3494   if (!x->assembled) {
3495     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3496     for (i=0; i<m; i++) {
3497       for (j=0; j<aij->imax[i]; j++) {
3498         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3499         col  = (PetscInt)(n*PetscRealPart(a));
3500         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3501       }
3502     }
3503   } else {
3504     ierr = MatSeqAIJGetArrayWrite(x,&aa);CHKERRQ(ierr);
3505     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aa+i);CHKERRQ(ierr);}
3506     ierr = MatSeqAIJRestoreArrayWrite(x,&aa);CHKERRQ(ierr);
3507   }
3508   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3509   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3510   PetscFunctionReturn(0);
3511 }
3512 
3513 /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3514 PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3515 {
3516   PetscErrorCode ierr;
3517   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3518   PetscScalar    a;
3519   PetscInt       m,n,i,j,col,nskip;
3520 
3521   PetscFunctionBegin;
3522   nskip = high - low;
3523   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3524   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3525   for (i=0; i<m; i++) {
3526     for (j=0; j<aij->imax[i]; j++) {
3527       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3528       col  = (PetscInt)(n*PetscRealPart(a));
3529       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3530       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3531     }
3532   }
3533   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3534   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3535   PetscFunctionReturn(0);
3536 }
3537 
3538 /* -------------------------------------------------------------------*/
3539 static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3540                                         MatGetRow_SeqAIJ,
3541                                         MatRestoreRow_SeqAIJ,
3542                                         MatMult_SeqAIJ,
3543                                 /*  4*/ MatMultAdd_SeqAIJ,
3544                                         MatMultTranspose_SeqAIJ,
3545                                         MatMultTransposeAdd_SeqAIJ,
3546                                         NULL,
3547                                         NULL,
3548                                         NULL,
3549                                 /* 10*/ NULL,
3550                                         MatLUFactor_SeqAIJ,
3551                                         NULL,
3552                                         MatSOR_SeqAIJ,
3553                                         MatTranspose_SeqAIJ,
3554                                 /*1 5*/ MatGetInfo_SeqAIJ,
3555                                         MatEqual_SeqAIJ,
3556                                         MatGetDiagonal_SeqAIJ,
3557                                         MatDiagonalScale_SeqAIJ,
3558                                         MatNorm_SeqAIJ,
3559                                 /* 20*/ NULL,
3560                                         MatAssemblyEnd_SeqAIJ,
3561                                         MatSetOption_SeqAIJ,
3562                                         MatZeroEntries_SeqAIJ,
3563                                 /* 24*/ MatZeroRows_SeqAIJ,
3564                                         NULL,
3565                                         NULL,
3566                                         NULL,
3567                                         NULL,
3568                                 /* 29*/ MatSetUp_SeqAIJ,
3569                                         NULL,
3570                                         NULL,
3571                                         NULL,
3572                                         NULL,
3573                                 /* 34*/ MatDuplicate_SeqAIJ,
3574                                         NULL,
3575                                         NULL,
3576                                         MatILUFactor_SeqAIJ,
3577                                         NULL,
3578                                 /* 39*/ MatAXPY_SeqAIJ,
3579                                         MatCreateSubMatrices_SeqAIJ,
3580                                         MatIncreaseOverlap_SeqAIJ,
3581                                         MatGetValues_SeqAIJ,
3582                                         MatCopy_SeqAIJ,
3583                                 /* 44*/ MatGetRowMax_SeqAIJ,
3584                                         MatScale_SeqAIJ,
3585                                         MatShift_SeqAIJ,
3586                                         MatDiagonalSet_SeqAIJ,
3587                                         MatZeroRowsColumns_SeqAIJ,
3588                                 /* 49*/ MatSetRandom_SeqAIJ,
3589                                         MatGetRowIJ_SeqAIJ,
3590                                         MatRestoreRowIJ_SeqAIJ,
3591                                         MatGetColumnIJ_SeqAIJ,
3592                                         MatRestoreColumnIJ_SeqAIJ,
3593                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3594                                         NULL,
3595                                         NULL,
3596                                         MatPermute_SeqAIJ,
3597                                         NULL,
3598                                 /* 59*/ NULL,
3599                                         MatDestroy_SeqAIJ,
3600                                         MatView_SeqAIJ,
3601                                         NULL,
3602                                         NULL,
3603                                 /* 64*/ NULL,
3604                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3605                                         NULL,
3606                                         NULL,
3607                                         NULL,
3608                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3609                                         MatGetRowMinAbs_SeqAIJ,
3610                                         NULL,
3611                                         NULL,
3612                                         NULL,
3613                                 /* 74*/ NULL,
3614                                         MatFDColoringApply_AIJ,
3615                                         NULL,
3616                                         NULL,
3617                                         NULL,
3618                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3619                                         NULL,
3620                                         NULL,
3621                                         NULL,
3622                                         MatLoad_SeqAIJ,
3623                                 /* 84*/ MatIsSymmetric_SeqAIJ,
3624                                         MatIsHermitian_SeqAIJ,
3625                                         NULL,
3626                                         NULL,
3627                                         NULL,
3628                                 /* 89*/ NULL,
3629                                         NULL,
3630                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3631                                         NULL,
3632                                         NULL,
3633                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3634                                         NULL,
3635                                         NULL,
3636                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3637                                         NULL,
3638                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3639                                         NULL,
3640                                         NULL,
3641                                         MatConjugate_SeqAIJ,
3642                                         NULL,
3643                                 /*104*/ MatSetValuesRow_SeqAIJ,
3644                                         MatRealPart_SeqAIJ,
3645                                         MatImaginaryPart_SeqAIJ,
3646                                         NULL,
3647                                         NULL,
3648                                 /*109*/ MatMatSolve_SeqAIJ,
3649                                         NULL,
3650                                         MatGetRowMin_SeqAIJ,
3651                                         NULL,
3652                                         MatMissingDiagonal_SeqAIJ,
3653                                 /*114*/ NULL,
3654                                         NULL,
3655                                         NULL,
3656                                         NULL,
3657                                         NULL,
3658                                 /*119*/ NULL,
3659                                         NULL,
3660                                         NULL,
3661                                         NULL,
3662                                         MatGetMultiProcBlock_SeqAIJ,
3663                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3664                                         MatGetColumnReductions_SeqAIJ,
3665                                         MatInvertBlockDiagonal_SeqAIJ,
3666                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3667                                         NULL,
3668                                 /*129*/ NULL,
3669                                         NULL,
3670                                         NULL,
3671                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3672                                         MatTransposeColoringCreate_SeqAIJ,
3673                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
3674                                         MatTransColoringApplyDenToSp_SeqAIJ,
3675                                         NULL,
3676                                         NULL,
3677                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3678                                  /*139*/NULL,
3679                                         NULL,
3680                                         NULL,
3681                                         MatFDColoringSetUp_SeqXAIJ,
3682                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
3683                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
3684                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3685                                         NULL,
3686                                         NULL
3687 };
3688 
3689 PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3690 {
3691   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
3692   PetscInt   i,nz,n;
3693 
3694   PetscFunctionBegin;
3695   nz = aij->maxnz;
3696   n  = mat->rmap->n;
3697   for (i=0; i<nz; i++) {
3698     aij->j[i] = indices[i];
3699   }
3700   aij->nz = nz;
3701   for (i=0; i<n; i++) {
3702     aij->ilen[i] = aij->imax[i];
3703   }
3704   PetscFunctionReturn(0);
3705 }
3706 
3707 /*
3708  * Given a sparse matrix with global column indices, compact it by using a local column space.
3709  * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3710  */
3711 PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3712 {
3713   Mat_SeqAIJ         *aij = (Mat_SeqAIJ*)mat->data;
3714   PetscTable         gid1_lid1;
3715   PetscTablePosition tpos;
3716   PetscInt           gid,lid,i,ec,nz = aij->nz;
3717   PetscInt           *garray,*jj = aij->j;
3718   PetscErrorCode     ierr;
3719 
3720   PetscFunctionBegin;
3721   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3722   PetscValidPointer(mapping,2);
3723   /* use a table */
3724   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3725   ec = 0;
3726   for (i=0; i<nz; i++) {
3727     PetscInt data,gid1 = jj[i] + 1;
3728     ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3729     if (!data) {
3730       /* one based table */
3731       ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3732     }
3733   }
3734   /* form array of columns we need */
3735   ierr = PetscMalloc1(ec,&garray);CHKERRQ(ierr);
3736   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3737   while (tpos) {
3738     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3739     gid--;
3740     lid--;
3741     garray[lid] = gid;
3742   }
3743   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3744   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3745   for (i=0; i<ec; i++) {
3746     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3747   }
3748   /* compact out the extra columns in B */
3749   for (i=0; i<nz; i++) {
3750     PetscInt gid1 = jj[i] + 1;
3751     ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3752     lid--;
3753     jj[i] = lid;
3754   }
3755   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3756   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
3757   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3758   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3759   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3760   PetscFunctionReturn(0);
3761 }
3762 
3763 /*@
3764     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3765        in the matrix.
3766 
3767   Input Parameters:
3768 +  mat - the SeqAIJ matrix
3769 -  indices - the column indices
3770 
3771   Level: advanced
3772 
3773   Notes:
3774     This can be called if you have precomputed the nonzero structure of the
3775   matrix and want to provide it to the matrix object to improve the performance
3776   of the MatSetValues() operation.
3777 
3778     You MUST have set the correct numbers of nonzeros per row in the call to
3779   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3780 
3781     MUST be called before any calls to MatSetValues();
3782 
3783     The indices should start with zero, not one.
3784 
3785 @*/
3786 PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3787 {
3788   PetscErrorCode ierr;
3789 
3790   PetscFunctionBegin;
3791   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3792   PetscValidPointer(indices,2);
3793   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3794   PetscFunctionReturn(0);
3795 }
3796 
3797 /* ----------------------------------------------------------------------------------------*/
3798 
3799 PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3800 {
3801   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3802   PetscErrorCode ierr;
3803   size_t         nz = aij->i[mat->rmap->n];
3804 
3805   PetscFunctionBegin;
3806   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3807 
3808   /* allocate space for values if not already there */
3809   if (!aij->saved_values) {
3810     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
3811     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3812   }
3813 
3814   /* copy values over */
3815   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3816   PetscFunctionReturn(0);
3817 }
3818 
3819 /*@
3820     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3821        example, reuse of the linear part of a Jacobian, while recomputing the
3822        nonlinear portion.
3823 
3824    Collect on Mat
3825 
3826   Input Parameters:
3827 .  mat - the matrix (currently only AIJ matrices support this option)
3828 
3829   Level: advanced
3830 
3831   Common Usage, with SNESSolve():
3832 $    Create Jacobian matrix
3833 $    Set linear terms into matrix
3834 $    Apply boundary conditions to matrix, at this time matrix must have
3835 $      final nonzero structure (i.e. setting the nonlinear terms and applying
3836 $      boundary conditions again will not change the nonzero structure
3837 $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3838 $    ierr = MatStoreValues(mat);
3839 $    Call SNESSetJacobian() with matrix
3840 $    In your Jacobian routine
3841 $      ierr = MatRetrieveValues(mat);
3842 $      Set nonlinear terms in matrix
3843 
3844   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3845 $    // build linear portion of Jacobian
3846 $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3847 $    ierr = MatStoreValues(mat);
3848 $    loop over nonlinear iterations
3849 $       ierr = MatRetrieveValues(mat);
3850 $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3851 $       // call MatAssemblyBegin/End() on matrix
3852 $       Solve linear system with Jacobian
3853 $    endloop
3854 
3855   Notes:
3856     Matrix must already be assemblied before calling this routine
3857     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3858     calling this routine.
3859 
3860     When this is called multiple times it overwrites the previous set of stored values
3861     and does not allocated additional space.
3862 
3863 .seealso: MatRetrieveValues()
3864 
3865 @*/
3866 PetscErrorCode  MatStoreValues(Mat mat)
3867 {
3868   PetscErrorCode ierr;
3869 
3870   PetscFunctionBegin;
3871   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3872   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3873   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3874   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3875   PetscFunctionReturn(0);
3876 }
3877 
3878 PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3879 {
3880   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3881   PetscErrorCode ierr;
3882   PetscInt       nz = aij->i[mat->rmap->n];
3883 
3884   PetscFunctionBegin;
3885   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3886   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3887   /* copy values over */
3888   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3889   PetscFunctionReturn(0);
3890 }
3891 
3892 /*@
3893     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3894        example, reuse of the linear part of a Jacobian, while recomputing the
3895        nonlinear portion.
3896 
3897    Collect on Mat
3898 
3899   Input Parameters:
3900 .  mat - the matrix (currently only AIJ matrices support this option)
3901 
3902   Level: advanced
3903 
3904 .seealso: MatStoreValues()
3905 
3906 @*/
3907 PetscErrorCode  MatRetrieveValues(Mat mat)
3908 {
3909   PetscErrorCode ierr;
3910 
3911   PetscFunctionBegin;
3912   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3913   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3914   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3915   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3916   PetscFunctionReturn(0);
3917 }
3918 
3919 /* --------------------------------------------------------------------------------*/
3920 /*@C
3921    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
3922    (the default parallel PETSc format).  For good matrix assembly performance
3923    the user should preallocate the matrix storage by setting the parameter nz
3924    (or the array nnz).  By setting these parameters accurately, performance
3925    during matrix assembly can be increased by more than a factor of 50.
3926 
3927    Collective
3928 
3929    Input Parameters:
3930 +  comm - MPI communicator, set to PETSC_COMM_SELF
3931 .  m - number of rows
3932 .  n - number of columns
3933 .  nz - number of nonzeros per row (same for all rows)
3934 -  nnz - array containing the number of nonzeros in the various rows
3935          (possibly different for each row) or NULL
3936 
3937    Output Parameter:
3938 .  A - the matrix
3939 
3940    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3941    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3942    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3943 
3944    Notes:
3945    If nnz is given then nz is ignored
3946 
3947    The AIJ format (also called the Yale sparse matrix format or
3948    compressed row storage), is fully compatible with standard Fortran 77
3949    storage.  That is, the stored row and column indices can begin at
3950    either one (as in Fortran) or zero.  See the users' manual for details.
3951 
3952    Specify the preallocated storage with either nz or nnz (not both).
3953    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
3954    allocation.  For large problems you MUST preallocate memory or you
3955    will get TERRIBLE performance, see the users' manual chapter on matrices.
3956 
3957    By default, this format uses inodes (identical nodes) when possible, to
3958    improve numerical efficiency of matrix-vector products and solves. We
3959    search for consecutive rows with the same nonzero structure, thereby
3960    reusing matrix information to achieve increased efficiency.
3961 
3962    Options Database Keys:
3963 +  -mat_no_inode  - Do not use inodes
3964 -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3965 
3966    Level: intermediate
3967 
3968 .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
3969 
3970 @*/
3971 PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
3972 {
3973   PetscErrorCode ierr;
3974 
3975   PetscFunctionBegin;
3976   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3977   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3978   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
3979   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
3980   PetscFunctionReturn(0);
3981 }
3982 
3983 /*@C
3984    MatSeqAIJSetPreallocation - For good matrix assembly performance
3985    the user should preallocate the matrix storage by setting the parameter nz
3986    (or the array nnz).  By setting these parameters accurately, performance
3987    during matrix assembly can be increased by more than a factor of 50.
3988 
3989    Collective
3990 
3991    Input Parameters:
3992 +  B - The matrix
3993 .  nz - number of nonzeros per row (same for all rows)
3994 -  nnz - array containing the number of nonzeros in the various rows
3995          (possibly different for each row) or NULL
3996 
3997    Notes:
3998      If nnz is given then nz is ignored
3999 
4000     The AIJ format (also called the Yale sparse matrix format or
4001    compressed row storage), is fully compatible with standard Fortran 77
4002    storage.  That is, the stored row and column indices can begin at
4003    either one (as in Fortran) or zero.  See the users' manual for details.
4004 
4005    Specify the preallocated storage with either nz or nnz (not both).
4006    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
4007    allocation.  For large problems you MUST preallocate memory or you
4008    will get TERRIBLE performance, see the users' manual chapter on matrices.
4009 
4010    You can call MatGetInfo() to get information on how effective the preallocation was;
4011    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
4012    You can also run with the option -info and look for messages with the string
4013    malloc in them to see if additional memory allocation was needed.
4014 
4015    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
4016    entries or columns indices
4017 
4018    By default, this format uses inodes (identical nodes) when possible, to
4019    improve numerical efficiency of matrix-vector products and solves. We
4020    search for consecutive rows with the same nonzero structure, thereby
4021    reusing matrix information to achieve increased efficiency.
4022 
4023    Options Database Keys:
4024 +  -mat_no_inode  - Do not use inodes
4025 -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
4026 
4027    Level: intermediate
4028 
4029 .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
4030           MatSeqAIJSetTotalPreallocation()
4031 
4032 @*/
4033 PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
4034 {
4035   PetscErrorCode ierr;
4036 
4037   PetscFunctionBegin;
4038   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
4039   PetscValidType(B,1);
4040   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
4041   PetscFunctionReturn(0);
4042 }
4043 
4044 PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4045 {
4046   Mat_SeqAIJ     *b;
4047   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
4048   PetscErrorCode ierr;
4049   PetscInt       i;
4050 
4051   PetscFunctionBegin;
4052   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4053   if (nz == MAT_SKIP_ALLOCATION) {
4054     skipallocation = PETSC_TRUE;
4055     nz             = 0;
4056   }
4057   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4058   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4059 
4060   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
4061   if (PetscUnlikely(nz < 0)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %" PetscInt_FMT,nz);
4062   if (PetscUnlikelyDebug(nnz)) {
4063     for (i=0; i<B->rmap->n; i++) {
4064       if (nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %" PetscInt_FMT " value %" PetscInt_FMT,i,nnz[i]);
4065       if (nnz[i] > B->cmap->n) SETERRQ3(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);
4066     }
4067   }
4068 
4069   B->preallocated = PETSC_TRUE;
4070 
4071   b = (Mat_SeqAIJ*)B->data;
4072 
4073   if (!skipallocation) {
4074     if (!b->imax) {
4075       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4076       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4077     }
4078     if (!b->ilen) {
4079       /* b->ilen will count nonzeros in each row so far. */
4080       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4081       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4082     } else {
4083       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4084     }
4085     if (!b->ipre) {
4086       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4087       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4088     }
4089     if (!nnz) {
4090       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4091       else if (nz < 0) nz = 1;
4092       nz = PetscMin(nz,B->cmap->n);
4093       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4094       nz = nz*B->rmap->n;
4095     } else {
4096       PetscInt64 nz64 = 0;
4097       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4098       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4099     }
4100 
4101     /* allocate the matrix space */
4102     /* FIXME: should B's old memory be unlogged? */
4103     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4104     if (B->structure_only) {
4105       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
4106       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4107       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4108     } else {
4109       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
4110       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4111     }
4112     b->i[0] = 0;
4113     for (i=1; i<B->rmap->n+1; i++) {
4114       b->i[i] = b->i[i-1] + b->imax[i-1];
4115     }
4116     if (B->structure_only) {
4117       b->singlemalloc = PETSC_FALSE;
4118       b->free_a       = PETSC_FALSE;
4119     } else {
4120       b->singlemalloc = PETSC_TRUE;
4121       b->free_a       = PETSC_TRUE;
4122     }
4123     b->free_ij      = PETSC_TRUE;
4124   } else {
4125     b->free_a  = PETSC_FALSE;
4126     b->free_ij = PETSC_FALSE;
4127   }
4128 
4129   if (b->ipre && nnz != b->ipre  && b->imax) {
4130     /* reserve user-requested sparsity */
4131     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4132   }
4133 
4134   b->nz               = 0;
4135   b->maxnz            = nz;
4136   B->info.nz_unneeded = (double)b->maxnz;
4137   if (realalloc) {
4138     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4139   }
4140   B->was_assembled = PETSC_FALSE;
4141   B->assembled     = PETSC_FALSE;
4142   PetscFunctionReturn(0);
4143 }
4144 
4145 PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4146 {
4147   Mat_SeqAIJ     *a;
4148   PetscInt       i;
4149   PetscErrorCode ierr;
4150 
4151   PetscFunctionBegin;
4152   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4153 
4154   /* Check local size. If zero, then return */
4155   if (!A->rmap->n) PetscFunctionReturn(0);
4156 
4157   a = (Mat_SeqAIJ*)A->data;
4158   /* if no saved info, we error out */
4159   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info ");
4160 
4161   if (!a->i || !a->j || !a->a || !a->imax || !a->ilen) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Memory info is incomplete, and can not reset preallocation ");
4162 
4163   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4164   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4165   a->i[0] = 0;
4166   for (i=1; i<A->rmap->n+1; i++) {
4167     a->i[i] = a->i[i-1] + a->imax[i-1];
4168   }
4169   A->preallocated     = PETSC_TRUE;
4170   a->nz               = 0;
4171   a->maxnz            = a->i[A->rmap->n];
4172   A->info.nz_unneeded = (double)a->maxnz;
4173   A->was_assembled    = PETSC_FALSE;
4174   A->assembled        = PETSC_FALSE;
4175   PetscFunctionReturn(0);
4176 }
4177 
4178 /*@
4179    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4180 
4181    Input Parameters:
4182 +  B - the matrix
4183 .  i - the indices into j for the start of each row (starts with zero)
4184 .  j - the column indices for each row (starts with zero) these must be sorted for each row
4185 -  v - optional values in the matrix
4186 
4187    Level: developer
4188 
4189    Notes:
4190       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
4191 
4192       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
4193       structure will be the union of all the previous nonzero structures.
4194 
4195     Developer Notes:
4196       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
4197       then just copies the v values directly with PetscMemcpy().
4198 
4199       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
4200 
4201 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4202 @*/
4203 PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4204 {
4205   PetscErrorCode ierr;
4206 
4207   PetscFunctionBegin;
4208   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
4209   PetscValidType(B,1);
4210   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4211   PetscFunctionReturn(0);
4212 }
4213 
4214 PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4215 {
4216   PetscInt       i;
4217   PetscInt       m,n;
4218   PetscInt       nz;
4219   PetscInt       *nnz;
4220   PetscErrorCode ierr;
4221 
4222   PetscFunctionBegin;
4223   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]);
4224 
4225   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4226   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4227 
4228   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4229   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4230   for (i = 0; i < m; i++) {
4231     nz     = Ii[i+1]- Ii[i];
4232     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz);
4233     nnz[i] = nz;
4234   }
4235   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4236   ierr = PetscFree(nnz);CHKERRQ(ierr);
4237 
4238   for (i = 0; i < m; i++) {
4239     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4240   }
4241 
4242   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4243   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4244 
4245   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4246   PetscFunctionReturn(0);
4247 }
4248 
4249 /*@
4250    MatSeqAIJKron - Computes C, the Kronecker product of A and B.
4251 
4252    Input Parameters:
4253 +  A - left-hand side matrix
4254 .  B - right-hand side matrix
4255 -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
4256 
4257    Output Parameter:
4258 .  C - Kronecker product of A and B
4259 
4260    Level: intermediate
4261 
4262    Notes:
4263       MAT_REUSE_MATRIX can only be used when the nonzero structure of the product matrix has not changed from that last call to MatSeqAIJKron().
4264 
4265 .seealso: MatCreateSeqAIJ(), MATSEQAIJ, MATKAIJ, MatReuse
4266 @*/
4267 PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C)
4268 {
4269   PetscErrorCode ierr;
4270 
4271   PetscFunctionBegin;
4272   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4273   PetscValidType(A,1);
4274   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4275   PetscValidType(B,2);
4276   PetscValidPointer(C,4);
4277   if (reuse == MAT_REUSE_MATRIX) {
4278     PetscValidHeaderSpecific(*C,MAT_CLASSID,4);
4279     PetscValidType(*C,4);
4280   }
4281   ierr = PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C));CHKERRQ(ierr);
4282   PetscFunctionReturn(0);
4283 }
4284 
4285 PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C)
4286 {
4287   PetscErrorCode     ierr;
4288   Mat                newmat;
4289   Mat_SeqAIJ         *a = (Mat_SeqAIJ*)A->data;
4290   Mat_SeqAIJ         *b = (Mat_SeqAIJ*)B->data;
4291   PetscScalar        *v;
4292   const PetscScalar  *aa,*ba;
4293   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;
4294   PetscBool          flg;
4295 
4296   PetscFunctionBegin;
4297   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4298   if (!A->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4299   if (B->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4300   if (!B->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4301   ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg);CHKERRQ(ierr);
4302   if (!flg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name);
4303   if (reuse != MAT_INITIAL_MATRIX && reuse != MAT_REUSE_MATRIX) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse);
4304   if (reuse == MAT_INITIAL_MATRIX) {
4305     ierr = PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j);CHKERRQ(ierr);
4306     ierr = MatCreate(PETSC_COMM_SELF,&newmat);CHKERRQ(ierr);
4307     ierr = MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn);CHKERRQ(ierr);
4308     ierr = MatSetType(newmat,MATAIJ);CHKERRQ(ierr);
4309     i[0] = 0;
4310     for (m = 0; m < am; ++m) {
4311       for (p = 0; p < bm; ++p) {
4312         i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]);
4313         for (n = a->i[m]; n < a->i[m+1]; ++n) {
4314           for (q = b->i[p]; q < b->i[p+1]; ++q) {
4315             j[nnz++] = a->j[n]*bn + b->j[q];
4316           }
4317         }
4318       }
4319     }
4320     ierr = MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL);CHKERRQ(ierr);
4321     *C = newmat;
4322     ierr = PetscFree2(i,j);CHKERRQ(ierr);
4323     nnz = 0;
4324   }
4325   ierr = MatSeqAIJGetArray(*C,&v);CHKERRQ(ierr);
4326   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4327   ierr = MatSeqAIJGetArrayRead(B,&ba);CHKERRQ(ierr);
4328   for (m = 0; m < am; ++m) {
4329     for (p = 0; p < bm; ++p) {
4330       for (n = a->i[m]; n < a->i[m+1]; ++n) {
4331         for (q = b->i[p]; q < b->i[p+1]; ++q) {
4332           v[nnz++] = aa[n] * ba[q];
4333         }
4334       }
4335     }
4336   }
4337   ierr = MatSeqAIJRestoreArray(*C,&v);CHKERRQ(ierr);
4338   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
4339   ierr = MatSeqAIJRestoreArrayRead(B,&ba);CHKERRQ(ierr);
4340   PetscFunctionReturn(0);
4341 }
4342 
4343 #include <../src/mat/impls/dense/seq/dense.h>
4344 #include <petsc/private/kernels/petscaxpy.h>
4345 
4346 /*
4347     Computes (B'*A')' since computing B*A directly is untenable
4348 
4349                n                       p                          p
4350         [             ]       [             ]         [                 ]
4351       m [      A      ]  *  n [       B     ]   =   m [         C       ]
4352         [             ]       [             ]         [                 ]
4353 
4354 */
4355 PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4356 {
4357   PetscErrorCode    ierr;
4358   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4359   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4360   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
4361   PetscInt          i,j,n,m,q,p;
4362   const PetscInt    *ii,*idx;
4363   const PetscScalar *b,*a,*a_q;
4364   PetscScalar       *c,*c_q;
4365   PetscInt          clda = sub_c->lda;
4366   PetscInt          alda = sub_a->lda;
4367 
4368   PetscFunctionBegin;
4369   m    = A->rmap->n;
4370   n    = A->cmap->n;
4371   p    = B->cmap->n;
4372   a    = sub_a->v;
4373   b    = sub_b->a;
4374   c    = sub_c->v;
4375   if (clda == m) {
4376     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
4377   } else {
4378     for (j=0;j<p;j++)
4379       for (i=0;i<m;i++)
4380         c[j*clda + i] = 0.0;
4381   }
4382   ii  = sub_b->i;
4383   idx = sub_b->j;
4384   for (i=0; i<n; i++) {
4385     q = ii[i+1] - ii[i];
4386     while (q-->0) {
4387       c_q = c + clda*(*idx);
4388       a_q = a + alda*i;
4389       PetscKernelAXPY(c_q,*b,a_q,m);
4390       idx++;
4391       b++;
4392     }
4393   }
4394   PetscFunctionReturn(0);
4395 }
4396 
4397 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4398 {
4399   PetscErrorCode ierr;
4400   PetscInt       m=A->rmap->n,n=B->cmap->n;
4401   PetscBool      cisdense;
4402 
4403   PetscFunctionBegin;
4404   if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %" PetscInt_FMT " != B->rmap->n %" PetscInt_FMT,A->cmap->n,B->rmap->n);
4405   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
4406   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
4407   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
4408   if (!cisdense) {
4409     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
4410   }
4411   ierr = MatSetUp(C);CHKERRQ(ierr);
4412 
4413   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4414   PetscFunctionReturn(0);
4415 }
4416 
4417 /* ----------------------------------------------------------------*/
4418 /*MC
4419    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
4420    based on compressed sparse row format.
4421 
4422    Options Database Keys:
4423 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
4424 
4425    Level: beginner
4426 
4427    Notes:
4428     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
4429     in this case the values associated with the rows and columns one passes in are set to zero
4430     in the matrix
4431 
4432     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
4433     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
4434 
4435   Developer Notes:
4436     It would be nice if all matrix formats supported passing NULL in for the numerical values
4437 
4438 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
4439 M*/
4440 
4441 /*MC
4442    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4443 
4444    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4445    and MATMPIAIJ otherwise.  As a result, for single process communicators,
4446   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4447   for communicators controlling multiple processes.  It is recommended that you call both of
4448   the above preallocation routines for simplicity.
4449 
4450    Options Database Keys:
4451 . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4452 
4453   Developer Notes:
4454     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4455    enough exist.
4456 
4457   Level: beginner
4458 
4459 .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4460 M*/
4461 
4462 /*MC
4463    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4464 
4465    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4466    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4467    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4468   for communicators controlling multiple processes.  It is recommended that you call both of
4469   the above preallocation routines for simplicity.
4470 
4471    Options Database Keys:
4472 . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4473 
4474   Level: beginner
4475 
4476 .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4477 M*/
4478 
4479 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
4480 #if defined(PETSC_HAVE_ELEMENTAL)
4481 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
4482 #endif
4483 #if defined(PETSC_HAVE_SCALAPACK)
4484 PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4485 #endif
4486 #if defined(PETSC_HAVE_HYPRE)
4487 PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
4488 #endif
4489 
4490 PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4491 PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
4492 PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
4493 
4494 /*@C
4495    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
4496 
4497    Not Collective
4498 
4499    Input Parameter:
4500 .  mat - a MATSEQAIJ matrix
4501 
4502    Output Parameter:
4503 .   array - pointer to the data
4504 
4505    Level: intermediate
4506 
4507 .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
4508 @*/
4509 PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
4510 {
4511   PetscErrorCode ierr;
4512   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4513 
4514   PetscFunctionBegin;
4515   if (aij->ops->getarray) {
4516     ierr = (*aij->ops->getarray)(A,array);CHKERRQ(ierr);
4517   } else {
4518     *array = aij->a;
4519   }
4520   PetscFunctionReturn(0);
4521 }
4522 
4523 /*@C
4524    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
4525 
4526    Not Collective
4527 
4528    Input Parameters:
4529 +  mat - a MATSEQAIJ matrix
4530 -  array - pointer to the data
4531 
4532    Level: intermediate
4533 
4534 .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
4535 @*/
4536 PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
4537 {
4538   PetscErrorCode ierr;
4539   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4540 
4541   PetscFunctionBegin;
4542   if (aij->ops->restorearray) {
4543     ierr = (*aij->ops->restorearray)(A,array);CHKERRQ(ierr);
4544   } else {
4545     *array = NULL;
4546   }
4547   PetscFunctionReturn(0);
4548 }
4549 
4550 /*@C
4551    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
4552 
4553    Not Collective
4554 
4555    Input Parameter:
4556 .  mat - a MATSEQAIJ matrix
4557 
4558    Output Parameter:
4559 .   array - pointer to the data
4560 
4561    Level: intermediate
4562 
4563 .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
4564 @*/
4565 PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
4566 {
4567   PetscErrorCode ierr;
4568   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4569 
4570   PetscFunctionBegin;
4571   if (aij->ops->getarrayread) {
4572     ierr = (*aij->ops->getarrayread)(A,array);CHKERRQ(ierr);
4573   } else {
4574     *array = aij->a;
4575   }
4576   PetscFunctionReturn(0);
4577 }
4578 
4579 /*@C
4580    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
4581 
4582    Not Collective
4583 
4584    Input Parameter:
4585 .  mat - a MATSEQAIJ matrix
4586 
4587    Output Parameter:
4588 .   array - pointer to the data
4589 
4590    Level: intermediate
4591 
4592 .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
4593 @*/
4594 PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
4595 {
4596   PetscErrorCode ierr;
4597   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4598 
4599   PetscFunctionBegin;
4600   if (aij->ops->restorearrayread) {
4601     ierr = (*aij->ops->restorearrayread)(A,array);CHKERRQ(ierr);
4602   } else {
4603     *array = NULL;
4604   }
4605   PetscFunctionReturn(0);
4606 }
4607 
4608 /*@C
4609    MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a MATSEQAIJ matrix is stored
4610 
4611    Not Collective
4612 
4613    Input Parameter:
4614 .  mat - a MATSEQAIJ matrix
4615 
4616    Output Parameter:
4617 .   array - pointer to the data
4618 
4619    Level: intermediate
4620 
4621 .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
4622 @*/
4623 PetscErrorCode  MatSeqAIJGetArrayWrite(Mat A,PetscScalar **array)
4624 {
4625   PetscErrorCode ierr;
4626   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4627 
4628   PetscFunctionBegin;
4629   if (aij->ops->getarraywrite) {
4630     ierr = (*aij->ops->getarraywrite)(A,array);CHKERRQ(ierr);
4631   } else {
4632     *array = aij->a;
4633   }
4634   PetscFunctionReturn(0);
4635 }
4636 
4637 /*@C
4638    MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead
4639 
4640    Not Collective
4641 
4642    Input Parameter:
4643 .  mat - a MATSEQAIJ matrix
4644 
4645    Output Parameter:
4646 .   array - pointer to the data
4647 
4648    Level: intermediate
4649 
4650 .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
4651 @*/
4652 PetscErrorCode  MatSeqAIJRestoreArrayWrite(Mat A,PetscScalar **array)
4653 {
4654   PetscErrorCode ierr;
4655   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4656 
4657   PetscFunctionBegin;
4658   if (aij->ops->restorearraywrite) {
4659     ierr = (*aij->ops->restorearraywrite)(A,array);CHKERRQ(ierr);
4660   } else {
4661     *array = NULL;
4662   }
4663   PetscFunctionReturn(0);
4664 }
4665 
4666 /*@C
4667    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
4668 
4669    Not Collective
4670 
4671    Input Parameter:
4672 .  mat - a MATSEQAIJ matrix
4673 
4674    Output Parameter:
4675 .   nz - the maximum number of nonzeros in any row
4676 
4677    Level: intermediate
4678 
4679 .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
4680 @*/
4681 PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
4682 {
4683   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4684 
4685   PetscFunctionBegin;
4686   *nz = aij->rmax;
4687   PetscFunctionReturn(0);
4688 }
4689 
4690 #if defined(PETSC_HAVE_CUDA)
4691 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat,MatType,MatReuse,Mat*);
4692 #endif
4693 #if defined(PETSC_HAVE_KOKKOS_KERNELS)
4694 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat,MatType,MatReuse,Mat*);
4695 #endif
4696 
4697 PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4698 {
4699   Mat_SeqAIJ     *b;
4700   PetscErrorCode ierr;
4701   PetscMPIInt    size;
4702 
4703   PetscFunctionBegin;
4704   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRMPI(ierr);
4705   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4706 
4707   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
4708 
4709   B->data = (void*)b;
4710 
4711   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4712   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
4713 
4714   b->row                = NULL;
4715   b->col                = NULL;
4716   b->icol               = NULL;
4717   b->reallocs           = 0;
4718   b->ignorezeroentries  = PETSC_FALSE;
4719   b->roworiented        = PETSC_TRUE;
4720   b->nonew              = 0;
4721   b->diag               = NULL;
4722   b->solve_work         = NULL;
4723   B->spptr              = NULL;
4724   b->saved_values       = NULL;
4725   b->idiag              = NULL;
4726   b->mdiag              = NULL;
4727   b->ssor_work          = NULL;
4728   b->omega              = 1.0;
4729   b->fshift             = 0.0;
4730   b->idiagvalid         = PETSC_FALSE;
4731   b->ibdiagvalid        = PETSC_FALSE;
4732   b->keepnonzeropattern = PETSC_FALSE;
4733 
4734   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4735 
4736 #if defined(PETSC_HAVE_MATLAB_ENGINE)
4737   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4738   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4739 #endif
4740 
4741   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4742   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4743   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4744   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4745   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4746   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
4747   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
4748 #if defined(PETSC_HAVE_MKL_SPARSE)
4749   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4750 #endif
4751 #if defined(PETSC_HAVE_CUDA)
4752   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
4753   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4754   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4755 #endif
4756 #if defined(PETSC_HAVE_KOKKOS_KERNELS)
4757   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
4758 #endif
4759   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4760 #if defined(PETSC_HAVE_ELEMENTAL)
4761   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4762 #endif
4763 #if defined(PETSC_HAVE_SCALAPACK)
4764   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4765 #endif
4766 #if defined(PETSC_HAVE_HYPRE)
4767   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
4768   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
4769 #endif
4770   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4771   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4772   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4773   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4774   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4775   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4776   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4777   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4778   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
4779   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
4780   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
4781   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4782   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ);CHKERRQ(ierr);
4783   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
4784   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4785   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
4786   PetscFunctionReturn(0);
4787 }
4788 
4789 /*
4790     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4791 */
4792 PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
4793 {
4794   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
4795   PetscErrorCode ierr;
4796   PetscInt       m = A->rmap->n,i;
4797 
4798   PetscFunctionBegin;
4799   if (!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4800 
4801   C->factortype = A->factortype;
4802   c->row        = NULL;
4803   c->col        = NULL;
4804   c->icol       = NULL;
4805   c->reallocs   = 0;
4806 
4807   C->assembled = PETSC_TRUE;
4808 
4809   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4810   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4811 
4812   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4813   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4814   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4815   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
4816   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
4817 
4818   /* allocate the matrix space */
4819   if (mallocmatspace) {
4820     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
4821     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4822 
4823     c->singlemalloc = PETSC_TRUE;
4824 
4825     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
4826     if (m > 0) {
4827       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4828       if (cpvalues == MAT_COPY_VALUES) {
4829         const PetscScalar *aa;
4830 
4831         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4832         ierr = PetscArraycpy(c->a,aa,a->i[m]);CHKERRQ(ierr);
4833         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4834       } else {
4835         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
4836       }
4837     }
4838   }
4839 
4840   c->ignorezeroentries = a->ignorezeroentries;
4841   c->roworiented       = a->roworiented;
4842   c->nonew             = a->nonew;
4843   if (a->diag) {
4844     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4845     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
4846     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4847   } else c->diag = NULL;
4848 
4849   c->solve_work         = NULL;
4850   c->saved_values       = NULL;
4851   c->idiag              = NULL;
4852   c->ssor_work          = NULL;
4853   c->keepnonzeropattern = a->keepnonzeropattern;
4854   c->free_a             = PETSC_TRUE;
4855   c->free_ij            = PETSC_TRUE;
4856 
4857   c->rmax         = a->rmax;
4858   c->nz           = a->nz;
4859   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4860   C->preallocated = PETSC_TRUE;
4861 
4862   c->compressedrow.use   = a->compressedrow.use;
4863   c->compressedrow.nrows = a->compressedrow.nrows;
4864   if (a->compressedrow.use) {
4865     i    = a->compressedrow.nrows;
4866     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4867     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4868     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
4869   } else {
4870     c->compressedrow.use    = PETSC_FALSE;
4871     c->compressedrow.i      = NULL;
4872     c->compressedrow.rindex = NULL;
4873   }
4874   c->nonzerorowcnt = a->nonzerorowcnt;
4875   C->nonzerostate  = A->nonzerostate;
4876 
4877   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4878   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
4879   PetscFunctionReturn(0);
4880 }
4881 
4882 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4883 {
4884   PetscErrorCode ierr;
4885 
4886   PetscFunctionBegin;
4887   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
4888   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4889   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
4890     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4891   }
4892   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4893   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4894   PetscFunctionReturn(0);
4895 }
4896 
4897 PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4898 {
4899   PetscBool      isbinary, ishdf5;
4900   PetscErrorCode ierr;
4901 
4902   PetscFunctionBegin;
4903   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
4904   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4905   /* force binary viewer to load .info file if it has not yet done so */
4906   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4907   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
4908   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
4909   if (isbinary) {
4910     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
4911   } else if (ishdf5) {
4912 #if defined(PETSC_HAVE_HDF5)
4913     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
4914 #else
4915     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
4916 #endif
4917   } else {
4918     SETERRQ2(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"Viewer type %s not yet supported for reading %s matrices",((PetscObject)viewer)->type_name,((PetscObject)newMat)->type_name);
4919   }
4920   PetscFunctionReturn(0);
4921 }
4922 
4923 PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
4924 {
4925   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
4926   PetscErrorCode ierr;
4927   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4928 
4929   PetscFunctionBegin;
4930   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4931 
4932   /* read in matrix header */
4933   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
4934   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4935   M = header[1]; N = header[2]; nz = header[3];
4936   if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%" PetscInt_FMT ") in file is negative",M);
4937   if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%" PetscInt_FMT ") in file is negative",N);
4938   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4939 
4940   /* set block sizes from the viewer's .info file */
4941   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
4942   /* set local and global sizes if not set already */
4943   if (mat->rmap->n < 0) mat->rmap->n = M;
4944   if (mat->cmap->n < 0) mat->cmap->n = N;
4945   if (mat->rmap->N < 0) mat->rmap->N = M;
4946   if (mat->cmap->N < 0) mat->cmap->N = N;
4947   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
4948   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
4949 
4950   /* check if the matrix sizes are correct */
4951   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4952   if (M != rows || N != cols) SETERRQ4(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);
4953 
4954   /* read in row lengths */
4955   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
4956   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
4957   /* check if sum(rowlens) is same as nz */
4958   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
4959   if (sum != nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Inconsistent matrix data in file: nonzeros = %" PetscInt_FMT ", sum-row-lengths = %" PetscInt_FMT,nz,sum);
4960   /* preallocate and check sizes */
4961   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
4962   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
4963   if (M != rows || N != cols) SETERRQ4(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);
4964   /* store row lengths */
4965   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
4966   ierr = PetscFree(rowlens);CHKERRQ(ierr);
4967 
4968   /* fill in "i" row pointers */
4969   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
4970   /* read in "j" column indices */
4971   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
4972   /* read in "a" nonzero values */
4973   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4974 
4975   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4976   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4977   PetscFunctionReturn(0);
4978 }
4979 
4980 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
4981 {
4982   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4983   PetscErrorCode    ierr;
4984   const PetscScalar *aa,*ba;
4985 #if defined(PETSC_USE_COMPLEX)
4986   PetscInt k;
4987 #endif
4988 
4989   PetscFunctionBegin;
4990   /* If the  matrix dimensions are not equal,or no of nonzeros */
4991   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4992     *flg = PETSC_FALSE;
4993     PetscFunctionReturn(0);
4994   }
4995 
4996   /* if the a->i are the same */
4997   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4998   if (!*flg) PetscFunctionReturn(0);
4999 
5000   /* if a->j are the same */
5001   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
5002   if (!*flg) PetscFunctionReturn(0);
5003 
5004   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
5005   ierr = MatSeqAIJGetArrayRead(B,&ba);CHKERRQ(ierr);
5006   /* if a->a are the same */
5007 #if defined(PETSC_USE_COMPLEX)
5008   for (k=0; k<a->nz; k++) {
5009     if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) {
5010       *flg = PETSC_FALSE;
5011       PetscFunctionReturn(0);
5012     }
5013   }
5014 #else
5015   ierr = PetscArraycmp(aa,ba,a->nz,flg);CHKERRQ(ierr);
5016 #endif
5017   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
5018   ierr = MatSeqAIJRestoreArrayRead(B,&ba);CHKERRQ(ierr);
5019   PetscFunctionReturn(0);
5020 }
5021 
5022 /*@
5023      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
5024               provided by the user.
5025 
5026       Collective
5027 
5028    Input Parameters:
5029 +   comm - must be an MPI communicator of size 1
5030 .   m - number of rows
5031 .   n - number of columns
5032 .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
5033 .   j - column indices
5034 -   a - matrix values
5035 
5036    Output Parameter:
5037 .   mat - the matrix
5038 
5039    Level: intermediate
5040 
5041    Notes:
5042        The i, j, and a arrays are not copied by this routine, the user must free these arrays
5043     once the matrix is destroyed and not before
5044 
5045        You cannot set new nonzero locations into this matrix, that will generate an error.
5046 
5047        The i and j indices are 0 based
5048 
5049        The format which is used for the sparse matrix input, is equivalent to a
5050     row-major ordering.. i.e for the following matrix, the input data expected is
5051     as shown
5052 
5053 $        1 0 0
5054 $        2 0 3
5055 $        4 5 6
5056 $
5057 $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
5058 $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
5059 $        v =  {1,2,3,4,5,6}  [size = 6]
5060 
5061 .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
5062 
5063 @*/
5064 PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
5065 {
5066   PetscErrorCode ierr;
5067   PetscInt       ii;
5068   Mat_SeqAIJ     *aij;
5069   PetscInt jj;
5070 
5071   PetscFunctionBegin;
5072   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
5073   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
5074   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
5075   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
5076   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
5077   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
5078   aij  = (Mat_SeqAIJ*)(*mat)->data;
5079   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
5080   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
5081 
5082   aij->i            = i;
5083   aij->j            = j;
5084   aij->a            = a;
5085   aij->singlemalloc = PETSC_FALSE;
5086   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
5087   aij->free_a       = PETSC_FALSE;
5088   aij->free_ij      = PETSC_FALSE;
5089 
5090   for (ii=0; ii<m; ii++) {
5091     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
5092     if (PetscDefined(USE_DEBUG)) {
5093       if (i[ii+1] - i[ii] < 0) SETERRQ2(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]);
5094       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
5095         if (j[jj] < j[jj-1]) SETERRQ3(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);
5096         if (j[jj] == j[jj-1]) SETERRQ3(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);
5097       }
5098     }
5099   }
5100   if (PetscDefined(USE_DEBUG)) {
5101     for (ii=0; ii<aij->i[m]; ii++) {
5102       if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %" PetscInt_FMT " index = %" PetscInt_FMT,ii,j[ii]);
5103       if (j[ii] > n - 1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %" PetscInt_FMT " index = %" PetscInt_FMT,ii,j[ii]);
5104     }
5105   }
5106 
5107   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5108   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5109   PetscFunctionReturn(0);
5110 }
5111 /*@C
5112      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
5113               provided by the user.
5114 
5115       Collective
5116 
5117    Input Parameters:
5118 +   comm - must be an MPI communicator of size 1
5119 .   m   - number of rows
5120 .   n   - number of columns
5121 .   i   - row indices
5122 .   j   - column indices
5123 .   a   - matrix values
5124 .   nz  - number of nonzeros
5125 -   idx - 0 or 1 based
5126 
5127    Output Parameter:
5128 .   mat - the matrix
5129 
5130    Level: intermediate
5131 
5132    Notes:
5133        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,
5134        the input data expected is as shown
5135 .vb
5136         1 0 0
5137         2 0 3
5138         4 5 6
5139 
5140         i =  {0,1,1,2,2,2}
5141         j =  {0,0,2,0,1,2}
5142         v =  {1,2,3,4,5,6}
5143 .ve
5144 
5145 .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
5146 
5147 @*/
5148 PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
5149 {
5150   PetscErrorCode ierr;
5151   PetscInt       ii, *nnz, one = 1,row,col;
5152 
5153   PetscFunctionBegin;
5154   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
5155   for (ii = 0; ii < nz; ii++) {
5156     nnz[i[ii] - !!idx] += 1;
5157   }
5158   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
5159   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
5160   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
5161   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
5162   for (ii = 0; ii < nz; ii++) {
5163     if (idx) {
5164       row = i[ii] - 1;
5165       col = j[ii] - 1;
5166     } else {
5167       row = i[ii];
5168       col = j[ii];
5169     }
5170     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
5171   }
5172   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5173   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5174   ierr = PetscFree(nnz);CHKERRQ(ierr);
5175   PetscFunctionReturn(0);
5176 }
5177 
5178 PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5179 {
5180   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5181   PetscErrorCode ierr;
5182 
5183   PetscFunctionBegin;
5184   a->idiagvalid  = PETSC_FALSE;
5185   a->ibdiagvalid = PETSC_FALSE;
5186 
5187   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
5188   PetscFunctionReturn(0);
5189 }
5190 
5191 PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
5192 {
5193   PetscErrorCode ierr;
5194   PetscMPIInt    size;
5195 
5196   PetscFunctionBegin;
5197   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
5198   if (size == 1) {
5199     if (scall == MAT_INITIAL_MATRIX) {
5200       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
5201     } else {
5202       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
5203     }
5204   } else {
5205     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
5206   }
5207   PetscFunctionReturn(0);
5208 }
5209 
5210 /*
5211  Permute A into C's *local* index space using rowemb,colemb.
5212  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
5213  of [0,m), colemb is in [0,n).
5214  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
5215  */
5216 PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
5217 {
5218   /* If making this function public, change the error returned in this function away from _PLIB. */
5219   PetscErrorCode ierr;
5220   Mat_SeqAIJ     *Baij;
5221   PetscBool      seqaij;
5222   PetscInt       m,n,*nz,i,j,count;
5223   PetscScalar    v;
5224   const PetscInt *rowindices,*colindices;
5225 
5226   PetscFunctionBegin;
5227   if (!B) PetscFunctionReturn(0);
5228   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
5229   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
5230   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
5231   if (rowemb) {
5232     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
5233     if (m != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Row IS of size %" PetscInt_FMT " is incompatible with matrix row size %" PetscInt_FMT,m,B->rmap->n);
5234   } else {
5235     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
5236   }
5237   if (colemb) {
5238     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
5239     if (n != B->cmap->n) SETERRQ2(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);
5240   } else {
5241     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
5242   }
5243 
5244   Baij = (Mat_SeqAIJ*)(B->data);
5245   if (pattern == DIFFERENT_NONZERO_PATTERN) {
5246     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
5247     for (i=0; i<B->rmap->n; i++) {
5248       nz[i] = Baij->i[i+1] - Baij->i[i];
5249     }
5250     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
5251     ierr = PetscFree(nz);CHKERRQ(ierr);
5252   }
5253   if (pattern == SUBSET_NONZERO_PATTERN) {
5254     ierr = MatZeroEntries(C);CHKERRQ(ierr);
5255   }
5256   count = 0;
5257   rowindices = NULL;
5258   colindices = NULL;
5259   if (rowemb) {
5260     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
5261   }
5262   if (colemb) {
5263     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
5264   }
5265   for (i=0; i<B->rmap->n; i++) {
5266     PetscInt row;
5267     row = i;
5268     if (rowindices) row = rowindices[i];
5269     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
5270       PetscInt col;
5271       col  = Baij->j[count];
5272       if (colindices) col = colindices[col];
5273       v    = Baij->a[count];
5274       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
5275       ++count;
5276     }
5277   }
5278   /* FIXME: set C's nonzerostate correctly. */
5279   /* Assembly for C is necessary. */
5280   C->preallocated = PETSC_TRUE;
5281   C->assembled     = PETSC_TRUE;
5282   C->was_assembled = PETSC_FALSE;
5283   PetscFunctionReturn(0);
5284 }
5285 
5286 PetscFunctionList MatSeqAIJList = NULL;
5287 
5288 /*@C
5289    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
5290 
5291    Collective on Mat
5292 
5293    Input Parameters:
5294 +  mat      - the matrix object
5295 -  matype   - matrix type
5296 
5297    Options Database Key:
5298 .  -mat_seqai_type  <method> - for example seqaijcrl
5299 
5300   Level: intermediate
5301 
5302 .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
5303 @*/
5304 PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
5305 {
5306   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
5307   PetscBool      sametype;
5308 
5309   PetscFunctionBegin;
5310   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
5311   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
5312   if (sametype) PetscFunctionReturn(0);
5313 
5314   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
5315   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
5316   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
5317   PetscFunctionReturn(0);
5318 }
5319 
5320 /*@C
5321   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
5322 
5323    Not Collective
5324 
5325    Input Parameters:
5326 +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
5327 -  function - routine to convert to subtype
5328 
5329    Notes:
5330    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
5331 
5332    Then, your matrix can be chosen with the procedural interface at runtime via the option
5333 $     -mat_seqaij_type my_mat
5334 
5335    Level: advanced
5336 
5337 .seealso: MatSeqAIJRegisterAll()
5338 
5339   Level: advanced
5340 @*/
5341 PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
5342 {
5343   PetscErrorCode ierr;
5344 
5345   PetscFunctionBegin;
5346   ierr = MatInitializePackage();CHKERRQ(ierr);
5347   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
5348   PetscFunctionReturn(0);
5349 }
5350 
5351 PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
5352 
5353 /*@C
5354   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
5355 
5356   Not Collective
5357 
5358   Level: advanced
5359 
5360 .seealso:  MatRegisterAll(), MatSeqAIJRegister()
5361 @*/
5362 PetscErrorCode  MatSeqAIJRegisterAll(void)
5363 {
5364   PetscErrorCode ierr;
5365 
5366   PetscFunctionBegin;
5367   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
5368   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
5369 
5370   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
5371   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
5372   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
5373 #if defined(PETSC_HAVE_MKL_SPARSE)
5374   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5375 #endif
5376 #if defined(PETSC_HAVE_CUDA)
5377   ierr = MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
5378 #endif
5379 #if defined(PETSC_HAVE_KOKKOS_KERNELS)
5380   ierr = MatSeqAIJRegister(MATSEQAIJKOKKOS,   MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
5381 #endif
5382 #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
5383   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
5384 #endif
5385   PetscFunctionReturn(0);
5386 }
5387 
5388 /*
5389     Special version for direct calls from Fortran
5390 */
5391 #include <petsc/private/fortranimpl.h>
5392 #if defined(PETSC_HAVE_FORTRAN_CAPS)
5393 #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
5394 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
5395 #define matsetvaluesseqaij_ matsetvaluesseqaij
5396 #endif
5397 
5398 /* Change these macros so can be used in void function */
5399 #undef CHKERRQ
5400 #define CHKERRQ(err) CHKERRABORT(PetscObjectComm((PetscObject)A),err)
5401 #undef SETERRQ2
5402 #define SETERRQ2(comm,err,b,c,d) CHKERRABORT(comm,err)
5403 #undef SETERRQ3
5404 #define SETERRQ3(comm,err,b,c,d,e) CHKERRABORT(comm,err)
5405 
5406 PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
5407 {
5408   Mat            A  = *AA;
5409   PetscInt       m  = *mm, n = *nn;
5410   InsertMode     is = *isis;
5411   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
5412   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
5413   PetscInt       *imax,*ai,*ailen;
5414   PetscErrorCode ierr;
5415   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
5416   MatScalar      *ap,value,*aa;
5417   PetscBool      ignorezeroentries = a->ignorezeroentries;
5418   PetscBool      roworiented       = a->roworiented;
5419 
5420   PetscFunctionBegin;
5421   MatCheckPreallocated(A,1);
5422   imax  = a->imax;
5423   ai    = a->i;
5424   ailen = a->ilen;
5425   aj    = a->j;
5426   aa    = a->a;
5427 
5428   for (k=0; k<m; k++) { /* loop over added rows */
5429     row = im[k];
5430     if (row < 0) continue;
5431     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
5432     rp   = aj + ai[row]; ap = aa + ai[row];
5433     rmax = imax[row]; nrow = ailen[row];
5434     low  = 0;
5435     high = nrow;
5436     for (l=0; l<n; l++) { /* loop over added columns */
5437       if (in[l] < 0) continue;
5438       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
5439       col = in[l];
5440       if (roworiented) value = v[l + k*n];
5441       else value = v[k + l*m];
5442 
5443       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
5444 
5445       if (col <= lastcol) low = 0;
5446       else high = nrow;
5447       lastcol = col;
5448       while (high-low > 5) {
5449         t = (low+high)/2;
5450         if (rp[t] > col) high = t;
5451         else             low  = t;
5452       }
5453       for (i=low; i<high; i++) {
5454         if (rp[i] > col) break;
5455         if (rp[i] == col) {
5456           if (is == ADD_VALUES) ap[i] += value;
5457           else                  ap[i] = value;
5458           goto noinsert;
5459         }
5460       }
5461       if (value == 0.0 && ignorezeroentries) goto noinsert;
5462       if (nonew == 1) goto noinsert;
5463       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5464       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
5465       N = nrow++ - 1; a->nz++; high++;
5466       /* shift up all the later entries in this row */
5467       for (ii=N; ii>=i; ii--) {
5468         rp[ii+1] = rp[ii];
5469         ap[ii+1] = ap[ii];
5470       }
5471       rp[i] = col;
5472       ap[i] = value;
5473       A->nonzerostate++;
5474 noinsert:;
5475       low = i + 1;
5476     }
5477     ailen[row] = nrow;
5478   }
5479   PetscFunctionReturnVoid();
5480 }
5481