xref: /petsc/src/mat/impls/aij/seq/aij.c (revision a83b8d76eac3dccd5dadc86ea0ccb0f1aa5a9776)
1 #define PETSCMAT_DLL
2 
3 
4 /*
5     Defines the basic matrix operations for the AIJ (compressed row)
6   matrix storage format.
7 */
8 
9 
10 #include "../src/mat/impls/aij/seq/aij.h"          /*I "petscmat.h" I*/
11 #include "petscbt.h"
12 
13 #undef __FUNCT__
14 #define __FUNCT__ "MatDiagonalSet_SeqAIJ"
15 PetscErrorCode PETSCMAT_DLLEXPORT MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
16 {
17   PetscErrorCode ierr;
18   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) Y->data;
19   PetscInt       i,*diag, m = Y->rmap->n;
20   MatScalar      *aa = aij->a;
21   PetscScalar    *v;
22   PetscTruth     missing;
23 
24   PetscFunctionBegin;
25   if (Y->assembled) {
26     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,PETSC_NULL);CHKERRQ(ierr);
27     if (!missing) {
28       diag = aij->diag;
29       ierr = VecGetArray(D,&v);CHKERRQ(ierr);
30       if (is == INSERT_VALUES) {
31 	for (i=0; i<m; i++) {
32 	  aa[diag[i]] = v[i];
33 	}
34       } else {
35 	for (i=0; i<m; i++) {
36 	  aa[diag[i]] += v[i];
37 	}
38       }
39       ierr = VecRestoreArray(D,&v);CHKERRQ(ierr);
40       PetscFunctionReturn(0);
41     }
42   }
43   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
44   PetscFunctionReturn(0);
45 }
46 
47 #undef __FUNCT__
48 #define __FUNCT__ "MatGetRowIJ_SeqAIJ"
49 PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *m,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
50 {
51   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
52   PetscErrorCode ierr;
53   PetscInt       i,ishift;
54 
55   PetscFunctionBegin;
56   *m     = A->rmap->n;
57   if (!ia) PetscFunctionReturn(0);
58   ishift = 0;
59   if (symmetric && !A->structurally_symmetric) {
60     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,ishift,oshift,ia,ja);CHKERRQ(ierr);
61   } else if (oshift == 1) {
62     PetscInt nz = a->i[A->rmap->n];
63     /* malloc space and  add 1 to i and j indices */
64     ierr = PetscMalloc((A->rmap->n+1)*sizeof(PetscInt),ia);CHKERRQ(ierr);
65     for (i=0; i<A->rmap->n+1; i++) (*ia)[i] = a->i[i] + 1;
66     if (ja) {
67       ierr = PetscMalloc((nz+1)*sizeof(PetscInt),ja);CHKERRQ(ierr);
68       for (i=0; i<nz; i++) (*ja)[i] = a->j[i] + 1;
69     }
70   } else {
71     *ia = a->i;
72     if (ja) *ja = a->j;
73   }
74   PetscFunctionReturn(0);
75 }
76 
77 #undef __FUNCT__
78 #define __FUNCT__ "MatRestoreRowIJ_SeqAIJ"
79 PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
80 {
81   PetscErrorCode ierr;
82 
83   PetscFunctionBegin;
84   if (!ia) PetscFunctionReturn(0);
85   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
86     ierr = PetscFree(*ia);CHKERRQ(ierr);
87     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
88   }
89   PetscFunctionReturn(0);
90 }
91 
92 #undef __FUNCT__
93 #define __FUNCT__ "MatGetColumnIJ_SeqAIJ"
94 PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *nn,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
95 {
96   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
97   PetscErrorCode ierr;
98   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
99   PetscInt       nz = a->i[m],row,*jj,mr,col;
100 
101   PetscFunctionBegin;
102   *nn = n;
103   if (!ia) PetscFunctionReturn(0);
104   if (symmetric) {
105     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,0,oshift,ia,ja);CHKERRQ(ierr);
106   } else {
107     ierr = PetscMalloc((n+1)*sizeof(PetscInt),&collengths);CHKERRQ(ierr);
108     ierr = PetscMemzero(collengths,n*sizeof(PetscInt));CHKERRQ(ierr);
109     ierr = PetscMalloc((n+1)*sizeof(PetscInt),&cia);CHKERRQ(ierr);
110     ierr = PetscMalloc((nz+1)*sizeof(PetscInt),&cja);CHKERRQ(ierr);
111     jj = a->j;
112     for (i=0; i<nz; i++) {
113       collengths[jj[i]]++;
114     }
115     cia[0] = oshift;
116     for (i=0; i<n; i++) {
117       cia[i+1] = cia[i] + collengths[i];
118     }
119     ierr = PetscMemzero(collengths,n*sizeof(PetscInt));CHKERRQ(ierr);
120     jj   = a->j;
121     for (row=0; row<m; row++) {
122       mr = a->i[row+1] - a->i[row];
123       for (i=0; i<mr; i++) {
124         col = *jj++;
125         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
126       }
127     }
128     ierr = PetscFree(collengths);CHKERRQ(ierr);
129     *ia = cia; *ja = cja;
130   }
131   PetscFunctionReturn(0);
132 }
133 
134 #undef __FUNCT__
135 #define __FUNCT__ "MatRestoreColumnIJ_SeqAIJ"
136 PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscTruth symmetric,PetscTruth inodecompressed,PetscInt *n,PetscInt *ia[],PetscInt *ja[],PetscTruth *done)
137 {
138   PetscErrorCode ierr;
139 
140   PetscFunctionBegin;
141   if (!ia) PetscFunctionReturn(0);
142 
143   ierr = PetscFree(*ia);CHKERRQ(ierr);
144   ierr = PetscFree(*ja);CHKERRQ(ierr);
145 
146   PetscFunctionReturn(0);
147 }
148 
149 #undef __FUNCT__
150 #define __FUNCT__ "MatSetValuesRow_SeqAIJ"
151 PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
152 {
153   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
154   PetscInt       *ai = a->i;
155   PetscErrorCode ierr;
156 
157   PetscFunctionBegin;
158   ierr = PetscMemcpy(a->a+ai[row],v,(ai[row+1]-ai[row])*sizeof(PetscScalar));CHKERRQ(ierr);
159   PetscFunctionReturn(0);
160 }
161 
162 #define CHUNKSIZE   15
163 
164 #undef __FUNCT__
165 #define __FUNCT__ "MatSetValues_SeqAIJ"
166 PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
167 {
168   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
169   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
170   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
171   PetscErrorCode ierr;
172   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
173   MatScalar      *ap,value,*aa = a->a;
174   PetscTruth     ignorezeroentries = a->ignorezeroentries;
175   PetscTruth     roworiented = a->roworiented;
176 
177   PetscFunctionBegin;
178   if (v) PetscValidScalarPointer(v,6);
179   for (k=0; k<m; k++) { /* loop over added rows */
180     row  = im[k];
181     if (row < 0) continue;
182 #if defined(PETSC_USE_DEBUG)
183     if (row >= A->rmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
184 #endif
185     rp   = aj + ai[row]; ap = aa + ai[row];
186     rmax = imax[row]; nrow = ailen[row];
187     low  = 0;
188     high = nrow;
189     for (l=0; l<n; l++) { /* loop over added columns */
190       if (in[l] < 0) continue;
191 #if defined(PETSC_USE_DEBUG)
192       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
193 #endif
194       col = in[l];
195       if (v) {
196 	if (roworiented) {
197 	  value = v[l + k*n];
198 	} else {
199 	  value = v[k + l*m];
200 	}
201       } else {
202         value = 0.;
203       }
204       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
205 
206       if (col <= lastcol) low = 0; else high = nrow;
207       lastcol = col;
208       while (high-low > 5) {
209         t = (low+high)/2;
210         if (rp[t] > col) high = t;
211         else             low  = t;
212       }
213       for (i=low; i<high; i++) {
214         if (rp[i] > col) break;
215         if (rp[i] == col) {
216           if (is == ADD_VALUES) ap[i] += value;
217           else                  ap[i] = value;
218           low = i + 1;
219           goto noinsert;
220         }
221       }
222       if (value == 0.0 && ignorezeroentries) goto noinsert;
223       if (nonew == 1) goto noinsert;
224       if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
225       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
226       N = nrow++ - 1; a->nz++; high++;
227       /* shift up all the later entries in this row */
228       for (ii=N; ii>=i; ii--) {
229         rp[ii+1] = rp[ii];
230         ap[ii+1] = ap[ii];
231       }
232       rp[i] = col;
233       ap[i] = value;
234       low   = i + 1;
235       noinsert:;
236     }
237     ailen[row] = nrow;
238   }
239   A->same_nonzero = PETSC_FALSE;
240   PetscFunctionReturn(0);
241 }
242 
243 
244 #undef __FUNCT__
245 #define __FUNCT__ "MatGetValues_SeqAIJ"
246 PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
247 {
248   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
249   PetscInt     *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
250   PetscInt     *ai = a->i,*ailen = a->ilen;
251   MatScalar    *ap,*aa = a->a;
252 
253   PetscFunctionBegin;
254   for (k=0; k<m; k++) { /* loop over rows */
255     row  = im[k];
256     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
257     if (row >= A->rmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
258     rp   = aj + ai[row]; ap = aa + ai[row];
259     nrow = ailen[row];
260     for (l=0; l<n; l++) { /* loop over columns */
261       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
262       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
263       col = in[l] ;
264       high = nrow; low = 0; /* assume unsorted */
265       while (high-low > 5) {
266         t = (low+high)/2;
267         if (rp[t] > col) high = t;
268         else             low  = t;
269       }
270       for (i=low; i<high; i++) {
271         if (rp[i] > col) break;
272         if (rp[i] == col) {
273           *v++ = ap[i];
274           goto finished;
275         }
276       }
277       *v++ = 0.0;
278       finished:;
279     }
280   }
281   PetscFunctionReturn(0);
282 }
283 
284 
285 #undef __FUNCT__
286 #define __FUNCT__ "MatView_SeqAIJ_Binary"
287 PetscErrorCode MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer)
288 {
289   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
290   PetscErrorCode ierr;
291   PetscInt       i,*col_lens;
292   int            fd;
293 
294   PetscFunctionBegin;
295   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
296   ierr = PetscMalloc((4+A->rmap->n)*sizeof(PetscInt),&col_lens);CHKERRQ(ierr);
297   col_lens[0] = MAT_FILE_COOKIE;
298   col_lens[1] = A->rmap->n;
299   col_lens[2] = A->cmap->n;
300   col_lens[3] = a->nz;
301 
302   /* store lengths of each row and write (including header) to file */
303   for (i=0; i<A->rmap->n; i++) {
304     col_lens[4+i] = a->i[i+1] - a->i[i];
305   }
306   ierr = PetscBinaryWrite(fd,col_lens,4+A->rmap->n,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
307   ierr = PetscFree(col_lens);CHKERRQ(ierr);
308 
309   /* store column indices (zero start index) */
310   ierr = PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
311 
312   /* store nonzero values */
313   ierr = PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
314   PetscFunctionReturn(0);
315 }
316 
317 EXTERN PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
318 
319 #undef __FUNCT__
320 #define __FUNCT__ "MatView_SeqAIJ_ASCII"
321 PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
322 {
323   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
324   PetscErrorCode    ierr;
325   PetscInt          i,j,m = A->rmap->n,shift=0;
326   const char        *name;
327   PetscViewerFormat format;
328 
329   PetscFunctionBegin;
330   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
331   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
332   if (format == PETSC_VIEWER_ASCII_MATLAB) {
333     PetscInt nofinalvalue = 0;
334     if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-!shift)) {
335       nofinalvalue = 1;
336     }
337     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
338     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
339     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
340     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
341     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
342 
343     for (i=0; i<m; i++) {
344       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
345 #if defined(PETSC_USE_COMPLEX)
346         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e + %18.16ei \n",i+1,a->j[j]+!shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
347 #else
348         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+!shift,a->a[j]);CHKERRQ(ierr);
349 #endif
350       }
351     }
352     if (nofinalvalue) {
353       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
354     }
355     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
356     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
357   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO) {
358      PetscFunctionReturn(0);
359   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
360     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
361     for (i=0; i<m; i++) {
362       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
363       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
364 #if defined(PETSC_USE_COMPLEX)
365         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
366           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
367         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
368           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
369         } else if (PetscRealPart(a->a[j]) != 0.0) {
370           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
371         }
372 #else
373         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);}
374 #endif
375       }
376       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
377     }
378     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
379   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
380     PetscInt nzd=0,fshift=1,*sptr;
381     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
382     ierr = PetscMalloc((m+1)*sizeof(PetscInt),&sptr);CHKERRQ(ierr);
383     for (i=0; i<m; i++) {
384       sptr[i] = nzd+1;
385       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
386         if (a->j[j] >= i) {
387 #if defined(PETSC_USE_COMPLEX)
388           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
389 #else
390           if (a->a[j] != 0.0) nzd++;
391 #endif
392         }
393       }
394     }
395     sptr[m] = nzd+1;
396     ierr = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
397     for (i=0; i<m+1; i+=6) {
398       if (i+4<m) {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);}
399       else if (i+3<m) {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);}
400       else if (i+2<m) {ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);}
401       else if (i+1<m) {ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);}
402       else if (i<m)   {ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);}
403       else            {ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);}
404     }
405     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
406     ierr = PetscFree(sptr);CHKERRQ(ierr);
407     for (i=0; i<m; i++) {
408       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
409         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
410       }
411       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
412     }
413     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
414     for (i=0; i<m; i++) {
415       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
416         if (a->j[j] >= i) {
417 #if defined(PETSC_USE_COMPLEX)
418           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
419             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
420           }
421 #else
422           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",a->a[j]);CHKERRQ(ierr);}
423 #endif
424         }
425       }
426       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
427     }
428     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
429   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
430     PetscInt         cnt = 0,jcnt;
431     PetscScalar value;
432 
433     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
434     for (i=0; i<m; i++) {
435       jcnt = 0;
436       for (j=0; j<A->cmap->n; j++) {
437         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
438           value = a->a[cnt++];
439           jcnt++;
440         } else {
441           value = 0.0;
442         }
443 #if defined(PETSC_USE_COMPLEX)
444         ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",PetscRealPart(value),PetscImaginaryPart(value));CHKERRQ(ierr);
445 #else
446         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",value);CHKERRQ(ierr);
447 #endif
448       }
449       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
450     }
451     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
452   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
453     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
454 #if defined(PETSC_USE_COMPLEX)
455     ierr = PetscViewerASCIIPrintf(viewer,"%%matrix complex general\n");CHKERRQ(ierr);
456 #else
457     ierr = PetscViewerASCIIPrintf(viewer,"%%matrix real general\n");CHKERRQ(ierr);
458 #endif
459     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
460     for (i=0; i<m; i++) {
461       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
462 #if defined(PETSC_USE_COMPLEX)
463         if (PetscImaginaryPart(a->a[j]) > 0.0) {
464           ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
465         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
466           ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G -%G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
467         } else {
468           ierr = PetscViewerASCIIPrintf(viewer,"%D %D, %G\n", i+shift,a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
469         }
470 #else
471         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %G\n", i+shift, a->j[j]+shift, a->a[j]);CHKERRQ(ierr);
472 #endif
473       }
474     }
475     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
476   } else {
477     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
478     if (A->factor){
479       for (i=0; i<m; i++) {
480         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
481         /* L part */
482 	for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
483 #if defined(PETSC_USE_COMPLEX)
484           if (PetscImaginaryPart(a->a[j]) > 0.0) {
485             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
486           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
487             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
488           } else {
489             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
490           }
491 #else
492           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);
493 #endif
494         }
495 	/* diagonal */
496 	j = a->diag[i];
497 #if defined(PETSC_USE_COMPLEX)
498         if (PetscImaginaryPart(a->a[j]) > 0.0) {
499             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
500           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
501             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
502           } else {
503             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
504           }
505 #else
506           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);
507 #endif
508 
509 	/* U part */
510 	for (j=a->diag[i+1]+1+shift; j<a->diag[i]+shift; j++) {
511 #if defined(PETSC_USE_COMPLEX)
512           if (PetscImaginaryPart(a->a[j]) > 0.0) {
513             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
514           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
515             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
516           } else {
517             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
518           }
519 #else
520           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);
521 #endif
522 }
523 	  ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
524         }
525     } else {
526       for (i=0; i<m; i++) {
527         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
528         for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
529 #if defined(PETSC_USE_COMPLEX)
530           if (PetscImaginaryPart(a->a[j]) > 0.0) {
531             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
532           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
533             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G - %G i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
534           } else {
535             ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
536           }
537 #else
538           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);
539 #endif
540         }
541         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
542       }
543     }
544     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
545   }
546   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
547   PetscFunctionReturn(0);
548 }
549 
550 #undef __FUNCT__
551 #define __FUNCT__ "MatView_SeqAIJ_Draw_Zoom"
552 PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
553 {
554   Mat               A = (Mat) Aa;
555   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
556   PetscErrorCode    ierr;
557   PetscInt          i,j,m = A->rmap->n,color;
558   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r,maxv = 0.0;
559   PetscViewer       viewer;
560   PetscViewerFormat format;
561 
562   PetscFunctionBegin;
563   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
564   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
565 
566   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
567   /* loop over matrix elements drawing boxes */
568 
569   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
570     /* Blue for negative, Cyan for zero and  Red for positive */
571     color = PETSC_DRAW_BLUE;
572     for (i=0; i<m; i++) {
573       y_l = m - i - 1.0; y_r = y_l + 1.0;
574       for (j=a->i[i]; j<a->i[i+1]; j++) {
575         x_l = a->j[j] ; x_r = x_l + 1.0;
576 #if defined(PETSC_USE_COMPLEX)
577         if (PetscRealPart(a->a[j]) >=  0.) continue;
578 #else
579         if (a->a[j] >=  0.) continue;
580 #endif
581         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
582       }
583     }
584     color = PETSC_DRAW_CYAN;
585     for (i=0; i<m; i++) {
586       y_l = m - i - 1.0; y_r = y_l + 1.0;
587       for (j=a->i[i]; j<a->i[i+1]; j++) {
588         x_l = a->j[j]; x_r = x_l + 1.0;
589         if (a->a[j] !=  0.) continue;
590         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
591       }
592     }
593     color = PETSC_DRAW_RED;
594     for (i=0; i<m; i++) {
595       y_l = m - i - 1.0; y_r = y_l + 1.0;
596       for (j=a->i[i]; j<a->i[i+1]; j++) {
597         x_l = a->j[j]; x_r = x_l + 1.0;
598 #if defined(PETSC_USE_COMPLEX)
599         if (PetscRealPart(a->a[j]) <=  0.) continue;
600 #else
601         if (a->a[j] <=  0.) continue;
602 #endif
603         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
604       }
605     }
606   } else {
607     /* use contour shading to indicate magnitude of values */
608     /* first determine max of all nonzero values */
609     PetscInt    nz = a->nz,count;
610     PetscDraw   popup;
611     PetscReal scale;
612 
613     for (i=0; i<nz; i++) {
614       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
615     }
616     scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv;
617     ierr  = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
618     if (popup) {ierr  = PetscDrawScalePopup(popup,0.0,maxv);CHKERRQ(ierr);}
619     count = 0;
620     for (i=0; i<m; i++) {
621       y_l = m - i - 1.0; y_r = y_l + 1.0;
622       for (j=a->i[i]; j<a->i[i+1]; j++) {
623         x_l = a->j[j]; x_r = x_l + 1.0;
624         color = PETSC_DRAW_BASIC_COLORS + (PetscInt)(scale*PetscAbsScalar(a->a[count]));
625         ierr  = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
626         count++;
627       }
628     }
629   }
630   PetscFunctionReturn(0);
631 }
632 
633 #undef __FUNCT__
634 #define __FUNCT__ "MatView_SeqAIJ_Draw"
635 PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
636 {
637   PetscErrorCode ierr;
638   PetscDraw      draw;
639   PetscReal      xr,yr,xl,yl,h,w;
640   PetscTruth     isnull;
641 
642   PetscFunctionBegin;
643   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
644   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
645   if (isnull) PetscFunctionReturn(0);
646 
647   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
648   xr  = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0;
649   xr += w;    yr += h;  xl = -w;     yl = -h;
650   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
651   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
652   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
653   PetscFunctionReturn(0);
654 }
655 
656 #undef __FUNCT__
657 #define __FUNCT__ "MatView_SeqAIJ"
658 PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
659 {
660   PetscErrorCode ierr;
661   PetscTruth     iascii,isbinary,isdraw;
662 
663   PetscFunctionBegin;
664   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
665   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);CHKERRQ(ierr);
666   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
667   if (iascii) {
668     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
669   } else if (isbinary) {
670     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
671   } else if (isdraw) {
672     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
673   } else {
674     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by SeqAIJ matrices",((PetscObject)viewer)->type_name);
675   }
676   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
677   PetscFunctionReturn(0);
678 }
679 
680 #undef __FUNCT__
681 #define __FUNCT__ "MatAssemblyEnd_SeqAIJ"
682 PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
683 {
684   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
685   PetscErrorCode ierr;
686   PetscInt       fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax;
687   PetscInt       m = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
688   MatScalar      *aa = a->a,*ap;
689   PetscReal      ratio=0.6;
690 
691   PetscFunctionBegin;
692   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
693 
694   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
695   for (i=1; i<m; i++) {
696     /* move each row back by the amount of empty slots (fshift) before it*/
697     fshift += imax[i-1] - ailen[i-1];
698     rmax   = PetscMax(rmax,ailen[i]);
699     if (fshift) {
700       ip = aj + ai[i] ;
701       ap = aa + ai[i] ;
702       N  = ailen[i];
703       for (j=0; j<N; j++) {
704         ip[j-fshift] = ip[j];
705         ap[j-fshift] = ap[j];
706       }
707     }
708     ai[i] = ai[i-1] + ailen[i-1];
709   }
710   if (m) {
711     fshift += imax[m-1] - ailen[m-1];
712     ai[m]  = ai[m-1] + ailen[m-1];
713   }
714   /* reset ilen and imax for each row */
715   for (i=0; i<m; i++) {
716     ailen[i] = imax[i] = ai[i+1] - ai[i];
717   }
718   a->nz = ai[m];
719   if (fshift && a->nounused == -1) {
720     SETERRQ3(PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D, %D unneeded", m, A->cmap->n, fshift);
721   }
722 
723   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
724   ierr = PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n,fshift,a->nz);CHKERRQ(ierr);
725   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
726   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
727 
728   a->reallocs          = 0;
729   A->info.nz_unneeded  = (double)fshift;
730   a->rmax              = rmax;
731 
732   /* check for zero rows. If found a large number of zero rows, use CompressedRow functions */
733   ierr = Mat_CheckCompressedRow(A,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
734   A->same_nonzero = PETSC_TRUE;
735 
736   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
737 
738   a->idiagvalid = PETSC_FALSE;
739   PetscFunctionReturn(0);
740 }
741 
742 #undef __FUNCT__
743 #define __FUNCT__ "MatRealPart_SeqAIJ"
744 PetscErrorCode MatRealPart_SeqAIJ(Mat A)
745 {
746   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
747   PetscInt       i,nz = a->nz;
748   MatScalar      *aa = a->a;
749 
750   PetscFunctionBegin;
751   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
752   PetscFunctionReturn(0);
753 }
754 
755 #undef __FUNCT__
756 #define __FUNCT__ "MatImaginaryPart_SeqAIJ"
757 PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
758 {
759   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
760   PetscInt       i,nz = a->nz;
761   MatScalar      *aa = a->a;
762 
763   PetscFunctionBegin;
764   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
765   PetscFunctionReturn(0);
766 }
767 
768 #undef __FUNCT__
769 #define __FUNCT__ "MatZeroEntries_SeqAIJ"
770 PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
771 {
772   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
773   PetscErrorCode ierr;
774 
775   PetscFunctionBegin;
776   ierr = PetscMemzero(a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));CHKERRQ(ierr);
777   PetscFunctionReturn(0);
778 }
779 
780 #undef __FUNCT__
781 #define __FUNCT__ "MatDestroy_SeqAIJ"
782 PetscErrorCode MatDestroy_SeqAIJ(Mat A)
783 {
784   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
785   PetscErrorCode ierr;
786 
787   PetscFunctionBegin;
788 #if defined(PETSC_USE_LOG)
789   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
790 #endif
791   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
792   if (a->row) {
793     ierr = ISDestroy(a->row);CHKERRQ(ierr);
794   }
795   if (a->col) {
796     ierr = ISDestroy(a->col);CHKERRQ(ierr);
797   }
798   ierr = PetscFree(a->diag);CHKERRQ(ierr);
799   ierr = PetscFree2(a->imax,a->ilen);CHKERRQ(ierr);
800   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
801   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
802   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);}
803   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
804   if (a->coloring) {ierr = ISColoringDestroy(a->coloring);CHKERRQ(ierr);}
805   ierr = PetscFree(a->xtoy);CHKERRQ(ierr);
806   if (a->XtoY) {ierr = MatDestroy(a->XtoY);CHKERRQ(ierr);}
807   if (a->compressedrow.checked && a->compressedrow.use){ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);}
808 
809   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
810 
811   ierr = PetscFree(a);CHKERRQ(ierr);
812 
813   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
814   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetColumnIndices_C","",PETSC_NULL);CHKERRQ(ierr);
815   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatStoreValues_C","",PETSC_NULL);CHKERRQ(ierr);
816   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatRetrieveValues_C","",PETSC_NULL);CHKERRQ(ierr);
817   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqsbaij_C","",PETSC_NULL);CHKERRQ(ierr);
818   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqbaij_C","",PETSC_NULL);CHKERRQ(ierr);
819   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatConvert_seqaij_seqcsrperm_C","",PETSC_NULL);CHKERRQ(ierr);
820   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatIsTranspose_C","",PETSC_NULL);CHKERRQ(ierr);
821   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr);
822   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C","",PETSC_NULL);CHKERRQ(ierr);
823   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatReorderForNonzeroDiagonal_C","",PETSC_NULL);CHKERRQ(ierr);
824   PetscFunctionReturn(0);
825 }
826 
827 #undef __FUNCT__
828 #define __FUNCT__ "MatSetOption_SeqAIJ"
829 PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscTruth flg)
830 {
831   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
832   PetscErrorCode ierr;
833 
834   PetscFunctionBegin;
835   switch (op) {
836     case MAT_ROW_ORIENTED:
837       a->roworiented       = flg;
838       break;
839     case MAT_KEEP_NONZERO_PATTERN:
840       a->keepnonzeropattern    = flg;
841       break;
842     case MAT_NEW_NONZERO_LOCATIONS:
843       a->nonew             = (flg ? 0 : 1);
844       break;
845     case MAT_NEW_NONZERO_LOCATION_ERR:
846       a->nonew             = (flg ? -1 : 0);
847       break;
848     case MAT_NEW_NONZERO_ALLOCATION_ERR:
849       a->nonew             = (flg ? -2 : 0);
850       break;
851     case MAT_UNUSED_NONZERO_LOCATION_ERR:
852       a->nounused          = (flg ? -1 : 0);
853       break;
854     case MAT_IGNORE_ZERO_ENTRIES:
855       a->ignorezeroentries = flg;
856       break;
857     case MAT_USE_COMPRESSEDROW:
858       a->compressedrow.use = flg;
859       break;
860     case MAT_SYMMETRIC:
861     case MAT_STRUCTURALLY_SYMMETRIC:
862     case MAT_HERMITIAN:
863     case MAT_SYMMETRY_ETERNAL:
864     case MAT_NEW_DIAGONALS:
865     case MAT_IGNORE_OFF_PROC_ENTRIES:
866     case MAT_USE_HASH_TABLE:
867       ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
868       break;
869     case MAT_USE_INODES:
870       /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */
871       break;
872     default:
873       SETERRQ1(PETSC_ERR_SUP,"unknown option %d",op);
874   }
875   ierr = MatSetOption_SeqAIJ_Inode(A,op,flg);CHKERRQ(ierr);
876   PetscFunctionReturn(0);
877 }
878 
879 #undef __FUNCT__
880 #define __FUNCT__ "MatGetDiagonal_SeqAIJ"
881 PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
882 {
883   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
884   PetscErrorCode ierr;
885   PetscInt       i,j,n;
886   PetscScalar    *x,zero = 0.0;
887 
888   PetscFunctionBegin;
889   ierr = VecSet(v,zero);CHKERRQ(ierr);
890   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
891   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
892   if (n != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
893   for (i=0; i<A->rmap->n; i++) {
894     for (j=a->i[i]; j<a->i[i+1]; j++) {
895       if (a->j[j] == i) {
896         x[i] = a->a[j];
897         break;
898       }
899     }
900   }
901   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
902   PetscFunctionReturn(0);
903 }
904 
905 #include "../src/mat/impls/aij/seq/ftn-kernels/fmult.h"
906 #undef __FUNCT__
907 #define __FUNCT__ "MatMultTransposeAdd_SeqAIJ"
908 PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
909 {
910   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
911   PetscScalar       *x,*y;
912   PetscErrorCode    ierr;
913   PetscInt          m = A->rmap->n;
914 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
915   MatScalar         *v;
916   PetscScalar       alpha;
917   PetscInt          n,i,j,*idx,*ii,*ridx=PETSC_NULL;
918   Mat_CompressedRow cprow = a->compressedrow;
919   PetscTruth        usecprow = cprow.use;
920 #endif
921 
922   PetscFunctionBegin;
923   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
924   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
925   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
926 
927 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
928   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
929 #else
930   if (usecprow){
931     m    = cprow.nrows;
932     ii   = cprow.i;
933     ridx = cprow.rindex;
934   } else {
935     ii = a->i;
936   }
937   for (i=0; i<m; i++) {
938     idx   = a->j + ii[i] ;
939     v     = a->a + ii[i] ;
940     n     = ii[i+1] - ii[i];
941     if (usecprow){
942       alpha = x[ridx[i]];
943     } else {
944       alpha = x[i];
945     }
946     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
947   }
948 #endif
949   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
950   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
951   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
952   PetscFunctionReturn(0);
953 }
954 
955 #undef __FUNCT__
956 #define __FUNCT__ "MatMultTranspose_SeqAIJ"
957 PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
958 {
959   PetscErrorCode ierr;
960 
961   PetscFunctionBegin;
962   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
963   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
964   PetscFunctionReturn(0);
965 }
966 
967 #include "../src/mat/impls/aij/seq/ftn-kernels/fmult.h"
968 #undef __FUNCT__
969 #define __FUNCT__ "MatMult_SeqAIJ"
970 PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
971 {
972   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
973   PetscScalar       *y;
974   const PetscScalar *x;
975   const MatScalar   *aa;
976   PetscErrorCode    ierr;
977   PetscInt          m=A->rmap->n;
978   const PetscInt    *aj,*ii,*ridx=PETSC_NULL;
979   PetscInt          n,i,nonzerorow=0;
980   PetscScalar       sum;
981   PetscTruth        usecprow=a->compressedrow.use;
982 
983 #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
984 #pragma disjoint(*x,*y,*aa)
985 #endif
986 
987   PetscFunctionBegin;
988   ierr = VecGetArray(xx,(PetscScalar**)&x);CHKERRQ(ierr);
989   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
990   aj  = a->j;
991   aa  = a->a;
992   ii  = a->i;
993   if (usecprow){ /* use compressed row format */
994     m    = a->compressedrow.nrows;
995     ii   = a->compressedrow.i;
996     ridx = a->compressedrow.rindex;
997     for (i=0; i<m; i++){
998       n   = ii[i+1] - ii[i];
999       aj  = a->j + ii[i];
1000       aa  = a->a + ii[i];
1001       sum = 0.0;
1002       nonzerorow += (n>0);
1003       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1004       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1005       y[*ridx++] = sum;
1006     }
1007   } else { /* do not use compressed row format */
1008 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
1009     fortranmultaij_(&m,x,ii,aj,aa,y);
1010 #else
1011     for (i=0; i<m; i++) {
1012       n   = ii[i+1] - ii[i];
1013       aj  = a->j + ii[i];
1014       aa  = a->a + ii[i];
1015       sum  = 0.0;
1016       nonzerorow += (n>0);
1017       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1018       y[i] = sum;
1019     }
1020 #endif
1021   }
1022   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1023   ierr = VecRestoreArray(xx,(PetscScalar**)&x);CHKERRQ(ierr);
1024   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1025   PetscFunctionReturn(0);
1026 }
1027 
1028 #include "../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h"
1029 #undef __FUNCT__
1030 #define __FUNCT__ "MatMultAdd_SeqAIJ"
1031 PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1032 {
1033   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
1034   PetscScalar     *x,*y,*z;
1035   const MatScalar *aa;
1036   PetscErrorCode  ierr;
1037   PetscInt        m = A->rmap->n,*aj,*ii;
1038 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
1039   PetscInt        n,i,jrow,j,*ridx=PETSC_NULL;
1040   PetscScalar     sum;
1041   PetscTruth      usecprow=a->compressedrow.use;
1042 #endif
1043 
1044   PetscFunctionBegin;
1045   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
1046   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1047   if (zz != yy) {
1048     ierr = VecGetArray(zz,&z);CHKERRQ(ierr);
1049   } else {
1050     z = y;
1051   }
1052 
1053   aj  = a->j;
1054   aa  = a->a;
1055   ii  = a->i;
1056 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
1057   fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1058 #else
1059   if (usecprow){ /* use compressed row format */
1060     if (zz != yy){
1061       ierr = PetscMemcpy(z,y,m*sizeof(PetscScalar));CHKERRQ(ierr);
1062     }
1063     m    = a->compressedrow.nrows;
1064     ii   = a->compressedrow.i;
1065     ridx = a->compressedrow.rindex;
1066     for (i=0; i<m; i++){
1067       n  = ii[i+1] - ii[i];
1068       aj  = a->j + ii[i];
1069       aa  = a->a + ii[i];
1070       sum = y[*ridx];
1071       for (j=0; j<n; j++) sum += (*aa++)*x[*aj++];
1072       z[*ridx++] = sum;
1073     }
1074   } else { /* do not use compressed row format */
1075     for (i=0; i<m; i++) {
1076       jrow = ii[i];
1077       n    = ii[i+1] - jrow;
1078       sum  = y[i];
1079       for (j=0; j<n; j++) {
1080         sum += aa[jrow]*x[aj[jrow]]; jrow++;
1081       }
1082       z[i] = sum;
1083     }
1084   }
1085 #endif
1086   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1087   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1088   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1089   if (zz != yy) {
1090     ierr = VecRestoreArray(zz,&z);CHKERRQ(ierr);
1091   }
1092   PetscFunctionReturn(0);
1093 }
1094 
1095 /*
1096      Adds diagonal pointers to sparse matrix structure.
1097 */
1098 #undef __FUNCT__
1099 #define __FUNCT__ "MatMarkDiagonal_SeqAIJ"
1100 PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
1101 {
1102   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1103   PetscErrorCode ierr;
1104   PetscInt       i,j,m = A->rmap->n;
1105 
1106   PetscFunctionBegin;
1107   if (!a->diag) {
1108     ierr = PetscMalloc(m*sizeof(PetscInt),&a->diag);CHKERRQ(ierr);
1109     ierr = PetscLogObjectMemory(A, m*sizeof(PetscInt));CHKERRQ(ierr);
1110   }
1111   for (i=0; i<A->rmap->n; i++) {
1112     a->diag[i] = a->i[i+1];
1113     for (j=a->i[i]; j<a->i[i+1]; j++) {
1114       if (a->j[j] == i) {
1115         a->diag[i] = j;
1116         break;
1117       }
1118     }
1119   }
1120   PetscFunctionReturn(0);
1121 }
1122 
1123 /*
1124      Checks for missing diagonals
1125 */
1126 #undef __FUNCT__
1127 #define __FUNCT__ "MatMissingDiagonal_SeqAIJ"
1128 PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscTruth *missing,PetscInt *d)
1129 {
1130   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1131   PetscInt       *diag,*jj = a->j,i;
1132 
1133   PetscFunctionBegin;
1134   *missing = PETSC_FALSE;
1135   if (A->rmap->n > 0 && !jj) {
1136     *missing  = PETSC_TRUE;
1137     if (d) *d = 0;
1138     PetscInfo(A,"Matrix has no entries therefor is missing diagonal");
1139   } else {
1140     diag = a->diag;
1141     for (i=0; i<A->rmap->n; i++) {
1142       if (jj[diag[i]] != i) {
1143 	*missing = PETSC_TRUE;
1144 	if (d) *d = i;
1145 	PetscInfo1(A,"Matrix is missing diagonal number %D",i);
1146       }
1147     }
1148   }
1149   PetscFunctionReturn(0);
1150 }
1151 
1152 EXTERN_C_BEGIN
1153 #undef __FUNCT__
1154 #define __FUNCT__ "MatInvertDiagonal_SeqAIJ"
1155 PetscErrorCode PETSCMAT_DLLEXPORT MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
1156 {
1157   Mat_SeqAIJ     *a = (Mat_SeqAIJ*) A->data;
1158   PetscErrorCode ierr;
1159   PetscInt       i,*diag,m = A->rmap->n;
1160   MatScalar      *v = a->a;
1161   PetscScalar    *idiag,*mdiag;
1162 
1163   PetscFunctionBegin;
1164   if (a->idiagvalid) PetscFunctionReturn(0);
1165   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1166   diag = a->diag;
1167   if (!a->idiag) {
1168     ierr     = PetscMalloc3(m,PetscScalar,&a->idiag,m,PetscScalar,&a->mdiag,m,PetscScalar,&a->ssor_work);CHKERRQ(ierr);
1169     ierr     = PetscLogObjectMemory(A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr);
1170     v        = a->a;
1171   }
1172   mdiag = a->mdiag;
1173   idiag = a->idiag;
1174 
1175   if (omega == 1.0 && !PetscAbsScalar(fshift)) {
1176     for (i=0; i<m; i++) {
1177       mdiag[i] = v[diag[i]];
1178       if (!PetscAbsScalar(mdiag[i])) SETERRQ1(PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1179       idiag[i] = 1.0/v[diag[i]];
1180     }
1181     ierr = PetscLogFlops(m);CHKERRQ(ierr);
1182   } else {
1183     for (i=0; i<m; i++) {
1184       mdiag[i] = v[diag[i]];
1185       idiag[i] = omega/(fshift + v[diag[i]]);
1186     }
1187     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
1188   }
1189   a->idiagvalid = PETSC_TRUE;
1190   PetscFunctionReturn(0);
1191 }
1192 EXTERN_C_END
1193 
1194 #include "../src/mat/impls/aij/seq/ftn-kernels/frelax.h"
1195 #undef __FUNCT__
1196 #define __FUNCT__ "MatSOR_SeqAIJ"
1197 PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
1198 {
1199   Mat_SeqAIJ         *a = (Mat_SeqAIJ*)A->data;
1200   PetscScalar        *x,d,sum,*t,scale;
1201   const MatScalar    *v = a->a,*idiag=0,*mdiag;
1202   const PetscScalar  *b, *bs,*xb, *ts;
1203   PetscErrorCode     ierr;
1204   PetscInt           n = A->cmap->n,m = A->rmap->n,i;
1205   const PetscInt     *idx,*diag;
1206 
1207   PetscFunctionBegin;
1208   its = its*lits;
1209 
1210   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
1211   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
1212   a->fshift = fshift;
1213   a->omega  = omega;
1214 
1215   diag = a->diag;
1216   t     = a->ssor_work;
1217   idiag = a->idiag;
1218   mdiag = a->mdiag;
1219 
1220   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
1221   if (xx != bb) {
1222     ierr = VecGetArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);
1223   } else {
1224     b = x;
1225   }
1226   CHKMEMQ;
1227   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
1228   if (flag == SOR_APPLY_UPPER) {
1229    /* apply (U + D/omega) to the vector */
1230     bs = b;
1231     for (i=0; i<m; i++) {
1232         d    = fshift + mdiag[i];
1233         n    = a->i[i+1] - diag[i] - 1;
1234         idx  = a->j + diag[i] + 1;
1235         v    = a->a + diag[i] + 1;
1236         sum  = b[i]*d/omega;
1237         PetscSparseDensePlusDot(sum,bs,v,idx,n);
1238         x[i] = sum;
1239     }
1240     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1241     if (bb != xx) {ierr = VecRestoreArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);}
1242     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
1243     PetscFunctionReturn(0);
1244   }
1245 
1246   if (flag == SOR_APPLY_LOWER) {
1247     SETERRQ(PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
1248   } else if (flag & SOR_EISENSTAT) {
1249     /* Let  A = L + U + D; where L is lower trianglar,
1250     U is upper triangular, E = D/omega; This routine applies
1251 
1252             (L + E)^{-1} A (U + E)^{-1}
1253 
1254     to a vector efficiently using Eisenstat's trick.
1255     */
1256     scale = (2.0/omega) - 1.0;
1257 
1258     /*  x = (E + U)^{-1} b */
1259     for (i=m-1; i>=0; i--) {
1260       n    = a->i[i+1] - diag[i] - 1;
1261       idx  = a->j + diag[i] + 1;
1262       v    = a->a + diag[i] + 1;
1263       sum  = b[i];
1264       PetscSparseDenseMinusDot(sum,x,v,idx,n);
1265       x[i] = sum*idiag[i];
1266     }
1267 
1268     /*  t = b - (2*E - D)x */
1269     v = a->a;
1270     for (i=0; i<m; i++) { t[i] = b[i] - scale*(v[*diag++])*x[i]; }
1271 
1272     /*  t = (E + L)^{-1}t */
1273     ts = t;
1274     diag = a->diag;
1275     for (i=0; i<m; i++) {
1276       n    = diag[i] - a->i[i];
1277       idx  = a->j + a->i[i];
1278       v    = a->a + a->i[i];
1279       sum  = t[i];
1280       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
1281       t[i] = sum*idiag[i];
1282       /*  x = x + t */
1283       x[i] += t[i];
1284     }
1285 
1286     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
1287     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1288     if (bb != xx) {ierr = VecRestoreArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);}
1289     PetscFunctionReturn(0);
1290   }
1291   if (flag & SOR_ZERO_INITIAL_GUESS) {
1292     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1293       for (i=0; i<m; i++) {
1294         n    = diag[i] - a->i[i];
1295         idx  = a->j + a->i[i];
1296         v    = a->a + a->i[i];
1297         sum  = b[i];
1298         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1299         t[i] = sum;
1300         x[i] = sum*idiag[i];
1301       }
1302       xb = t;
1303       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
1304     } else xb = b;
1305     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1306       for (i=m-1; i>=0; i--) {
1307         n    = a->i[i+1] - diag[i] - 1;
1308         idx  = a->j + diag[i] + 1;
1309         v    = a->a + diag[i] + 1;
1310         sum  = xb[i];
1311         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1312         if (xb == b) {
1313           x[i] = sum*idiag[i];
1314         } else {
1315           x[i] = (1-omega)*x[i] + sum*idiag[i];
1316         }
1317       }
1318       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
1319     }
1320     its--;
1321   }
1322   while (its--) {
1323     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1324       for (i=0; i<m; i++) {
1325         n    = a->i[i+1] - a->i[i];
1326         idx  = a->j + a->i[i];
1327         v    = a->a + a->i[i];
1328         sum  = b[i];
1329         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1330         x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1331       }
1332       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1333     }
1334     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1335       for (i=m-1; i>=0; i--) {
1336         n    = a->i[i+1] - a->i[i];
1337         idx  = a->j + a->i[i];
1338         v    = a->a + a->i[i];
1339         sum  = b[i];
1340         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1341         x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1342       }
1343       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1344     }
1345   }
1346   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1347   if (bb != xx) {ierr = VecRestoreArray(bb,(PetscScalar**)&b);CHKERRQ(ierr);}
1348   CHKMEMQ;  PetscFunctionReturn(0);
1349 }
1350 
1351 
1352 #undef __FUNCT__
1353 #define __FUNCT__ "MatGetInfo_SeqAIJ"
1354 PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
1355 {
1356   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1357 
1358   PetscFunctionBegin;
1359   info->block_size     = 1.0;
1360   info->nz_allocated   = (double)a->maxnz;
1361   info->nz_used        = (double)a->nz;
1362   info->nz_unneeded    = (double)(a->maxnz - a->nz);
1363   info->assemblies     = (double)A->num_ass;
1364   info->mallocs        = (double)a->reallocs;
1365   info->memory         = ((PetscObject)A)->mem;
1366   if (A->factor) {
1367     info->fill_ratio_given  = A->info.fill_ratio_given;
1368     info->fill_ratio_needed = A->info.fill_ratio_needed;
1369     info->factor_mallocs    = A->info.factor_mallocs;
1370   } else {
1371     info->fill_ratio_given  = 0;
1372     info->fill_ratio_needed = 0;
1373     info->factor_mallocs    = 0;
1374   }
1375   PetscFunctionReturn(0);
1376 }
1377 
1378 #undef __FUNCT__
1379 #define __FUNCT__ "MatZeroRows_SeqAIJ"
1380 PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag)
1381 {
1382   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1383   PetscInt       i,m = A->rmap->n - 1,d;
1384   PetscErrorCode ierr;
1385   PetscTruth     missing;
1386 
1387   PetscFunctionBegin;
1388   if (a->keepnonzeropattern) {
1389     for (i=0; i<N; i++) {
1390       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1391       ierr = PetscMemzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]*sizeof(PetscScalar));CHKERRQ(ierr);
1392     }
1393     if (diag != 0.0) {
1394       ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
1395       if (missing) SETERRQ1(PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D",d);
1396       for (i=0; i<N; i++) {
1397         a->a[a->diag[rows[i]]] = diag;
1398       }
1399     }
1400     A->same_nonzero = PETSC_TRUE;
1401   } else {
1402     if (diag != 0.0) {
1403       for (i=0; i<N; i++) {
1404         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1405         if (a->ilen[rows[i]] > 0) {
1406           a->ilen[rows[i]]          = 1;
1407           a->a[a->i[rows[i]]] = diag;
1408           a->j[a->i[rows[i]]] = rows[i];
1409         } else { /* in case row was completely empty */
1410           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
1411         }
1412       }
1413     } else {
1414       for (i=0; i<N; i++) {
1415         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
1416         a->ilen[rows[i]] = 0;
1417       }
1418     }
1419     A->same_nonzero = PETSC_FALSE;
1420   }
1421   ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1422   PetscFunctionReturn(0);
1423 }
1424 
1425 #undef __FUNCT__
1426 #define __FUNCT__ "MatGetRow_SeqAIJ"
1427 PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1428 {
1429   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1430   PetscInt   *itmp;
1431 
1432   PetscFunctionBegin;
1433   if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row);
1434 
1435   *nz = a->i[row+1] - a->i[row];
1436   if (v) *v = a->a + a->i[row];
1437   if (idx) {
1438     itmp = a->j + a->i[row];
1439     if (*nz) {
1440       *idx = itmp;
1441     }
1442     else *idx = 0;
1443   }
1444   PetscFunctionReturn(0);
1445 }
1446 
1447 /* remove this function? */
1448 #undef __FUNCT__
1449 #define __FUNCT__ "MatRestoreRow_SeqAIJ"
1450 PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1451 {
1452   PetscFunctionBegin;
1453   PetscFunctionReturn(0);
1454 }
1455 
1456 #undef __FUNCT__
1457 #define __FUNCT__ "MatNorm_SeqAIJ"
1458 PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
1459 {
1460   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1461   MatScalar      *v = a->a;
1462   PetscReal      sum = 0.0;
1463   PetscErrorCode ierr;
1464   PetscInt       i,j;
1465 
1466   PetscFunctionBegin;
1467   if (type == NORM_FROBENIUS) {
1468     for (i=0; i<a->nz; i++) {
1469 #if defined(PETSC_USE_COMPLEX)
1470       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1471 #else
1472       sum += (*v)*(*v); v++;
1473 #endif
1474     }
1475     *nrm = sqrt(sum);
1476   } else if (type == NORM_1) {
1477     PetscReal *tmp;
1478     PetscInt    *jj = a->j;
1479     ierr = PetscMalloc((A->cmap->n+1)*sizeof(PetscReal),&tmp);CHKERRQ(ierr);
1480     ierr = PetscMemzero(tmp,A->cmap->n*sizeof(PetscReal));CHKERRQ(ierr);
1481     *nrm = 0.0;
1482     for (j=0; j<a->nz; j++) {
1483         tmp[*jj++] += PetscAbsScalar(*v);  v++;
1484     }
1485     for (j=0; j<A->cmap->n; j++) {
1486       if (tmp[j] > *nrm) *nrm = tmp[j];
1487     }
1488     ierr = PetscFree(tmp);CHKERRQ(ierr);
1489   } else if (type == NORM_INFINITY) {
1490     *nrm = 0.0;
1491     for (j=0; j<A->rmap->n; j++) {
1492       v = a->a + a->i[j];
1493       sum = 0.0;
1494       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
1495         sum += PetscAbsScalar(*v); v++;
1496       }
1497       if (sum > *nrm) *nrm = sum;
1498     }
1499   } else {
1500     SETERRQ(PETSC_ERR_SUP,"No support for two norm");
1501   }
1502   PetscFunctionReturn(0);
1503 }
1504 
1505 #undef __FUNCT__
1506 #define __FUNCT__ "MatTranspose_SeqAIJ"
1507 PetscErrorCode MatTranspose_SeqAIJ(Mat A,MatReuse reuse,Mat *B)
1508 {
1509   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1510   Mat            C;
1511   PetscErrorCode ierr;
1512   PetscInt       i,*aj = a->j,*ai = a->i,m = A->rmap->n,len,*col;
1513   MatScalar      *array = a->a;
1514 
1515   PetscFunctionBegin;
1516   if (reuse == MAT_REUSE_MATRIX && A == *B && m != A->cmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Square matrix only for in-place");
1517 
1518   if (reuse == MAT_INITIAL_MATRIX || *B == A) {
1519     ierr = PetscMalloc((1+A->cmap->n)*sizeof(PetscInt),&col);CHKERRQ(ierr);
1520     ierr = PetscMemzero(col,(1+A->cmap->n)*sizeof(PetscInt));CHKERRQ(ierr);
1521 
1522     for (i=0; i<ai[m]; i++) col[aj[i]] += 1;
1523     ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
1524     ierr = MatSetSizes(C,A->cmap->n,m,A->cmap->n,m);CHKERRQ(ierr);
1525     ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
1526     ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,col);CHKERRQ(ierr);
1527     ierr = PetscFree(col);CHKERRQ(ierr);
1528   } else {
1529     C = *B;
1530   }
1531 
1532   for (i=0; i<m; i++) {
1533     len    = ai[i+1]-ai[i];
1534     ierr   = MatSetValues_SeqAIJ(C,len,aj,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1535     array += len;
1536     aj    += len;
1537   }
1538   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1539   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1540 
1541   if (reuse == MAT_INITIAL_MATRIX || *B != A) {
1542     *B = C;
1543   } else {
1544     ierr = MatHeaderCopy(A,C);CHKERRQ(ierr);
1545   }
1546   PetscFunctionReturn(0);
1547 }
1548 
1549 EXTERN_C_BEGIN
1550 #undef __FUNCT__
1551 #define __FUNCT__ "MatIsTranspose_SeqAIJ"
1552 PetscErrorCode PETSCMAT_DLLEXPORT MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscTruth *f)
1553 {
1554   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1555   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
1556   MatScalar      *va,*vb;
1557   PetscErrorCode ierr;
1558   PetscInt       ma,na,mb,nb, i;
1559 
1560   PetscFunctionBegin;
1561   bij = (Mat_SeqAIJ *) B->data;
1562 
1563   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
1564   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
1565   if (ma!=nb || na!=mb){
1566     *f = PETSC_FALSE;
1567     PetscFunctionReturn(0);
1568   }
1569   aii = aij->i; bii = bij->i;
1570   adx = aij->j; bdx = bij->j;
1571   va  = aij->a; vb = bij->a;
1572   ierr = PetscMalloc(ma*sizeof(PetscInt),&aptr);CHKERRQ(ierr);
1573   ierr = PetscMalloc(mb*sizeof(PetscInt),&bptr);CHKERRQ(ierr);
1574   for (i=0; i<ma; i++) aptr[i] = aii[i];
1575   for (i=0; i<mb; i++) bptr[i] = bii[i];
1576 
1577   *f = PETSC_TRUE;
1578   for (i=0; i<ma; i++) {
1579     while (aptr[i]<aii[i+1]) {
1580       PetscInt         idc,idr;
1581       PetscScalar vc,vr;
1582       /* column/row index/value */
1583       idc = adx[aptr[i]];
1584       idr = bdx[bptr[idc]];
1585       vc  = va[aptr[i]];
1586       vr  = vb[bptr[idc]];
1587       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
1588 	*f = PETSC_FALSE;
1589         goto done;
1590       } else {
1591 	aptr[i]++;
1592         if (B || i!=idc) bptr[idc]++;
1593       }
1594     }
1595   }
1596  done:
1597   ierr = PetscFree(aptr);CHKERRQ(ierr);
1598   if (B) {
1599     ierr = PetscFree(bptr);CHKERRQ(ierr);
1600   }
1601   PetscFunctionReturn(0);
1602 }
1603 EXTERN_C_END
1604 
1605 EXTERN_C_BEGIN
1606 #undef __FUNCT__
1607 #define __FUNCT__ "MatIsHermitianTranspose_SeqAIJ"
1608 PetscErrorCode PETSCMAT_DLLEXPORT MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscTruth *f)
1609 {
1610   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *) A->data,*bij = (Mat_SeqAIJ*) A->data;
1611   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
1612   MatScalar      *va,*vb;
1613   PetscErrorCode ierr;
1614   PetscInt       ma,na,mb,nb, i;
1615 
1616   PetscFunctionBegin;
1617   bij = (Mat_SeqAIJ *) B->data;
1618 
1619   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
1620   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
1621   if (ma!=nb || na!=mb){
1622     *f = PETSC_FALSE;
1623     PetscFunctionReturn(0);
1624   }
1625   aii = aij->i; bii = bij->i;
1626   adx = aij->j; bdx = bij->j;
1627   va  = aij->a; vb = bij->a;
1628   ierr = PetscMalloc(ma*sizeof(PetscInt),&aptr);CHKERRQ(ierr);
1629   ierr = PetscMalloc(mb*sizeof(PetscInt),&bptr);CHKERRQ(ierr);
1630   for (i=0; i<ma; i++) aptr[i] = aii[i];
1631   for (i=0; i<mb; i++) bptr[i] = bii[i];
1632 
1633   *f = PETSC_TRUE;
1634   for (i=0; i<ma; i++) {
1635     while (aptr[i]<aii[i+1]) {
1636       PetscInt         idc,idr;
1637       PetscScalar vc,vr;
1638       /* column/row index/value */
1639       idc = adx[aptr[i]];
1640       idr = bdx[bptr[idc]];
1641       vc  = va[aptr[i]];
1642       vr  = vb[bptr[idc]];
1643       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
1644 	*f = PETSC_FALSE;
1645         goto done;
1646       } else {
1647 	aptr[i]++;
1648         if (B || i!=idc) bptr[idc]++;
1649       }
1650     }
1651   }
1652  done:
1653   ierr = PetscFree(aptr);CHKERRQ(ierr);
1654   if (B) {
1655     ierr = PetscFree(bptr);CHKERRQ(ierr);
1656   }
1657   PetscFunctionReturn(0);
1658 }
1659 EXTERN_C_END
1660 
1661 #undef __FUNCT__
1662 #define __FUNCT__ "MatIsSymmetric_SeqAIJ"
1663 PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscTruth *f)
1664 {
1665   PetscErrorCode ierr;
1666   PetscFunctionBegin;
1667   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
1668   PetscFunctionReturn(0);
1669 }
1670 
1671 #undef __FUNCT__
1672 #define __FUNCT__ "MatIsHermitian_SeqAIJ"
1673 PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscTruth *f)
1674 {
1675   PetscErrorCode ierr;
1676   PetscFunctionBegin;
1677   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
1678   PetscFunctionReturn(0);
1679 }
1680 
1681 #undef __FUNCT__
1682 #define __FUNCT__ "MatDiagonalScale_SeqAIJ"
1683 PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
1684 {
1685   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1686   PetscScalar    *l,*r,x;
1687   MatScalar      *v;
1688   PetscErrorCode ierr;
1689   PetscInt       i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz,*jj;
1690 
1691   PetscFunctionBegin;
1692   if (ll) {
1693     /* The local size is used so that VecMPI can be passed to this routine
1694        by MatDiagonalScale_MPIAIJ */
1695     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
1696     if (m != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
1697     ierr = VecGetArray(ll,&l);CHKERRQ(ierr);
1698     v = a->a;
1699     for (i=0; i<m; i++) {
1700       x = l[i];
1701       M = a->i[i+1] - a->i[i];
1702       for (j=0; j<M; j++) { (*v++) *= x;}
1703     }
1704     ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr);
1705     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
1706   }
1707   if (rr) {
1708     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
1709     if (n != A->cmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
1710     ierr = VecGetArray(rr,&r);CHKERRQ(ierr);
1711     v = a->a; jj = a->j;
1712     for (i=0; i<nz; i++) {
1713       (*v++) *= r[*jj++];
1714     }
1715     ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr);
1716     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
1717   }
1718   PetscFunctionReturn(0);
1719 }
1720 
1721 #undef __FUNCT__
1722 #define __FUNCT__ "MatGetSubMatrix_SeqAIJ"
1723 PetscErrorCode MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
1724 {
1725   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*c;
1726   PetscErrorCode ierr;
1727   PetscInt       *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
1728   PetscInt       row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
1729   const PetscInt *irow,*icol;
1730   PetscInt       nrows,ncols;
1731   PetscInt       *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
1732   MatScalar      *a_new,*mat_a;
1733   Mat            C;
1734   PetscTruth     stride,sorted;
1735 
1736   PetscFunctionBegin;
1737   ierr = ISSorted(isrow,&sorted);CHKERRQ(ierr);
1738   if (!sorted) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted");
1739   ierr = ISSorted(iscol,&sorted);CHKERRQ(ierr);
1740   if (!sorted) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted");
1741 
1742   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
1743   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
1744   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
1745 
1746   ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
1747   ierr = ISStride(iscol,&stride);CHKERRQ(ierr);
1748   if (stride && step == 1) {
1749     /* special case of contiguous rows */
1750     ierr = PetscMalloc2(nrows,PetscInt,&lens,nrows,PetscInt,&starts);CHKERRQ(ierr);
1751     /* loop over new rows determining lens and starting points */
1752     for (i=0; i<nrows; i++) {
1753       kstart  = ai[irow[i]];
1754       kend    = kstart + ailen[irow[i]];
1755       for (k=kstart; k<kend; k++) {
1756         if (aj[k] >= first) {
1757           starts[i] = k;
1758           break;
1759 	}
1760       }
1761       sum = 0;
1762       while (k < kend) {
1763         if (aj[k++] >= first+ncols) break;
1764         sum++;
1765       }
1766       lens[i] = sum;
1767     }
1768     /* create submatrix */
1769     if (scall == MAT_REUSE_MATRIX) {
1770       PetscInt n_cols,n_rows;
1771       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
1772       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
1773       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
1774       C = *B;
1775     } else {
1776       ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
1777       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
1778       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
1779       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
1780     }
1781     c = (Mat_SeqAIJ*)C->data;
1782 
1783     /* loop over rows inserting into submatrix */
1784     a_new    = c->a;
1785     j_new    = c->j;
1786     i_new    = c->i;
1787 
1788     for (i=0; i<nrows; i++) {
1789       ii    = starts[i];
1790       lensi = lens[i];
1791       for (k=0; k<lensi; k++) {
1792         *j_new++ = aj[ii+k] - first;
1793       }
1794       ierr = PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));CHKERRQ(ierr);
1795       a_new      += lensi;
1796       i_new[i+1]  = i_new[i] + lensi;
1797       c->ilen[i]  = lensi;
1798     }
1799     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
1800   } else {
1801     ierr  = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
1802     ierr  = PetscMalloc(oldcols*sizeof(PetscInt),&smap);CHKERRQ(ierr);
1803     ierr  = PetscMemzero(smap,oldcols*sizeof(PetscInt));CHKERRQ(ierr);
1804     ierr  = PetscMalloc((1+nrows)*sizeof(PetscInt),&lens);CHKERRQ(ierr);
1805     for (i=0; i<ncols; i++) smap[icol[i]] = i+1;
1806     /* determine lens of each row */
1807     for (i=0; i<nrows; i++) {
1808       kstart  = ai[irow[i]];
1809       kend    = kstart + a->ilen[irow[i]];
1810       lens[i] = 0;
1811       for (k=kstart; k<kend; k++) {
1812         if (smap[aj[k]]) {
1813           lens[i]++;
1814         }
1815       }
1816     }
1817     /* Create and fill new matrix */
1818     if (scall == MAT_REUSE_MATRIX) {
1819       PetscTruth equal;
1820 
1821       c = (Mat_SeqAIJ *)((*B)->data);
1822       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
1823       ierr = PetscMemcmp(c->ilen,lens,(*B)->rmap->n*sizeof(PetscInt),&equal);CHKERRQ(ierr);
1824       if (!equal) {
1825         SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
1826       }
1827       ierr = PetscMemzero(c->ilen,(*B)->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
1828       C = *B;
1829     } else {
1830       ierr = MatCreate(((PetscObject)A)->comm,&C);CHKERRQ(ierr);
1831       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
1832       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
1833       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
1834     }
1835     c = (Mat_SeqAIJ *)(C->data);
1836     for (i=0; i<nrows; i++) {
1837       row    = irow[i];
1838       kstart = ai[row];
1839       kend   = kstart + a->ilen[row];
1840       mat_i  = c->i[i];
1841       mat_j  = c->j + mat_i;
1842       mat_a  = c->a + mat_i;
1843       mat_ilen = c->ilen + i;
1844       for (k=kstart; k<kend; k++) {
1845         if ((tcol=smap[a->j[k]])) {
1846           *mat_j++ = tcol - 1;
1847           *mat_a++ = a->a[k];
1848           (*mat_ilen)++;
1849 
1850         }
1851       }
1852     }
1853     /* Free work space */
1854     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
1855     ierr = PetscFree(smap);CHKERRQ(ierr);
1856     ierr = PetscFree(lens);CHKERRQ(ierr);
1857   }
1858   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1859   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1860 
1861   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
1862   *B = C;
1863   PetscFunctionReturn(0);
1864 }
1865 
1866 #undef __FUNCT__
1867 #define __FUNCT__ "MatILUFactor_SeqAIJ"
1868 PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
1869 {
1870   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
1871   PetscErrorCode ierr;
1872   Mat            outA;
1873   PetscTruth     row_identity,col_identity;
1874 
1875   PetscFunctionBegin;
1876   if (info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
1877 
1878   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
1879   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
1880 
1881   outA          = inA;
1882   outA->factor  = MAT_FACTOR_LU;
1883   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
1884   if (a->row) { ierr = ISDestroy(a->row);CHKERRQ(ierr);}
1885   a->row = row;
1886   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
1887   if (a->col) { ierr = ISDestroy(a->col);CHKERRQ(ierr);}
1888   a->col = col;
1889 
1890   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
1891   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} /* need to remove old one */
1892   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
1893   ierr = PetscLogObjectParent(inA,a->icol);CHKERRQ(ierr);
1894 
1895   if (!a->solve_work) { /* this matrix may have been factored before */
1896      ierr = PetscMalloc((inA->rmap->n+1)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr);
1897      ierr = PetscLogObjectMemory(inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
1898   }
1899 
1900   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
1901   if (row_identity && col_identity) {
1902     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
1903   } else {
1904     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
1905   }
1906   PetscFunctionReturn(0);
1907 }
1908 
1909 #include "petscblaslapack.h"
1910 #undef __FUNCT__
1911 #define __FUNCT__ "MatScale_SeqAIJ"
1912 PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
1913 {
1914   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
1915   PetscScalar    oalpha = alpha;
1916   PetscErrorCode ierr;
1917   PetscBLASInt   one = 1,bnz = PetscBLASIntCast(a->nz);
1918 
1919   PetscFunctionBegin;
1920   BLASscal_(&bnz,&oalpha,a->a,&one);
1921   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
1922   PetscFunctionReturn(0);
1923 }
1924 
1925 #undef __FUNCT__
1926 #define __FUNCT__ "MatGetSubMatrices_SeqAIJ"
1927 PetscErrorCode MatGetSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
1928 {
1929   PetscErrorCode ierr;
1930   PetscInt       i;
1931 
1932   PetscFunctionBegin;
1933   if (scall == MAT_INITIAL_MATRIX) {
1934     ierr = PetscMalloc((n+1)*sizeof(Mat),B);CHKERRQ(ierr);
1935   }
1936 
1937   for (i=0; i<n; i++) {
1938     ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
1939   }
1940   PetscFunctionReturn(0);
1941 }
1942 
1943 #undef __FUNCT__
1944 #define __FUNCT__ "MatIncreaseOverlap_SeqAIJ"
1945 PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
1946 {
1947   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1948   PetscErrorCode ierr;
1949   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
1950   const PetscInt *idx;
1951   PetscInt       start,end,*ai,*aj;
1952   PetscBT        table;
1953 
1954   PetscFunctionBegin;
1955   m     = A->rmap->n;
1956   ai    = a->i;
1957   aj    = a->j;
1958 
1959   if (ov < 0)  SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
1960 
1961   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&nidx);CHKERRQ(ierr);
1962   ierr = PetscBTCreate(m,table);CHKERRQ(ierr);
1963 
1964   for (i=0; i<is_max; i++) {
1965     /* Initialize the two local arrays */
1966     isz  = 0;
1967     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
1968 
1969     /* Extract the indices, assume there can be duplicate entries */
1970     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
1971     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
1972 
1973     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
1974     for (j=0; j<n ; ++j){
1975       if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];}
1976     }
1977     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
1978     ierr = ISDestroy(is[i]);CHKERRQ(ierr);
1979 
1980     k = 0;
1981     for (j=0; j<ov; j++){ /* for each overlap */
1982       n = isz;
1983       for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
1984         row   = nidx[k];
1985         start = ai[row];
1986         end   = ai[row+1];
1987         for (l = start; l<end ; l++){
1988           val = aj[l] ;
1989           if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;}
1990         }
1991       }
1992     }
1993     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,(is+i));CHKERRQ(ierr);
1994   }
1995   ierr = PetscBTDestroy(table);CHKERRQ(ierr);
1996   ierr = PetscFree(nidx);CHKERRQ(ierr);
1997   PetscFunctionReturn(0);
1998 }
1999 
2000 /* -------------------------------------------------------------- */
2001 #undef __FUNCT__
2002 #define __FUNCT__ "MatPermute_SeqAIJ"
2003 PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
2004 {
2005   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2006   PetscErrorCode ierr;
2007   PetscInt       i,nz,m = A->rmap->n,n = A->cmap->n;
2008   const PetscInt *row,*col;
2009   PetscInt       *cnew,j,*lens;
2010   IS             icolp,irowp;
2011   PetscInt       *cwork;
2012   PetscScalar    *vwork;
2013 
2014   PetscFunctionBegin;
2015   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
2016   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
2017   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
2018   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
2019 
2020   /* determine lengths of permuted rows */
2021   ierr = PetscMalloc((m+1)*sizeof(PetscInt),&lens);CHKERRQ(ierr);
2022   for (i=0; i<m; i++) {
2023     lens[row[i]] = a->i[i+1] - a->i[i];
2024   }
2025   ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr);
2026   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
2027   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2028   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
2029   ierr = PetscFree(lens);CHKERRQ(ierr);
2030 
2031   ierr = PetscMalloc(n*sizeof(PetscInt),&cnew);CHKERRQ(ierr);
2032   for (i=0; i<m; i++) {
2033     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
2034     for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];}
2035     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
2036     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
2037   }
2038   ierr = PetscFree(cnew);CHKERRQ(ierr);
2039   (*B)->assembled     = PETSC_FALSE;
2040   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2041   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2042   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
2043   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
2044   ierr = ISDestroy(irowp);CHKERRQ(ierr);
2045   ierr = ISDestroy(icolp);CHKERRQ(ierr);
2046   PetscFunctionReturn(0);
2047 }
2048 
2049 #undef __FUNCT__
2050 #define __FUNCT__ "MatCopy_SeqAIJ"
2051 PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
2052 {
2053   PetscErrorCode ierr;
2054 
2055   PetscFunctionBegin;
2056   /* If the two matrices have the same copy implementation, use fast copy. */
2057   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
2058     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2059     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
2060 
2061     if (a->i[A->rmap->n] != b->i[B->rmap->n]) {
2062       SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
2063     }
2064     ierr = PetscMemcpy(b->a,a->a,(a->i[A->rmap->n])*sizeof(PetscScalar));CHKERRQ(ierr);
2065   } else {
2066     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
2067   }
2068   PetscFunctionReturn(0);
2069 }
2070 
2071 #undef __FUNCT__
2072 #define __FUNCT__ "MatSetUpPreallocation_SeqAIJ"
2073 PetscErrorCode MatSetUpPreallocation_SeqAIJ(Mat A)
2074 {
2075   PetscErrorCode ierr;
2076 
2077   PetscFunctionBegin;
2078   ierr =  MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);CHKERRQ(ierr);
2079   PetscFunctionReturn(0);
2080 }
2081 
2082 #undef __FUNCT__
2083 #define __FUNCT__ "MatGetArray_SeqAIJ"
2084 PetscErrorCode MatGetArray_SeqAIJ(Mat A,PetscScalar *array[])
2085 {
2086   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2087   PetscFunctionBegin;
2088   *array = a->a;
2089   PetscFunctionReturn(0);
2090 }
2091 
2092 #undef __FUNCT__
2093 #define __FUNCT__ "MatRestoreArray_SeqAIJ"
2094 PetscErrorCode MatRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
2095 {
2096   PetscFunctionBegin;
2097   PetscFunctionReturn(0);
2098 }
2099 
2100 #undef __FUNCT__
2101 #define __FUNCT__ "MatFDColoringApply_SeqAIJ"
2102 PetscErrorCode MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
2103 {
2104   PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f;
2105   PetscErrorCode ierr;
2106   PetscInt       k,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
2107   PetscScalar    dx,*y,*xx,*w3_array;
2108   PetscScalar    *vscale_array;
2109   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin;
2110   Vec            w1,w2,w3;
2111   void           *fctx = coloring->fctx;
2112   PetscTruth     flg = PETSC_FALSE;
2113 
2114   PetscFunctionBegin;
2115   if (!coloring->w1) {
2116     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
2117     ierr = PetscLogObjectParent(coloring,coloring->w1);CHKERRQ(ierr);
2118     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
2119     ierr = PetscLogObjectParent(coloring,coloring->w2);CHKERRQ(ierr);
2120     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
2121     ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr);
2122   }
2123   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
2124 
2125   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
2126   ierr = PetscOptionsGetTruth(((PetscObject)coloring)->prefix,"-mat_fd_coloring_dont_rezero",&flg,PETSC_NULL);CHKERRQ(ierr);
2127   if (flg) {
2128     ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr);
2129   } else {
2130     PetscTruth assembled;
2131     ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
2132     if (assembled) {
2133       ierr = MatZeroEntries(J);CHKERRQ(ierr);
2134     }
2135   }
2136 
2137   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
2138   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
2139 
2140   /*
2141        This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets
2142      coloring->F for the coarser grids from the finest
2143   */
2144   if (coloring->F) {
2145     ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr);
2146     ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr);
2147     if (m1 != m2) {
2148       coloring->F = 0;
2149     }
2150   }
2151 
2152   if (coloring->F) {
2153     w1          = coloring->F;
2154     coloring->F = 0;
2155   } else {
2156     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2157     ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr);
2158     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2159   }
2160 
2161   /*
2162       Compute all the scale factors and share with other processors
2163   */
2164   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
2165   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
2166   for (k=0; k<coloring->ncolors; k++) {
2167     /*
2168        Loop over each column associated with color adding the
2169        perturbation to the vector w3.
2170     */
2171     for (l=0; l<coloring->ncolumns[k]; l++) {
2172       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
2173       dx  = xx[col];
2174       if (dx == 0.0) dx = 1.0;
2175 #if !defined(PETSC_USE_COMPLEX)
2176       if (dx < umin && dx >= 0.0)      dx = umin;
2177       else if (dx < 0.0 && dx > -umin) dx = -umin;
2178 #else
2179       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
2180       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2181 #endif
2182       dx                *= epsilon;
2183       vscale_array[col] = 1.0/dx;
2184     }
2185   }
2186   vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
2187   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2188   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2189 
2190   /*  ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
2191       ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/
2192 
2193   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
2194   else                        vscaleforrow = coloring->columnsforrow;
2195 
2196   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
2197   /*
2198       Loop over each color
2199   */
2200   for (k=0; k<coloring->ncolors; k++) {
2201     coloring->currentcolor = k;
2202     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
2203     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
2204     /*
2205        Loop over each column associated with color adding the
2206        perturbation to the vector w3.
2207     */
2208     for (l=0; l<coloring->ncolumns[k]; l++) {
2209       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
2210       dx  = xx[col];
2211       if (dx == 0.0) dx = 1.0;
2212 #if !defined(PETSC_USE_COMPLEX)
2213       if (dx < umin && dx >= 0.0)      dx = umin;
2214       else if (dx < 0.0 && dx > -umin) dx = -umin;
2215 #else
2216       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
2217       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2218 #endif
2219       dx            *= epsilon;
2220       if (!PetscAbsScalar(dx)) SETERRQ(PETSC_ERR_PLIB,"Computed 0 differencing parameter");
2221       w3_array[col] += dx;
2222     }
2223     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
2224 
2225     /*
2226        Evaluate function at x1 + dx (here dx is a vector of perturbations)
2227     */
2228 
2229     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2230     ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
2231     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
2232     ierr = VecAXPY(w2,-1.0,w1);CHKERRQ(ierr);
2233 
2234     /*
2235        Loop over rows of vector, putting results into Jacobian matrix
2236     */
2237     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
2238     for (l=0; l<coloring->nrows[k]; l++) {
2239       row    = coloring->rows[k][l];
2240       col    = coloring->columnsforrow[k][l];
2241       y[row] *= vscale_array[vscaleforrow[k][l]];
2242       srow   = row + start;
2243       ierr   = MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
2244     }
2245     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
2246   }
2247   coloring->currentcolor = k;
2248   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
2249   xx = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
2250   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2251   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2252   PetscFunctionReturn(0);
2253 }
2254 
2255 #include "petscblaslapack.h"
2256 #undef __FUNCT__
2257 #define __FUNCT__ "MatAXPY_SeqAIJ"
2258 PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
2259 {
2260   PetscErrorCode ierr;
2261   PetscInt       i;
2262   Mat_SeqAIJ     *x  = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data;
2263   PetscBLASInt   one=1,bnz = PetscBLASIntCast(x->nz);
2264 
2265   PetscFunctionBegin;
2266   if (str == SAME_NONZERO_PATTERN) {
2267     PetscScalar alpha = a;
2268     BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one);
2269   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2270     if (y->xtoy && y->XtoY != X) {
2271       ierr = PetscFree(y->xtoy);CHKERRQ(ierr);
2272       ierr = MatDestroy(y->XtoY);CHKERRQ(ierr);
2273     }
2274     if (!y->xtoy) { /* get xtoy */
2275       ierr = MatAXPYGetxtoy_Private(X->rmap->n,x->i,x->j,PETSC_NULL, y->i,y->j,PETSC_NULL, &y->xtoy);CHKERRQ(ierr);
2276       y->XtoY = X;
2277       ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr);
2278     }
2279     for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += a*(x->a[i]);
2280     ierr = PetscInfo3(Y,"ratio of nnz(X)/nnz(Y): %d/%d = %G\n",x->nz,y->nz,(PetscReal)(x->nz)/y->nz);CHKERRQ(ierr);
2281   } else {
2282     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
2283   }
2284   PetscFunctionReturn(0);
2285 }
2286 
2287 #undef __FUNCT__
2288 #define __FUNCT__ "MatSetBlockSize_SeqAIJ"
2289 PetscErrorCode MatSetBlockSize_SeqAIJ(Mat A,PetscInt bs)
2290 {
2291   PetscErrorCode ierr;
2292 
2293   PetscFunctionBegin;
2294   ierr = PetscLayoutSetBlockSize(A->rmap,bs);CHKERRQ(ierr);
2295   ierr = PetscLayoutSetBlockSize(A->cmap,bs);CHKERRQ(ierr);
2296   PetscFunctionReturn(0);
2297 }
2298 
2299 #undef __FUNCT__
2300 #define __FUNCT__ "MatConjugate_SeqAIJ"
2301 PetscErrorCode PETSCMAT_DLLEXPORT MatConjugate_SeqAIJ(Mat mat)
2302 {
2303 #if defined(PETSC_USE_COMPLEX)
2304   Mat_SeqAIJ  *aij = (Mat_SeqAIJ *)mat->data;
2305   PetscInt    i,nz;
2306   PetscScalar *a;
2307 
2308   PetscFunctionBegin;
2309   nz = aij->nz;
2310   a  = aij->a;
2311   for (i=0; i<nz; i++) {
2312     a[i] = PetscConj(a[i]);
2313   }
2314 #else
2315   PetscFunctionBegin;
2316 #endif
2317   PetscFunctionReturn(0);
2318 }
2319 
2320 #undef __FUNCT__
2321 #define __FUNCT__ "MatGetRowMaxAbs_SeqAIJ"
2322 PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2323 {
2324   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2325   PetscErrorCode ierr;
2326   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2327   PetscReal      atmp;
2328   PetscScalar    *x;
2329   MatScalar      *aa;
2330 
2331   PetscFunctionBegin;
2332   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2333   aa   = a->a;
2334   ai   = a->i;
2335   aj   = a->j;
2336 
2337   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2338   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2339   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
2340   if (n != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2341   for (i=0; i<m; i++) {
2342     ncols = ai[1] - ai[0]; ai++;
2343     x[i] = 0.0;
2344     for (j=0; j<ncols; j++){
2345       atmp = PetscAbsScalar(*aa);
2346       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
2347       aa++; aj++;
2348     }
2349   }
2350   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2351   PetscFunctionReturn(0);
2352 }
2353 
2354 #undef __FUNCT__
2355 #define __FUNCT__ "MatGetRowMax_SeqAIJ"
2356 PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2357 {
2358   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2359   PetscErrorCode ierr;
2360   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2361   PetscScalar    *x;
2362   MatScalar      *aa;
2363 
2364   PetscFunctionBegin;
2365   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2366   aa   = a->a;
2367   ai   = a->i;
2368   aj   = a->j;
2369 
2370   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2371   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2372   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
2373   if (n != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2374   for (i=0; i<m; i++) {
2375     ncols = ai[1] - ai[0]; ai++;
2376     if (ncols == A->cmap->n) { /* row is dense */
2377       x[i] = *aa; if (idx) idx[i] = 0;
2378     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
2379       x[i] = 0.0;
2380       if (idx) {
2381         idx[i] = 0; /* in case ncols is zero */
2382         for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */
2383           if (aj[j] > j) {
2384             idx[i] = j;
2385             break;
2386           }
2387         }
2388       }
2389     }
2390     for (j=0; j<ncols; j++){
2391       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
2392       aa++; aj++;
2393     }
2394   }
2395   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2396   PetscFunctionReturn(0);
2397 }
2398 
2399 #undef __FUNCT__
2400 #define __FUNCT__ "MatGetRowMinAbs_SeqAIJ"
2401 PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2402 {
2403   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2404   PetscErrorCode ierr;
2405   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2406   PetscReal      atmp;
2407   PetscScalar    *x;
2408   MatScalar      *aa;
2409 
2410   PetscFunctionBegin;
2411   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2412   aa   = a->a;
2413   ai   = a->i;
2414   aj   = a->j;
2415 
2416   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2417   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2418   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
2419   if (n != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2420   for (i=0; i<m; i++) {
2421     ncols = ai[1] - ai[0]; ai++;
2422     if (ncols) {
2423       /* Get first nonzero */
2424       for(j = 0; j < ncols; j++) {
2425         atmp = PetscAbsScalar(aa[j]);
2426         if (atmp > 1.0e-12) {x[i] = atmp; if (idx) idx[i] = aj[j]; break;}
2427       }
2428       if (j == ncols) {x[i] = *aa; if (idx) idx[i] = *aj;}
2429     } else {
2430       x[i] = 0.0; if (idx) idx[i] = 0;
2431     }
2432     for(j = 0; j < ncols; j++) {
2433       atmp = PetscAbsScalar(*aa);
2434       if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
2435       aa++; aj++;
2436     }
2437   }
2438   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2439   PetscFunctionReturn(0);
2440 }
2441 
2442 #undef __FUNCT__
2443 #define __FUNCT__ "MatGetRowMin_SeqAIJ"
2444 PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
2445 {
2446   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
2447   PetscErrorCode ierr;
2448   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
2449   PetscScalar    *x;
2450   MatScalar      *aa;
2451 
2452   PetscFunctionBegin;
2453   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2454   aa   = a->a;
2455   ai   = a->i;
2456   aj   = a->j;
2457 
2458   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2459   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2460   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
2461   if (n != A->rmap->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2462   for (i=0; i<m; i++) {
2463     ncols = ai[1] - ai[0]; ai++;
2464     if (ncols == A->cmap->n) { /* row is dense */
2465       x[i] = *aa; if (idx) idx[i] = 0;
2466     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
2467       x[i] = 0.0;
2468       if (idx) {   /* find first implicit 0.0 in the row */
2469         idx[i] = 0; /* in case ncols is zero */
2470         for (j=0;j<ncols;j++) {
2471           if (aj[j] > j) {
2472             idx[i] = j;
2473             break;
2474           }
2475         }
2476       }
2477     }
2478     for (j=0; j<ncols; j++){
2479       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
2480       aa++; aj++;
2481     }
2482   }
2483   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2484   PetscFunctionReturn(0);
2485 }
2486 extern PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringApply_AIJ(Mat,MatFDColoring,Vec,MatStructure*,void*);
2487 /* -------------------------------------------------------------------*/
2488 static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
2489        MatGetRow_SeqAIJ,
2490        MatRestoreRow_SeqAIJ,
2491        MatMult_SeqAIJ,
2492 /* 4*/ MatMultAdd_SeqAIJ,
2493        MatMultTranspose_SeqAIJ,
2494        MatMultTransposeAdd_SeqAIJ,
2495        0,
2496        0,
2497        0,
2498 /*10*/ 0,
2499        MatLUFactor_SeqAIJ,
2500        0,
2501        MatSOR_SeqAIJ,
2502        MatTranspose_SeqAIJ,
2503 /*15*/ MatGetInfo_SeqAIJ,
2504        MatEqual_SeqAIJ,
2505        MatGetDiagonal_SeqAIJ,
2506        MatDiagonalScale_SeqAIJ,
2507        MatNorm_SeqAIJ,
2508 /*20*/ 0,
2509        MatAssemblyEnd_SeqAIJ,
2510        MatSetOption_SeqAIJ,
2511        MatZeroEntries_SeqAIJ,
2512 /*24*/ MatZeroRows_SeqAIJ,
2513        0,
2514        0,
2515        0,
2516        0,
2517 /*29*/ MatSetUpPreallocation_SeqAIJ,
2518        0,
2519        0,
2520        MatGetArray_SeqAIJ,
2521        MatRestoreArray_SeqAIJ,
2522 /*34*/ MatDuplicate_SeqAIJ,
2523        0,
2524        0,
2525        MatILUFactor_SeqAIJ,
2526        0,
2527 /*39*/ MatAXPY_SeqAIJ,
2528        MatGetSubMatrices_SeqAIJ,
2529        MatIncreaseOverlap_SeqAIJ,
2530        MatGetValues_SeqAIJ,
2531        MatCopy_SeqAIJ,
2532 /*44*/ MatGetRowMax_SeqAIJ,
2533        MatScale_SeqAIJ,
2534        0,
2535        MatDiagonalSet_SeqAIJ,
2536        MatILUDTFactor_SeqAIJ,
2537 /*49*/ MatSetBlockSize_SeqAIJ,
2538        MatGetRowIJ_SeqAIJ,
2539        MatRestoreRowIJ_SeqAIJ,
2540        MatGetColumnIJ_SeqAIJ,
2541        MatRestoreColumnIJ_SeqAIJ,
2542 /*54*/ MatFDColoringCreate_SeqAIJ,
2543        0,
2544        0,
2545        MatPermute_SeqAIJ,
2546        0,
2547 /*59*/ 0,
2548        MatDestroy_SeqAIJ,
2549        MatView_SeqAIJ,
2550        0,
2551        0,
2552 /*64*/ 0,
2553        0,
2554        0,
2555        0,
2556        0,
2557 /*69*/ MatGetRowMaxAbs_SeqAIJ,
2558        MatGetRowMinAbs_SeqAIJ,
2559        0,
2560        MatSetColoring_SeqAIJ,
2561 #if defined(PETSC_HAVE_ADIC)
2562        MatSetValuesAdic_SeqAIJ,
2563 #else
2564        0,
2565 #endif
2566 /*74*/ MatSetValuesAdifor_SeqAIJ,
2567        MatFDColoringApply_AIJ,
2568        0,
2569        0,
2570        0,
2571 /*79*/ 0,
2572        0,
2573        0,
2574        0,
2575        MatLoad_SeqAIJ,
2576 /*84*/ MatIsSymmetric_SeqAIJ,
2577        MatIsHermitian_SeqAIJ,
2578        0,
2579        0,
2580        0,
2581 /*89*/ MatMatMult_SeqAIJ_SeqAIJ,
2582        MatMatMultSymbolic_SeqAIJ_SeqAIJ,
2583        MatMatMultNumeric_SeqAIJ_SeqAIJ,
2584        MatPtAP_Basic,
2585        MatPtAPSymbolic_SeqAIJ,
2586 /*94*/ MatPtAPNumeric_SeqAIJ,
2587        MatMatMultTranspose_SeqAIJ_SeqAIJ,
2588        MatMatMultTransposeSymbolic_SeqAIJ_SeqAIJ,
2589        MatMatMultTransposeNumeric_SeqAIJ_SeqAIJ,
2590        MatPtAPSymbolic_SeqAIJ_SeqAIJ,
2591 /*99*/ MatPtAPNumeric_SeqAIJ_SeqAIJ,
2592        0,
2593        0,
2594        MatConjugate_SeqAIJ,
2595        0,
2596 /*104*/MatSetValuesRow_SeqAIJ,
2597        MatRealPart_SeqAIJ,
2598        MatImaginaryPart_SeqAIJ,
2599        0,
2600        0,
2601 /*109*/0,
2602        0,
2603        MatGetRowMin_SeqAIJ,
2604        0,
2605        MatMissingDiagonal_SeqAIJ,
2606 /*114*/0,
2607        0,
2608        0,
2609        MatILUDTFactorSymbolic_SeqAIJ,
2610        MatILUDTFactorNumeric_SeqAIJ
2611 };
2612 
2613 EXTERN_C_BEGIN
2614 #undef __FUNCT__
2615 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ"
2616 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
2617 {
2618   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2619   PetscInt   i,nz,n;
2620 
2621   PetscFunctionBegin;
2622 
2623   nz = aij->maxnz;
2624   n  = mat->rmap->n;
2625   for (i=0; i<nz; i++) {
2626     aij->j[i] = indices[i];
2627   }
2628   aij->nz = nz;
2629   for (i=0; i<n; i++) {
2630     aij->ilen[i] = aij->imax[i];
2631   }
2632 
2633   PetscFunctionReturn(0);
2634 }
2635 EXTERN_C_END
2636 
2637 #undef __FUNCT__
2638 #define __FUNCT__ "MatSeqAIJSetColumnIndices"
2639 /*@
2640     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
2641        in the matrix.
2642 
2643   Input Parameters:
2644 +  mat - the SeqAIJ matrix
2645 -  indices - the column indices
2646 
2647   Level: advanced
2648 
2649   Notes:
2650     This can be called if you have precomputed the nonzero structure of the
2651   matrix and want to provide it to the matrix object to improve the performance
2652   of the MatSetValues() operation.
2653 
2654     You MUST have set the correct numbers of nonzeros per row in the call to
2655   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
2656 
2657     MUST be called before any calls to MatSetValues();
2658 
2659     The indices should start with zero, not one.
2660 
2661 @*/
2662 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
2663 {
2664   PetscErrorCode ierr,(*f)(Mat,PetscInt *);
2665 
2666   PetscFunctionBegin;
2667   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2668   PetscValidPointer(indices,2);
2669   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr);
2670   if (f) {
2671     ierr = (*f)(mat,indices);CHKERRQ(ierr);
2672   } else {
2673     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to set column indices");
2674   }
2675   PetscFunctionReturn(0);
2676 }
2677 
2678 /* ----------------------------------------------------------------------------------------*/
2679 
2680 EXTERN_C_BEGIN
2681 #undef __FUNCT__
2682 #define __FUNCT__ "MatStoreValues_SeqAIJ"
2683 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues_SeqAIJ(Mat mat)
2684 {
2685   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
2686   PetscErrorCode ierr;
2687   size_t         nz = aij->i[mat->rmap->n];
2688 
2689   PetscFunctionBegin;
2690   if (aij->nonew != 1) {
2691     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
2692   }
2693 
2694   /* allocate space for values if not already there */
2695   if (!aij->saved_values) {
2696     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
2697     ierr = PetscLogObjectMemory(mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
2698   }
2699 
2700   /* copy values over */
2701   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2702   PetscFunctionReturn(0);
2703 }
2704 EXTERN_C_END
2705 
2706 #undef __FUNCT__
2707 #define __FUNCT__ "MatStoreValues"
2708 /*@
2709     MatStoreValues - Stashes a copy of the matrix values; this allows, for
2710        example, reuse of the linear part of a Jacobian, while recomputing the
2711        nonlinear portion.
2712 
2713    Collect on Mat
2714 
2715   Input Parameters:
2716 .  mat - the matrix (currently only AIJ matrices support this option)
2717 
2718   Level: advanced
2719 
2720   Common Usage, with SNESSolve():
2721 $    Create Jacobian matrix
2722 $    Set linear terms into matrix
2723 $    Apply boundary conditions to matrix, at this time matrix must have
2724 $      final nonzero structure (i.e. setting the nonlinear terms and applying
2725 $      boundary conditions again will not change the nonzero structure
2726 $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
2727 $    ierr = MatStoreValues(mat);
2728 $    Call SNESSetJacobian() with matrix
2729 $    In your Jacobian routine
2730 $      ierr = MatRetrieveValues(mat);
2731 $      Set nonlinear terms in matrix
2732 
2733   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
2734 $    // build linear portion of Jacobian
2735 $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
2736 $    ierr = MatStoreValues(mat);
2737 $    loop over nonlinear iterations
2738 $       ierr = MatRetrieveValues(mat);
2739 $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
2740 $       // call MatAssemblyBegin/End() on matrix
2741 $       Solve linear system with Jacobian
2742 $    endloop
2743 
2744   Notes:
2745     Matrix must already be assemblied before calling this routine
2746     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
2747     calling this routine.
2748 
2749     When this is called multiple times it overwrites the previous set of stored values
2750     and does not allocated additional space.
2751 
2752 .seealso: MatRetrieveValues()
2753 
2754 @*/
2755 PetscErrorCode PETSCMAT_DLLEXPORT MatStoreValues(Mat mat)
2756 {
2757   PetscErrorCode ierr,(*f)(Mat);
2758 
2759   PetscFunctionBegin;
2760   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2761   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2762   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2763 
2764   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatStoreValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2765   if (f) {
2766     ierr = (*f)(mat);CHKERRQ(ierr);
2767   } else {
2768     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to store values");
2769   }
2770   PetscFunctionReturn(0);
2771 }
2772 
2773 EXTERN_C_BEGIN
2774 #undef __FUNCT__
2775 #define __FUNCT__ "MatRetrieveValues_SeqAIJ"
2776 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues_SeqAIJ(Mat mat)
2777 {
2778   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *)mat->data;
2779   PetscErrorCode ierr;
2780   PetscInt       nz = aij->i[mat->rmap->n];
2781 
2782   PetscFunctionBegin;
2783   if (aij->nonew != 1) {
2784     SETERRQ(PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
2785   }
2786   if (!aij->saved_values) {
2787     SETERRQ(PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
2788   }
2789   /* copy values over */
2790   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2791   PetscFunctionReturn(0);
2792 }
2793 EXTERN_C_END
2794 
2795 #undef __FUNCT__
2796 #define __FUNCT__ "MatRetrieveValues"
2797 /*@
2798     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
2799        example, reuse of the linear part of a Jacobian, while recomputing the
2800        nonlinear portion.
2801 
2802    Collect on Mat
2803 
2804   Input Parameters:
2805 .  mat - the matrix (currently on AIJ matrices support this option)
2806 
2807   Level: advanced
2808 
2809 .seealso: MatStoreValues()
2810 
2811 @*/
2812 PetscErrorCode PETSCMAT_DLLEXPORT MatRetrieveValues(Mat mat)
2813 {
2814   PetscErrorCode ierr,(*f)(Mat);
2815 
2816   PetscFunctionBegin;
2817   PetscValidHeaderSpecific(mat,MAT_COOKIE,1);
2818   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2819   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2820 
2821   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatRetrieveValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2822   if (f) {
2823     ierr = (*f)(mat);CHKERRQ(ierr);
2824   } else {
2825     SETERRQ(PETSC_ERR_SUP,"Wrong type of matrix to retrieve values");
2826   }
2827   PetscFunctionReturn(0);
2828 }
2829 
2830 
2831 /* --------------------------------------------------------------------------------*/
2832 #undef __FUNCT__
2833 #define __FUNCT__ "MatCreateSeqAIJ"
2834 /*@C
2835    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
2836    (the default parallel PETSc format).  For good matrix assembly performance
2837    the user should preallocate the matrix storage by setting the parameter nz
2838    (or the array nnz).  By setting these parameters accurately, performance
2839    during matrix assembly can be increased by more than a factor of 50.
2840 
2841    Collective on MPI_Comm
2842 
2843    Input Parameters:
2844 +  comm - MPI communicator, set to PETSC_COMM_SELF
2845 .  m - number of rows
2846 .  n - number of columns
2847 .  nz - number of nonzeros per row (same for all rows)
2848 -  nnz - array containing the number of nonzeros in the various rows
2849          (possibly different for each row) or PETSC_NULL
2850 
2851    Output Parameter:
2852 .  A - the matrix
2853 
2854    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
2855    MatXXXXSetPreallocation() paradgm instead of this routine directly.
2856    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
2857 
2858    Notes:
2859    If nnz is given then nz is ignored
2860 
2861    The AIJ format (also called the Yale sparse matrix format or
2862    compressed row storage), is fully compatible with standard Fortran 77
2863    storage.  That is, the stored row and column indices can begin at
2864    either one (as in Fortran) or zero.  See the users' manual for details.
2865 
2866    Specify the preallocated storage with either nz or nnz (not both).
2867    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2868    allocation.  For large problems you MUST preallocate memory or you
2869    will get TERRIBLE performance, see the users' manual chapter on matrices.
2870 
2871    By default, this format uses inodes (identical nodes) when possible, to
2872    improve numerical efficiency of matrix-vector products and solves. We
2873    search for consecutive rows with the same nonzero structure, thereby
2874    reusing matrix information to achieve increased efficiency.
2875 
2876    Options Database Keys:
2877 +  -mat_no_inode  - Do not use inodes
2878 .  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
2879 -  -mat_aij_oneindex - Internally use indexing starting at 1
2880         rather than 0.  Note that when calling MatSetValues(),
2881         the user still MUST index entries starting at 0!
2882 
2883    Level: intermediate
2884 
2885 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
2886 
2887 @*/
2888 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
2889 {
2890   PetscErrorCode ierr;
2891 
2892   PetscFunctionBegin;
2893   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2894   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
2895   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
2896   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,(PetscInt*)nnz);CHKERRQ(ierr);
2897   PetscFunctionReturn(0);
2898 }
2899 
2900 #undef __FUNCT__
2901 #define __FUNCT__ "MatSeqAIJSetPreallocation"
2902 /*@C
2903    MatSeqAIJSetPreallocation - For good matrix assembly performance
2904    the user should preallocate the matrix storage by setting the parameter nz
2905    (or the array nnz).  By setting these parameters accurately, performance
2906    during matrix assembly can be increased by more than a factor of 50.
2907 
2908    Collective on MPI_Comm
2909 
2910    Input Parameters:
2911 +  B - The matrix-free
2912 .  nz - number of nonzeros per row (same for all rows)
2913 -  nnz - array containing the number of nonzeros in the various rows
2914          (possibly different for each row) or PETSC_NULL
2915 
2916    Notes:
2917      If nnz is given then nz is ignored
2918 
2919     The AIJ format (also called the Yale sparse matrix format or
2920    compressed row storage), is fully compatible with standard Fortran 77
2921    storage.  That is, the stored row and column indices can begin at
2922    either one (as in Fortran) or zero.  See the users' manual for details.
2923 
2924    Specify the preallocated storage with either nz or nnz (not both).
2925    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2926    allocation.  For large problems you MUST preallocate memory or you
2927    will get TERRIBLE performance, see the users' manual chapter on matrices.
2928 
2929    You can call MatGetInfo() to get information on how effective the preallocation was;
2930    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
2931    You can also run with the option -info and look for messages with the string
2932    malloc in them to see if additional memory allocation was needed.
2933 
2934    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
2935    entries or columns indices
2936 
2937    By default, this format uses inodes (identical nodes) when possible, to
2938    improve numerical efficiency of matrix-vector products and solves. We
2939    search for consecutive rows with the same nonzero structure, thereby
2940    reusing matrix information to achieve increased efficiency.
2941 
2942    Options Database Keys:
2943 +  -mat_no_inode  - Do not use inodes
2944 .  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
2945 -  -mat_aij_oneindex - Internally use indexing starting at 1
2946         rather than 0.  Note that when calling MatSetValues(),
2947         the user still MUST index entries starting at 0!
2948 
2949    Level: intermediate
2950 
2951 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo()
2952 
2953 @*/
2954 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
2955 {
2956   PetscErrorCode ierr,(*f)(Mat,PetscInt,const PetscInt[]);
2957 
2958   PetscFunctionBegin;
2959   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
2960   if (f) {
2961     ierr = (*f)(B,nz,nnz);CHKERRQ(ierr);
2962   }
2963   PetscFunctionReturn(0);
2964 }
2965 
2966 EXTERN_C_BEGIN
2967 #undef __FUNCT__
2968 #define __FUNCT__ "MatSeqAIJSetPreallocation_SeqAIJ"
2969 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,PetscInt *nnz)
2970 {
2971   Mat_SeqAIJ     *b;
2972   PetscTruth     skipallocation = PETSC_FALSE;
2973   PetscErrorCode ierr;
2974   PetscInt       i;
2975 
2976   PetscFunctionBegin;
2977 
2978   if (nz == MAT_SKIP_ALLOCATION) {
2979     skipallocation = PETSC_TRUE;
2980     nz             = 0;
2981   }
2982 
2983   ierr = PetscLayoutSetBlockSize(B->rmap,1);CHKERRQ(ierr);
2984   ierr = PetscLayoutSetBlockSize(B->cmap,1);CHKERRQ(ierr);
2985   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
2986   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
2987 
2988   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
2989   if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
2990   if (nnz) {
2991     for (i=0; i<B->rmap->n; i++) {
2992       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
2993       if (nnz[i] > B->cmap->n) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %d value %d rowlength %d",i,nnz[i],B->cmap->n);
2994     }
2995   }
2996 
2997   B->preallocated = PETSC_TRUE;
2998   b = (Mat_SeqAIJ*)B->data;
2999 
3000   if (!skipallocation) {
3001     if (!b->imax) {
3002       ierr = PetscMalloc2(B->rmap->n,PetscInt,&b->imax,B->rmap->n,PetscInt,&b->ilen);CHKERRQ(ierr);
3003       ierr = PetscLogObjectMemory(B,2*B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3004     }
3005     if (!nnz) {
3006       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
3007       else if (nz <= 0)        nz = 1;
3008       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
3009       nz = nz*B->rmap->n;
3010     } else {
3011       nz = 0;
3012       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
3013     }
3014     /* b->ilen will count nonzeros in each row so far. */
3015     for (i=0; i<B->rmap->n; i++) { b->ilen[i] = 0; }
3016 
3017     /* allocate the matrix space */
3018     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
3019     ierr = PetscMalloc3(nz,PetscScalar,&b->a,nz,PetscInt,&b->j,B->rmap->n+1,PetscInt,&b->i);CHKERRQ(ierr);
3020     ierr = PetscLogObjectMemory(B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
3021     b->i[0] = 0;
3022     for (i=1; i<B->rmap->n+1; i++) {
3023       b->i[i] = b->i[i-1] + b->imax[i-1];
3024     }
3025     b->singlemalloc = PETSC_TRUE;
3026     b->free_a       = PETSC_TRUE;
3027     b->free_ij      = PETSC_TRUE;
3028   } else {
3029     b->free_a       = PETSC_FALSE;
3030     b->free_ij      = PETSC_FALSE;
3031   }
3032 
3033   b->nz                = 0;
3034   b->maxnz             = nz;
3035   B->info.nz_unneeded  = (double)b->maxnz;
3036   PetscFunctionReturn(0);
3037 }
3038 EXTERN_C_END
3039 
3040 #undef  __FUNCT__
3041 #define __FUNCT__  "MatSeqAIJSetPreallocationCSR"
3042 /*@
3043    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
3044 
3045    Input Parameters:
3046 +  B - the matrix
3047 .  i - the indices into j for the start of each row (starts with zero)
3048 .  j - the column indices for each row (starts with zero) these must be sorted for each row
3049 -  v - optional values in the matrix
3050 
3051    Level: developer
3052 
3053    The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
3054 
3055 .keywords: matrix, aij, compressed row, sparse, sequential
3056 
3057 .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), SeqAIJ
3058 @*/
3059 PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
3060 {
3061   PetscErrorCode (*f)(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]);
3062   PetscErrorCode ierr;
3063 
3064   PetscFunctionBegin;
3065   PetscValidHeaderSpecific(B,MAT_COOKIE,1);
3066   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",(void (**)(void))&f);CHKERRQ(ierr);
3067   if (f) {
3068     ierr = (*f)(B,i,j,v);CHKERRQ(ierr);
3069   }
3070   PetscFunctionReturn(0);
3071 }
3072 
3073 EXTERN_C_BEGIN
3074 #undef  __FUNCT__
3075 #define __FUNCT__  "MatSeqAIJSetPreallocationCSR_SeqAIJ"
3076 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
3077 {
3078   PetscInt       i;
3079   PetscInt       m,n;
3080   PetscInt       nz;
3081   PetscInt       *nnz, nz_max = 0;
3082   PetscScalar    *values;
3083   PetscErrorCode ierr;
3084 
3085   PetscFunctionBegin;
3086   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
3087 
3088   if (Ii[0]) {
3089     SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
3090   }
3091   ierr = PetscMalloc((m+1) * sizeof(PetscInt), &nnz);CHKERRQ(ierr);
3092   for(i = 0; i < m; i++) {
3093     nz     = Ii[i+1]- Ii[i];
3094     nz_max = PetscMax(nz_max, nz);
3095     if (nz < 0) {
3096       SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
3097     }
3098     nnz[i] = nz;
3099   }
3100   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
3101   ierr = PetscFree(nnz);CHKERRQ(ierr);
3102 
3103   if (v) {
3104     values = (PetscScalar*) v;
3105   } else {
3106     ierr = PetscMalloc(nz_max*sizeof(PetscScalar), &values);CHKERRQ(ierr);
3107     ierr = PetscMemzero(values, nz_max*sizeof(PetscScalar));CHKERRQ(ierr);
3108   }
3109 
3110   for(i = 0; i < m; i++) {
3111     nz  = Ii[i+1] - Ii[i];
3112     ierr = MatSetValues_SeqAIJ(B, 1, &i, nz, J+Ii[i], values + (v ? Ii[i] : 0), INSERT_VALUES);CHKERRQ(ierr);
3113   }
3114 
3115   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3116   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3117 
3118   if (!v) {
3119     ierr = PetscFree(values);CHKERRQ(ierr);
3120   }
3121   PetscFunctionReturn(0);
3122 }
3123 EXTERN_C_END
3124 
3125 #include "../src/mat/impls/dense/seq/dense.h"
3126 #include "private/petscaxpy.h"
3127 
3128 #undef __FUNCT__
3129 #define __FUNCT__ "MatMatMultNumeric_SeqDense_SeqAIJ"
3130 /*
3131     Computes (B'*A')' since computing B*A directly is untenable
3132 
3133                n                       p                          p
3134         (              )       (              )         (                  )
3135       m (      A       )  *  n (       B      )   =   m (         C        )
3136         (              )       (              )         (                  )
3137 
3138 */
3139 PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
3140 {
3141   PetscErrorCode     ierr;
3142   Mat_SeqDense       *sub_a = (Mat_SeqDense*)A->data;
3143   Mat_SeqAIJ         *sub_b = (Mat_SeqAIJ*)B->data;
3144   Mat_SeqDense       *sub_c = (Mat_SeqDense*)C->data;
3145   PetscInt           i,n,m,q,p;
3146   const PetscInt     *ii,*idx;
3147   const PetscScalar  *b,*a,*a_q;
3148   PetscScalar        *c,*c_q;
3149 
3150   PetscFunctionBegin;
3151   m = A->rmap->n;
3152   n = A->cmap->n;
3153   p = B->cmap->n;
3154   a = sub_a->v;
3155   b = sub_b->a;
3156   c = sub_c->v;
3157   ierr = PetscMemzero(c,m*p*sizeof(PetscScalar));CHKERRQ(ierr);
3158 
3159   ii  = sub_b->i;
3160   idx = sub_b->j;
3161   for (i=0; i<n; i++) {
3162     q = ii[i+1] - ii[i];
3163     while (q-->0) {
3164       c_q = c + m*(*idx);
3165       a_q = a + m*i;
3166       PetscAXPY(c_q,*b,a_q,m);
3167       idx++;
3168       b++;
3169     }
3170   }
3171   PetscFunctionReturn(0);
3172 }
3173 
3174 #undef __FUNCT__
3175 #define __FUNCT__ "MatMatMultSymbolic_SeqDense_SeqAIJ"
3176 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C)
3177 {
3178   PetscErrorCode ierr;
3179   PetscInt       m=A->rmap->n,n=B->cmap->n;
3180   Mat            Cmat;
3181 
3182   PetscFunctionBegin;
3183   if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->rmap->n %d\n",A->cmap->n,B->rmap->n);
3184   ierr = MatCreate(((PetscObject)A)->comm,&Cmat);CHKERRQ(ierr);
3185   ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr);
3186   ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr);
3187   ierr = MatSeqDenseSetPreallocation(Cmat,PETSC_NULL);CHKERRQ(ierr);
3188   Cmat->assembled = PETSC_TRUE;
3189   *C = Cmat;
3190   PetscFunctionReturn(0);
3191 }
3192 
3193 /* ----------------------------------------------------------------*/
3194 #undef __FUNCT__
3195 #define __FUNCT__ "MatMatMult_SeqDense_SeqAIJ"
3196 PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
3197 {
3198   PetscErrorCode ierr;
3199 
3200   PetscFunctionBegin;
3201   if (scall == MAT_INITIAL_MATRIX){
3202     ierr = MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);CHKERRQ(ierr);
3203   }
3204   ierr = MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);CHKERRQ(ierr);
3205   PetscFunctionReturn(0);
3206 }
3207 
3208 
3209 /*MC
3210    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
3211    based on compressed sparse row format.
3212 
3213    Options Database Keys:
3214 . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
3215 
3216   Level: beginner
3217 
3218 .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
3219 M*/
3220 
3221 EXTERN_C_BEGIN
3222 #if defined(PETSC_HAVE_PASTIX)
3223 extern PetscErrorCode MatGetFactor_seqaij_pastix(Mat,MatFactorType,Mat*);
3224 #endif
3225 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SCALAR_SINGLE) && !defined(PETSC_USE_SCALAR_MAT_SINGLE)
3226 extern PetscErrorCode MatGetFactor_seqaij_essl(Mat,MatFactorType,Mat *);
3227 #endif
3228 extern PetscErrorCode PETSCMAT_DLLEXPORT MatConvert_SeqAIJ_SeqCRL(Mat,MatType,MatReuse,Mat*);
3229 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_petsc(Mat,MatFactorType,Mat*);
3230 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_bas(Mat,MatFactorType,Mat*);
3231 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactorAvailable_seqaij_petsc(Mat,MatFactorType,PetscTruth *);
3232 #if defined(PETSC_HAVE_MUMPS)
3233 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_mumps(Mat,MatFactorType,Mat*);
3234 #endif
3235 #if defined(PETSC_HAVE_SUPERLU)
3236 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_superlu(Mat,MatFactorType,Mat*);
3237 #endif
3238 #if defined(PETSC_HAVE_SUPERLU_DIST)
3239 extern PetscErrorCode MatGetFactor_seqaij_superlu_dist(Mat,MatFactorType,Mat*);
3240 #endif
3241 #if defined(PETSC_HAVE_SPOOLES)
3242 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_spooles(Mat,MatFactorType,Mat*);
3243 #endif
3244 #if defined(PETSC_HAVE_UMFPACK)
3245 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_umfpack(Mat,MatFactorType,Mat*);
3246 #endif
3247 #if defined(PETSC_HAVE_LUSOL)
3248 extern PetscErrorCode PETSCMAT_DLLEXPORT MatGetFactor_seqaij_lusol(Mat,MatFactorType,Mat*);
3249 #endif
3250 EXTERN_C_END
3251 
3252 
3253 EXTERN_C_BEGIN
3254 #undef __FUNCT__
3255 #define __FUNCT__ "MatCreate_SeqAIJ"
3256 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqAIJ(Mat B)
3257 {
3258   Mat_SeqAIJ     *b;
3259   PetscErrorCode ierr;
3260   PetscMPIInt    size;
3261 
3262   PetscFunctionBegin;
3263   ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr);
3264   if (size > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
3265 
3266   ierr = PetscNewLog(B,Mat_SeqAIJ,&b);CHKERRQ(ierr);
3267   B->data             = (void*)b;
3268   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
3269   B->mapping          = 0;
3270   b->row              = 0;
3271   b->col              = 0;
3272   b->icol             = 0;
3273   b->reallocs         = 0;
3274   b->ignorezeroentries = PETSC_FALSE;
3275   b->roworiented       = PETSC_TRUE;
3276   b->nonew             = 0;
3277   b->diag              = 0;
3278   b->solve_work        = 0;
3279   B->spptr             = 0;
3280   b->saved_values      = 0;
3281   b->idiag             = 0;
3282   b->mdiag             = 0;
3283   b->ssor_work         = 0;
3284   b->omega             = 1.0;
3285   b->fshift            = 0.0;
3286   b->idiagvalid        = PETSC_FALSE;
3287   b->keepnonzeropattern    = PETSC_FALSE;
3288   b->xtoy              = 0;
3289   b->XtoY              = 0;
3290   b->compressedrow.use     = PETSC_FALSE;
3291   b->compressedrow.nrows   = B->rmap->n;
3292   b->compressedrow.i       = PETSC_NULL;
3293   b->compressedrow.rindex  = PETSC_NULL;
3294   b->compressedrow.checked = PETSC_FALSE;
3295   B->same_nonzero          = PETSC_FALSE;
3296 
3297   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
3298 #if defined(PETSC_HAVE_PASTIX)
3299   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_pastix_C",
3300 					   "MatGetFactor_seqaij_pastix",
3301 					   MatGetFactor_seqaij_pastix);CHKERRQ(ierr);
3302 #endif
3303 #if defined(PETSC_HAVE_ESSL) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SCALAR_SINGLE) && !defined(PETSC_USE_SCALAR_MAT_SINGLE)
3304   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_essl_C",
3305                                      "MatGetFactor_seqaij_essl",
3306                                      MatGetFactor_seqaij_essl);CHKERRQ(ierr);
3307 #endif
3308 #if defined(PETSC_HAVE_SUPERLU)
3309   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_C",
3310                                      "MatGetFactor_seqaij_superlu",
3311                                      MatGetFactor_seqaij_superlu);CHKERRQ(ierr);
3312 #endif
3313 #if defined(PETSC_HAVE_SUPERLU_DIST)
3314   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_dist_C",
3315                                      "MatGetFactor_seqaij_superlu_dist",
3316                                      MatGetFactor_seqaij_superlu_dist);CHKERRQ(ierr);
3317 #endif
3318 #if defined(PETSC_HAVE_SPOOLES)
3319   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_spooles_C",
3320                                      "MatGetFactor_seqaij_spooles",
3321                                      MatGetFactor_seqaij_spooles);CHKERRQ(ierr);
3322 #endif
3323 #if defined(PETSC_HAVE_MUMPS)
3324   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_mumps_C",
3325                                      "MatGetFactor_seqaij_mumps",
3326                                      MatGetFactor_seqaij_mumps);CHKERRQ(ierr);
3327 #endif
3328 #if defined(PETSC_HAVE_UMFPACK)
3329     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_umfpack_C",
3330                                      "MatGetFactor_seqaij_umfpack",
3331                                      MatGetFactor_seqaij_umfpack);CHKERRQ(ierr);
3332 #endif
3333 #if defined(PETSC_HAVE_LUSOL)
3334     ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_lusol_C",
3335                                      "MatGetFactor_seqaij_lusol",
3336                                      MatGetFactor_seqaij_lusol);CHKERRQ(ierr);
3337 #endif
3338   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_petsc_C",
3339                                      "MatGetFactor_seqaij_petsc",
3340                                      MatGetFactor_seqaij_petsc);CHKERRQ(ierr);
3341   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactorAvailable_petsc_C",
3342                                      "MatGetFactorAvailable_seqaij_petsc",
3343                                      MatGetFactorAvailable_seqaij_petsc);CHKERRQ(ierr);
3344   /*  ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_bas_C",
3345                                      "MatGetFactor_seqaij_bas",
3346                                      MatGetFactor_seqaij_bas); */
3347   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C",
3348                                      "MatSeqAIJSetColumnIndices_SeqAIJ",
3349                                      MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
3350   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
3351                                      "MatStoreValues_SeqAIJ",
3352                                      MatStoreValues_SeqAIJ);CHKERRQ(ierr);
3353   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
3354                                      "MatRetrieveValues_SeqAIJ",
3355                                      MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
3356   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",
3357                                      "MatConvert_SeqAIJ_SeqSBAIJ",
3358                                       MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
3359   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqbaij_C",
3360                                      "MatConvert_SeqAIJ_SeqBAIJ",
3361                                       MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
3362   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqcsrperm_C",
3363                                      "MatConvert_SeqAIJ_SeqCSRPERM",
3364                                       MatConvert_SeqAIJ_SeqCSRPERM);CHKERRQ(ierr);
3365   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_seqaij_seqcrl_C",
3366                                      "MatConvert_SeqAIJ_SeqCRL",
3367                                       MatConvert_SeqAIJ_SeqCRL);CHKERRQ(ierr);
3368   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C",
3369                                      "MatIsTranspose_SeqAIJ",
3370                                       MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
3371   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsHermitianTranspose_C",
3372                                      "MatIsHermitianTranspose_SeqAIJ",
3373                                       MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
3374   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocation_C",
3375                                      "MatSeqAIJSetPreallocation_SeqAIJ",
3376                                       MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
3377   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",
3378 				     "MatSeqAIJSetPreallocationCSR_SeqAIJ",
3379 				      MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
3380   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatReorderForNonzeroDiagonal_C",
3381                                      "MatReorderForNonzeroDiagonal_SeqAIJ",
3382                                       MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
3383   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMult_seqdense_seqaij_C",
3384                                      "MatMatMult_SeqDense_SeqAIJ",
3385                                       MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr);
3386   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C",
3387                                      "MatMatMultSymbolic_SeqDense_SeqAIJ",
3388                                       MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr);
3389   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C",
3390                                      "MatMatMultNumeric_SeqDense_SeqAIJ",
3391                                       MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr);
3392   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
3393   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
3394   PetscFunctionReturn(0);
3395 }
3396 EXTERN_C_END
3397 
3398 #undef __FUNCT__
3399 #define __FUNCT__ "MatDuplicateNoCreate_SeqAIJ"
3400 /*
3401     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
3402 */
3403 PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscTruth mallocmatspace)
3404 {
3405   Mat_SeqAIJ     *c,*a = (Mat_SeqAIJ*)A->data;
3406   PetscErrorCode ierr;
3407   PetscInt       i,m = A->rmap->n;
3408 
3409   PetscFunctionBegin;
3410   c = (Mat_SeqAIJ*)C->data;
3411 
3412   C->factor           = A->factor;
3413 
3414   c->row            = 0;
3415   c->col            = 0;
3416   c->icol           = 0;
3417   c->reallocs       = 0;
3418 
3419   C->assembled      = PETSC_TRUE;
3420 
3421   ierr = PetscLayoutSetBlockSize(C->rmap,1);CHKERRQ(ierr);
3422   ierr = PetscLayoutSetBlockSize(C->cmap,1);CHKERRQ(ierr);
3423   ierr = PetscLayoutSetUp(C->rmap);CHKERRQ(ierr);
3424   ierr = PetscLayoutSetUp(C->cmap);CHKERRQ(ierr);
3425 
3426   ierr = PetscMalloc2(m,PetscInt,&c->imax,m,PetscInt,&c->ilen);CHKERRQ(ierr);
3427   ierr = PetscLogObjectMemory(C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
3428   for (i=0; i<m; i++) {
3429     c->imax[i] = a->imax[i];
3430     c->ilen[i] = a->ilen[i];
3431   }
3432 
3433   /* allocate the matrix space */
3434   if (mallocmatspace){
3435     ierr = PetscMalloc3(a->i[m],PetscScalar,&c->a,a->i[m],PetscInt,&c->j,m+1,PetscInt,&c->i);CHKERRQ(ierr);
3436     ierr = PetscLogObjectMemory(C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
3437     c->singlemalloc = PETSC_TRUE;
3438     ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
3439     if (m > 0) {
3440       ierr = PetscMemcpy(c->j,a->j,(a->i[m])*sizeof(PetscInt));CHKERRQ(ierr);
3441       if (cpvalues == MAT_COPY_VALUES) {
3442         ierr = PetscMemcpy(c->a,a->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
3443       } else {
3444         ierr = PetscMemzero(c->a,(a->i[m])*sizeof(PetscScalar));CHKERRQ(ierr);
3445       }
3446     }
3447   }
3448 
3449   c->ignorezeroentries = a->ignorezeroentries;
3450   c->roworiented       = a->roworiented;
3451   c->nonew             = a->nonew;
3452   if (a->diag) {
3453     ierr = PetscMalloc((m+1)*sizeof(PetscInt),&c->diag);CHKERRQ(ierr);
3454     ierr = PetscLogObjectMemory(C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
3455     for (i=0; i<m; i++) {
3456       c->diag[i] = a->diag[i];
3457     }
3458   } else c->diag           = 0;
3459   c->solve_work            = 0;
3460   c->saved_values          = 0;
3461   c->idiag                 = 0;
3462   c->ssor_work             = 0;
3463   c->keepnonzeropattern    = a->keepnonzeropattern;
3464   c->free_a                = PETSC_TRUE;
3465   c->free_ij               = PETSC_TRUE;
3466   c->xtoy                  = 0;
3467   c->XtoY                  = 0;
3468 
3469   c->nz                 = a->nz;
3470   c->maxnz              = a->maxnz;
3471   C->preallocated       = PETSC_TRUE;
3472 
3473   c->compressedrow.use     = a->compressedrow.use;
3474   c->compressedrow.nrows   = a->compressedrow.nrows;
3475   c->compressedrow.checked = a->compressedrow.checked;
3476   if (a->compressedrow.checked && a->compressedrow.use){
3477     i = a->compressedrow.nrows;
3478     ierr = PetscMalloc2(i+1,PetscInt,&c->compressedrow.i,i,PetscInt,&c->compressedrow.rindex);CHKERRQ(ierr);
3479     ierr = PetscMemcpy(c->compressedrow.i,a->compressedrow.i,(i+1)*sizeof(PetscInt));CHKERRQ(ierr);
3480     ierr = PetscMemcpy(c->compressedrow.rindex,a->compressedrow.rindex,i*sizeof(PetscInt));CHKERRQ(ierr);
3481   } else {
3482     c->compressedrow.use    = PETSC_FALSE;
3483     c->compressedrow.i      = PETSC_NULL;
3484     c->compressedrow.rindex = PETSC_NULL;
3485   }
3486   C->same_nonzero = A->same_nonzero;
3487   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
3488 
3489   ierr = PetscFListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
3490   PetscFunctionReturn(0);
3491 }
3492 
3493 #undef __FUNCT__
3494 #define __FUNCT__ "MatDuplicate_SeqAIJ"
3495 PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
3496 {
3497   PetscErrorCode ierr;
3498 
3499   PetscFunctionBegin;
3500   ierr = MatCreate(((PetscObject)A)->comm,B);CHKERRQ(ierr);
3501   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
3502   ierr = MatSetType(*B,MATSEQAIJ);CHKERRQ(ierr);
3503   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
3504   PetscFunctionReturn(0);
3505 }
3506 
3507 #undef __FUNCT__
3508 #define __FUNCT__ "MatLoad_SeqAIJ"
3509 PetscErrorCode MatLoad_SeqAIJ(PetscViewer viewer, const MatType type,Mat *A)
3510 {
3511   Mat_SeqAIJ     *a;
3512   Mat            B;
3513   PetscErrorCode ierr;
3514   PetscInt       i,sum,nz,header[4],*rowlengths = 0,M,N;
3515   int            fd;
3516   PetscMPIInt    size;
3517   MPI_Comm       comm;
3518 
3519   PetscFunctionBegin;
3520   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
3521   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
3522   if (size > 1) SETERRQ(PETSC_ERR_ARG_SIZ,"view must have one processor");
3523   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
3524   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
3525   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
3526   M = header[1]; N = header[2]; nz = header[3];
3527 
3528   if (nz < 0) {
3529     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
3530   }
3531 
3532   /* read in row lengths */
3533   ierr = PetscMalloc(M*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
3534   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
3535 
3536   /* check if sum of rowlengths is same as nz */
3537   for (i=0,sum=0; i< M; i++) sum +=rowlengths[i];
3538   if (sum != nz) SETERRQ2(PETSC_ERR_FILE_READ,"Inconsistant matrix data in file. no-nonzeros = %d, sum-row-lengths = %d\n",nz,sum);
3539 
3540   /* create our matrix */
3541   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
3542   ierr = MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
3543   ierr = MatSetType(B,type);CHKERRQ(ierr);
3544   ierr = MatSeqAIJSetPreallocation_SeqAIJ(B,0,rowlengths);CHKERRQ(ierr);
3545   a = (Mat_SeqAIJ*)B->data;
3546 
3547   ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr);
3548 
3549   /* read in nonzero values */
3550   ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr);
3551 
3552   /* set matrix "i" values */
3553   a->i[0] = 0;
3554   for (i=1; i<= M; i++) {
3555     a->i[i]      = a->i[i-1] + rowlengths[i-1];
3556     a->ilen[i-1] = rowlengths[i-1];
3557   }
3558   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
3559 
3560   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3561   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3562   *A = B;
3563   PetscFunctionReturn(0);
3564 }
3565 
3566 #undef __FUNCT__
3567 #define __FUNCT__ "MatEqual_SeqAIJ"
3568 PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg)
3569 {
3570   Mat_SeqAIJ     *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data;
3571   PetscErrorCode ierr;
3572 #if defined(PETSC_USE_COMPLEX)
3573   PetscInt k;
3574 #endif
3575 
3576   PetscFunctionBegin;
3577   /* If the  matrix dimensions are not equal,or no of nonzeros */
3578   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
3579     *flg = PETSC_FALSE;
3580     PetscFunctionReturn(0);
3581   }
3582 
3583   /* if the a->i are the same */
3584   ierr = PetscMemcmp(a->i,b->i,(A->rmap->n+1)*sizeof(PetscInt),flg);CHKERRQ(ierr);
3585   if (!*flg) PetscFunctionReturn(0);
3586 
3587   /* if a->j are the same */
3588   ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(PetscInt),flg);CHKERRQ(ierr);
3589   if (!*flg) PetscFunctionReturn(0);
3590 
3591   /* if a->a are the same */
3592 #if defined(PETSC_USE_COMPLEX)
3593   for (k=0; k<a->nz; k++){
3594     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])){
3595       *flg = PETSC_FALSE;
3596       PetscFunctionReturn(0);
3597     }
3598   }
3599 #else
3600   ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr);
3601 #endif
3602   PetscFunctionReturn(0);
3603 }
3604 
3605 #undef __FUNCT__
3606 #define __FUNCT__ "MatCreateSeqAIJWithArrays"
3607 /*@
3608      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
3609               provided by the user.
3610 
3611       Collective on MPI_Comm
3612 
3613    Input Parameters:
3614 +   comm - must be an MPI communicator of size 1
3615 .   m - number of rows
3616 .   n - number of columns
3617 .   i - row indices
3618 .   j - column indices
3619 -   a - matrix values
3620 
3621    Output Parameter:
3622 .   mat - the matrix
3623 
3624    Level: intermediate
3625 
3626    Notes:
3627        The i, j, and a arrays are not copied by this routine, the user must free these arrays
3628     once the matrix is destroyed
3629 
3630        You cannot set new nonzero locations into this matrix, that will generate an error.
3631 
3632        The i and j indices are 0 based
3633 
3634        The format which is used for the sparse matrix input, is equivalent to a
3635     row-major ordering.. i.e for the following matrix, the input data expected is
3636     as shown:
3637 
3638         1 0 0
3639         2 0 3
3640         4 5 6
3641 
3642         i =  {0,1,3,6}  [size = nrow+1  = 3+1]
3643         j =  {0,0,2,0,1,2}  [size = nz = 6]; values must be sorted for each row
3644         v =  {1,2,3,4,5,6}  [size = nz = 6]
3645 
3646 
3647 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
3648 
3649 @*/
3650 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt* i,PetscInt*j,PetscScalar *a,Mat *mat)
3651 {
3652   PetscErrorCode ierr;
3653   PetscInt       ii;
3654   Mat_SeqAIJ     *aij;
3655 #if defined(PETSC_USE_DEBUG)
3656   PetscInt       jj;
3657 #endif
3658 
3659   PetscFunctionBegin;
3660   if (i[0]) {
3661     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
3662   }
3663   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
3664   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
3665   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
3666   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr);
3667   aij  = (Mat_SeqAIJ*)(*mat)->data;
3668   ierr = PetscMalloc2(m,PetscInt,&aij->imax,m,PetscInt,&aij->ilen);CHKERRQ(ierr);
3669 
3670   aij->i = i;
3671   aij->j = j;
3672   aij->a = a;
3673   aij->singlemalloc = PETSC_FALSE;
3674   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
3675   aij->free_a       = PETSC_FALSE;
3676   aij->free_ij      = PETSC_FALSE;
3677 
3678   for (ii=0; ii<m; ii++) {
3679     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
3680 #if defined(PETSC_USE_DEBUG)
3681     if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]);
3682     for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
3683       if (j[jj] < j[jj-1]) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is not sorted",jj-i[ii],j[jj],ii);
3684       if (j[jj] == j[jj]-1) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual colum %D) in row %D is identical to previous entry",jj-i[ii],j[jj],ii);
3685     }
3686 #endif
3687   }
3688 #if defined(PETSC_USE_DEBUG)
3689   for (ii=0; ii<aij->i[m]; ii++) {
3690     if (j[ii] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %d index = %d",ii,j[ii]);
3691     if (j[ii] > n - 1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %d index = %d",ii,j[ii]);
3692   }
3693 #endif
3694 
3695   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3696   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3697   PetscFunctionReturn(0);
3698 }
3699 
3700 #undef __FUNCT__
3701 #define __FUNCT__ "MatSetColoring_SeqAIJ"
3702 PetscErrorCode MatSetColoring_SeqAIJ(Mat A,ISColoring coloring)
3703 {
3704   PetscErrorCode ierr;
3705   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3706 
3707   PetscFunctionBegin;
3708   if (coloring->ctype == IS_COLORING_GLOBAL) {
3709     ierr        = ISColoringReference(coloring);CHKERRQ(ierr);
3710     a->coloring = coloring;
3711   } else if (coloring->ctype == IS_COLORING_GHOSTED) {
3712     PetscInt             i,*larray;
3713     ISColoring      ocoloring;
3714     ISColoringValue *colors;
3715 
3716     /* set coloring for diagonal portion */
3717     ierr = PetscMalloc(A->cmap->n*sizeof(PetscInt),&larray);CHKERRQ(ierr);
3718     for (i=0; i<A->cmap->n; i++) {
3719       larray[i] = i;
3720     }
3721     ierr = ISGlobalToLocalMappingApply(A->mapping,IS_GTOLM_MASK,A->cmap->n,larray,PETSC_NULL,larray);CHKERRQ(ierr);
3722     ierr = PetscMalloc(A->cmap->n*sizeof(ISColoringValue),&colors);CHKERRQ(ierr);
3723     for (i=0; i<A->cmap->n; i++) {
3724       colors[i] = coloring->colors[larray[i]];
3725     }
3726     ierr = PetscFree(larray);CHKERRQ(ierr);
3727     ierr = ISColoringCreate(PETSC_COMM_SELF,coloring->n,A->cmap->n,colors,&ocoloring);CHKERRQ(ierr);
3728     a->coloring = ocoloring;
3729   }
3730   PetscFunctionReturn(0);
3731 }
3732 
3733 #if defined(PETSC_HAVE_ADIC)
3734 EXTERN_C_BEGIN
3735 #include "adic/ad_utils.h"
3736 EXTERN_C_END
3737 
3738 #undef __FUNCT__
3739 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ"
3740 PetscErrorCode MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
3741 {
3742   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3743   PetscInt        m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j,nlen;
3744   PetscScalar     *v = a->a,*values = ((PetscScalar*)advalues)+1;
3745   ISColoringValue *color;
3746 
3747   PetscFunctionBegin;
3748   if (!a->coloring) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
3749   nlen  = PetscADGetDerivTypeSize()/sizeof(PetscScalar);
3750   color = a->coloring->colors;
3751   /* loop over rows */
3752   for (i=0; i<m; i++) {
3753     nz = ii[i+1] - ii[i];
3754     /* loop over columns putting computed value into matrix */
3755     for (j=0; j<nz; j++) {
3756       *v++ = values[color[*jj++]];
3757     }
3758     values += nlen; /* jump to next row of derivatives */
3759   }
3760   PetscFunctionReturn(0);
3761 }
3762 #endif
3763 
3764 #undef __FUNCT__
3765 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ"
3766 PetscErrorCode MatSetValuesAdifor_SeqAIJ(Mat A,PetscInt nl,void *advalues)
3767 {
3768   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3769   PetscInt         m = A->rmap->n,*ii = a->i,*jj = a->j,nz,i,j;
3770   MatScalar       *v = a->a;
3771   PetscScalar     *values = (PetscScalar *)advalues;
3772   ISColoringValue *color;
3773 
3774   PetscFunctionBegin;
3775   if (!a->coloring) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Coloring not set for matrix");
3776   color = a->coloring->colors;
3777   /* loop over rows */
3778   for (i=0; i<m; i++) {
3779     nz = ii[i+1] - ii[i];
3780     /* loop over columns putting computed value into matrix */
3781     for (j=0; j<nz; j++) {
3782       *v++ = values[color[*jj++]];
3783     }
3784     values += nl; /* jump to next row of derivatives */
3785   }
3786   PetscFunctionReturn(0);
3787 }
3788 
3789 /*
3790     Special version for direct calls from Fortran
3791 */
3792 #if defined(PETSC_HAVE_FORTRAN_CAPS)
3793 #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
3794 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
3795 #define matsetvaluesseqaij_ matsetvaluesseqaij
3796 #endif
3797 
3798 /* Change these macros so can be used in void function */
3799 #undef CHKERRQ
3800 #define CHKERRQ(ierr) CHKERRABORT(((PetscObject)A)->comm,ierr)
3801 #undef SETERRQ2
3802 #define SETERRQ2(ierr,b,c,d) CHKERRABORT(((PetscObject)A)->comm,ierr)
3803 
3804 EXTERN_C_BEGIN
3805 #undef __FUNCT__
3806 #define __FUNCT__ "matsetvaluesseqaij_"
3807 void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
3808 {
3809   Mat            A = *AA;
3810   PetscInt       m = *mm, n = *nn;
3811   InsertMode     is = *isis;
3812   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3813   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
3814   PetscInt       *imax,*ai,*ailen;
3815   PetscErrorCode ierr;
3816   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
3817   MatScalar      *ap,value,*aa;
3818   PetscTruth     ignorezeroentries = a->ignorezeroentries;
3819   PetscTruth     roworiented = a->roworiented;
3820 
3821   PetscFunctionBegin;
3822   ierr = MatPreallocated(A);CHKERRQ(ierr);
3823   imax = a->imax;
3824   ai = a->i;
3825   ailen = a->ilen;
3826   aj = a->j;
3827   aa = a->a;
3828 
3829   for (k=0; k<m; k++) { /* loop over added rows */
3830     row  = im[k];
3831     if (row < 0) continue;
3832 #if defined(PETSC_USE_DEBUG)
3833     if (row >= A->rmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
3834 #endif
3835     rp   = aj + ai[row]; ap = aa + ai[row];
3836     rmax = imax[row]; nrow = ailen[row];
3837     low  = 0;
3838     high = nrow;
3839     for (l=0; l<n; l++) { /* loop over added columns */
3840       if (in[l] < 0) continue;
3841 #if defined(PETSC_USE_DEBUG)
3842       if (in[l] >= A->cmap->n) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
3843 #endif
3844       col = in[l];
3845       if (roworiented) {
3846         value = v[l + k*n];
3847       } else {
3848         value = v[k + l*m];
3849       }
3850       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
3851 
3852       if (col <= lastcol) low = 0; else high = nrow;
3853       lastcol = col;
3854       while (high-low > 5) {
3855         t = (low+high)/2;
3856         if (rp[t] > col) high = t;
3857         else             low  = t;
3858       }
3859       for (i=low; i<high; i++) {
3860         if (rp[i] > col) break;
3861         if (rp[i] == col) {
3862           if (is == ADD_VALUES) ap[i] += value;
3863           else                  ap[i] = value;
3864           goto noinsert;
3865         }
3866       }
3867       if (value == 0.0 && ignorezeroentries) goto noinsert;
3868       if (nonew == 1) goto noinsert;
3869       if (nonew == -1) SETERRABORT(((PetscObject)A)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
3870       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
3871       N = nrow++ - 1; a->nz++; high++;
3872       /* shift up all the later entries in this row */
3873       for (ii=N; ii>=i; ii--) {
3874         rp[ii+1] = rp[ii];
3875         ap[ii+1] = ap[ii];
3876       }
3877       rp[i] = col;
3878       ap[i] = value;
3879       noinsert:;
3880       low = i + 1;
3881     }
3882     ailen[row] = nrow;
3883   }
3884   A->same_nonzero = PETSC_FALSE;
3885   PetscFunctionReturnVoid();
3886 }
3887 EXTERN_C_END
3888