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