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