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