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