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