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