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