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