xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 5ed2d596fd9914de76abbaed56c65f4792ae57ae)
1 /*$Id: aij.c,v 1.385 2001/09/07 20:09:22 bsmith Exp $*/
2 /*
3     Defines the basic matrix operations for the AIJ (compressed row)
4   matrix storage format.
5 */
6 
7 #include "src/mat/impls/aij/seq/aij.h"          /*I "petscmat.h" I*/
8 #include "src/vec/vecimpl.h"
9 #include "src/inline/spops.h"
10 #include "src/inline/dot.h"
11 #include "petscbt.h"
12 
13 
14 EXTERN int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**);
15 
16 #undef __FUNCT__
17 #define __FUNCT__ "MatGetRowIJ_SeqAIJ"
18 int MatGetRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *m,int **ia,int **ja,PetscTruth *done)
19 {
20   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21   int        ierr,i,ishift;
22 
23   PetscFunctionBegin;
24   *m     = A->m;
25   if (!ia) PetscFunctionReturn(0);
26   ishift = a->indexshift;
27   if (symmetric && !A->structurally_symmetric) {
28     ierr = MatToSymmetricIJ_SeqAIJ(A->m,a->i,a->j,ishift,oshift,ia,ja);CHKERRQ(ierr);
29   } else if (oshift == 0 && ishift == -1) {
30     int nz = a->i[A->m] - 1;
31     /* malloc space and  subtract 1 from i and j indices */
32     ierr = PetscMalloc((A->m+1)*sizeof(int),ia);CHKERRQ(ierr);
33     ierr = PetscMalloc((nz+1)*sizeof(int),ja);CHKERRQ(ierr);
34     for (i=0; i<nz; i++) (*ja)[i] = a->j[i] - 1;
35     for (i=0; i<A->m+1; i++) (*ia)[i] = a->i[i] - 1;
36   } else if (oshift == 1 && ishift == 0) {
37     int nz = a->i[A->m];
38     /* malloc space and  add 1 to i and j indices */
39     ierr = PetscMalloc((A->m+1)*sizeof(int),ia);CHKERRQ(ierr);
40     ierr = PetscMalloc((nz+1)*sizeof(int),ja);CHKERRQ(ierr);
41     for (i=0; i<nz; i++) (*ja)[i] = a->j[i] + 1;
42     for (i=0; i<A->m+1; i++) (*ia)[i] = a->i[i] + 1;
43   } else {
44     *ia = a->i; *ja = a->j;
45   }
46   PetscFunctionReturn(0);
47 }
48 
49 #undef __FUNCT__
50 #define __FUNCT__ "MatRestoreRowIJ_SeqAIJ"
51 int MatRestoreRowIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia,int **ja,PetscTruth *done)
52 {
53   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
54   int        ishift = a->indexshift,ierr;
55 
56   PetscFunctionBegin;
57   if (!ia) PetscFunctionReturn(0);
58   if ((symmetric && !A->structurally_symmetric) || (oshift == 0 && ishift == -1) || (oshift == 1 && ishift == 0)) {
59     ierr = PetscFree(*ia);CHKERRQ(ierr);
60     ierr = PetscFree(*ja);CHKERRQ(ierr);
61   }
62   PetscFunctionReturn(0);
63 }
64 
65 #undef __FUNCT__
66 #define __FUNCT__ "MatGetColumnIJ_SeqAIJ"
67 int MatGetColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *nn,int **ia,int **ja,PetscTruth *done)
68 {
69   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
70   int        ierr,i,ishift = a->indexshift,*collengths,*cia,*cja,n = A->n,m = A->m;
71   int        nz = a->i[m]+ishift,row,*jj,mr,col;
72 
73   PetscFunctionBegin;
74   *nn     = A->n;
75   if (!ia) PetscFunctionReturn(0);
76   if (symmetric) {
77     ierr = MatToSymmetricIJ_SeqAIJ(A->m,a->i,a->j,ishift,oshift,ia,ja);CHKERRQ(ierr);
78   } else {
79     ierr = PetscMalloc((n+1)*sizeof(int),&collengths);CHKERRQ(ierr);
80     ierr = PetscMemzero(collengths,n*sizeof(int));CHKERRQ(ierr);
81     ierr = PetscMalloc((n+1)*sizeof(int),&cia);CHKERRQ(ierr);
82     ierr = PetscMalloc((nz+1)*sizeof(int),&cja);CHKERRQ(ierr);
83     jj = a->j;
84     for (i=0; i<nz; i++) {
85       collengths[jj[i] + ishift]++;
86     }
87     cia[0] = oshift;
88     for (i=0; i<n; i++) {
89       cia[i+1] = cia[i] + collengths[i];
90     }
91     ierr = PetscMemzero(collengths,n*sizeof(int));CHKERRQ(ierr);
92     jj   = a->j;
93     for (row=0; row<m; row++) {
94       mr = a->i[row+1] - a->i[row];
95       for (i=0; i<mr; i++) {
96         col = *jj++ + ishift;
97         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
98       }
99     }
100     ierr = PetscFree(collengths);CHKERRQ(ierr);
101     *ia = cia; *ja = cja;
102   }
103   PetscFunctionReturn(0);
104 }
105 
106 #undef __FUNCT__
107 #define __FUNCT__ "MatRestoreColumnIJ_SeqAIJ"
108 int MatRestoreColumnIJ_SeqAIJ(Mat A,int oshift,PetscTruth symmetric,int *n,int **ia,int **ja,PetscTruth *done)
109 {
110   int ierr;
111 
112   PetscFunctionBegin;
113   if (!ia) PetscFunctionReturn(0);
114 
115   ierr = PetscFree(*ia);CHKERRQ(ierr);
116   ierr = PetscFree(*ja);CHKERRQ(ierr);
117 
118   PetscFunctionReturn(0);
119 }
120 
121 #define CHUNKSIZE   15
122 
123 #undef __FUNCT__
124 #define __FUNCT__ "MatSetValues_SeqAIJ"
125 int MatSetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,PetscScalar *v,InsertMode is)
126 {
127   Mat_SeqAIJ  *a = (Mat_SeqAIJ*)A->data;
128   int         *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,sorted = a->sorted;
129   int         *imax = a->imax,*ai = a->i,*ailen = a->ilen;
130   int         *aj = a->j,nonew = a->nonew,shift = a->indexshift,ierr;
131   PetscScalar *ap,value,*aa = a->a;
132   PetscTruth  ignorezeroentries = ((a->ignorezeroentries && is == ADD_VALUES) ? PETSC_TRUE:PETSC_FALSE);
133   PetscTruth  roworiented = a->roworiented;
134 
135   PetscFunctionBegin;
136   for (k=0; k<m; k++) { /* loop over added rows */
137     row  = im[k];
138     if (row < 0) continue;
139 #if defined(PETSC_USE_BOPT_g)
140     if (row >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %d max %d",row,A->m);
141 #endif
142     rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
143     rmax = imax[row]; nrow = ailen[row];
144     low = 0;
145     for (l=0; l<n; l++) { /* loop over added columns */
146       if (in[l] < 0) continue;
147 #if defined(PETSC_USE_BOPT_g)
148       if (in[l] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %d max %d",in[l],A->n);
149 #endif
150       col = in[l] - shift;
151       if (roworiented) {
152         value = v[l + k*n];
153       } else {
154         value = v[k + l*m];
155       }
156       if (value == 0.0 && ignorezeroentries) continue;
157 
158       if (!sorted) low = 0; high = nrow;
159       while (high-low > 5) {
160         t = (low+high)/2;
161         if (rp[t] > col) high = t;
162         else             low  = t;
163       }
164       for (i=low; i<high; i++) {
165         if (rp[i] > col) break;
166         if (rp[i] == col) {
167           if (is == ADD_VALUES) ap[i] += value;
168           else                  ap[i] = value;
169           goto noinsert;
170         }
171       }
172       if (nonew == 1) goto noinsert;
173       else if (nonew == -1) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%d,%d) in the matrix",row,col);
174       if (nrow >= rmax) {
175         /* there is no extra room in row, therefore enlarge */
176         int         new_nz = ai[A->m] + CHUNKSIZE,len,*new_i,*new_j;
177         PetscScalar *new_a;
178 
179         if (nonew == -2) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%d,%d) in the matrix requiring new malloc()",row,col);
180 
181         /* malloc new storage space */
182         len     = new_nz*(sizeof(int)+sizeof(PetscScalar))+(A->m+1)*sizeof(int);
183 	ierr    = PetscMalloc(len,&new_a);CHKERRQ(ierr);
184         new_j   = (int*)(new_a + new_nz);
185         new_i   = new_j + new_nz;
186 
187         /* copy over old data into new slots */
188         for (ii=0; ii<row+1; ii++) {new_i[ii] = ai[ii];}
189         for (ii=row+1; ii<A->m+1; ii++) {new_i[ii] = ai[ii]+CHUNKSIZE;}
190         ierr = PetscMemcpy(new_j,aj,(ai[row]+nrow+shift)*sizeof(int));CHKERRQ(ierr);
191         len  = (new_nz - CHUNKSIZE - ai[row] - nrow - shift);
192         ierr = PetscMemcpy(new_j+ai[row]+shift+nrow+CHUNKSIZE,aj+ai[row]+shift+nrow,len*sizeof(int));CHKERRQ(ierr);
193         ierr = PetscMemcpy(new_a,aa,(ai[row]+nrow+shift)*sizeof(PetscScalar));CHKERRQ(ierr);
194         ierr = PetscMemcpy(new_a+ai[row]+shift+nrow+CHUNKSIZE,aa+ai[row]+shift+nrow,len*sizeof(PetscScalar));CHKERRQ(ierr);
195         /* free up old matrix storage */
196         ierr = PetscFree(a->a);CHKERRQ(ierr);
197         if (!a->singlemalloc) {
198           ierr = PetscFree(a->i);CHKERRQ(ierr);
199           ierr = PetscFree(a->j);CHKERRQ(ierr);
200         }
201         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
202         a->singlemalloc = PETSC_TRUE;
203 
204         rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
205         rmax = imax[row] = imax[row] + CHUNKSIZE;
206         PetscLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + sizeof(PetscScalar)));
207         a->maxnz += CHUNKSIZE;
208         a->reallocs++;
209       }
210       N = nrow++ - 1; a->nz++;
211       /* shift up all the later entries in this row */
212       for (ii=N; ii>=i; ii--) {
213         rp[ii+1] = rp[ii];
214         ap[ii+1] = ap[ii];
215       }
216       rp[i] = col;
217       ap[i] = value;
218       noinsert:;
219       low = i + 1;
220     }
221     ailen[row] = nrow;
222   }
223   PetscFunctionReturn(0);
224 }
225 
226 #undef __FUNCT__
227 #define __FUNCT__ "MatGetValues_SeqAIJ"
228 int MatGetValues_SeqAIJ(Mat A,int m,int *im,int n,int *in,PetscScalar *v)
229 {
230   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
231   int          *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
232   int          *ai = a->i,*ailen = a->ilen,shift = a->indexshift;
233   PetscScalar  *ap,*aa = a->a,zero = 0.0;
234 
235   PetscFunctionBegin;
236   for (k=0; k<m; k++) { /* loop over rows */
237     row  = im[k];
238     if (row < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %d",row);
239     if (row >= A->m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: %d",row);
240     rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
241     nrow = ailen[row];
242     for (l=0; l<n; l++) { /* loop over columns */
243       if (in[l] < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %d",in[l]);
244       if (in[l] >= A->n) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: %d",in[l]);
245       col = in[l] - shift;
246       high = nrow; low = 0; /* assume unsorted */
247       while (high-low > 5) {
248         t = (low+high)/2;
249         if (rp[t] > col) high = t;
250         else             low  = t;
251       }
252       for (i=low; i<high; i++) {
253         if (rp[i] > col) break;
254         if (rp[i] == col) {
255           *v++ = ap[i];
256           goto finished;
257         }
258       }
259       *v++ = zero;
260       finished:;
261     }
262   }
263   PetscFunctionReturn(0);
264 }
265 
266 
267 #undef __FUNCT__
268 #define __FUNCT__ "MatView_SeqAIJ_Binary"
269 int MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer)
270 {
271   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
272   int        i,fd,*col_lens,ierr;
273 
274   PetscFunctionBegin;
275   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
276   ierr = PetscMalloc((4+A->m)*sizeof(int),&col_lens);CHKERRQ(ierr);
277   col_lens[0] = MAT_FILE_COOKIE;
278   col_lens[1] = A->m;
279   col_lens[2] = A->n;
280   col_lens[3] = a->nz;
281 
282   /* store lengths of each row and write (including header) to file */
283   for (i=0; i<A->m; i++) {
284     col_lens[4+i] = a->i[i+1] - a->i[i];
285   }
286   ierr = PetscBinaryWrite(fd,col_lens,4+A->m,PETSC_INT,1);CHKERRQ(ierr);
287   ierr = PetscFree(col_lens);CHKERRQ(ierr);
288 
289   /* store column indices (zero start index) */
290   if (a->indexshift) {
291     for (i=0; i<a->nz; i++) a->j[i]--;
292   }
293   ierr = PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,0);CHKERRQ(ierr);
294   if (a->indexshift) {
295     for (i=0; i<a->nz; i++) a->j[i]++;
296   }
297 
298   /* store nonzero values */
299   ierr = PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,0);CHKERRQ(ierr);
300   PetscFunctionReturn(0);
301 }
302 
303 extern int MatMPIAIJFactorInfo_SuperLu(Mat,PetscViewer);
304 extern int MatSeqAIJFactorInfo_Spooles(Mat,PetscViewer);
305 
306 #undef __FUNCT__
307 #define __FUNCT__ "MatView_SeqAIJ_ASCII"
308 int MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
309 {
310   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
311   int               ierr,i,j,m = A->m,shift = a->indexshift;
312   char              *name;
313   PetscViewerFormat format;
314 
315   PetscFunctionBegin;
316   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
317   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
318   if (format == PETSC_VIEWER_ASCII_INFO_LONG || format == PETSC_VIEWER_ASCII_INFO) {
319     if (a->inode.size) {
320       ierr = PetscViewerASCIIPrintf(viewer,"using I-node routines: found %d nodes, limit used is %d\n",a->inode.node_count,a->inode.limit);CHKERRQ(ierr);
321     } else {
322       ierr = PetscViewerASCIIPrintf(viewer,"not using I-node routines\n");CHKERRQ(ierr);
323     }
324   } else if (format == PETSC_VIEWER_ASCII_MATLAB) {
325     int nofinalvalue = 0;
326     if ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->n-!shift)) {
327       nofinalvalue = 1;
328     }
329     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
330     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %d %d \n",m,A->n);CHKERRQ(ierr);
331     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %d \n",a->nz);CHKERRQ(ierr);
332     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%d,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
333     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
334 
335     for (i=0; i<m; i++) {
336       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
337 #if defined(PETSC_USE_COMPLEX)
338         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);
339 #else
340         ierr = PetscViewerASCIIPrintf(viewer,"%d %d  %18.16e\n",i+1,a->j[j]+!shift,a->a[j]);CHKERRQ(ierr);
341 #endif
342       }
343     }
344     if (nofinalvalue) {
345       ierr = PetscViewerASCIIPrintf(viewer,"%d %d  %18.16e\n",m,A->n,0.0);CHKERRQ(ierr);
346     }
347     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
348     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
349   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
350 #if defined(PETSC_HAVE_SUPERLUDIST) && !defined(PETSC_USE_SINGLE) && !defined(PETSC_USE_COMPLEX)
351      ierr = MatMPIAIJFactorInfo_SuperLu(A,viewer);CHKERRQ(ierr);
352 #endif
353 #if defined(PETSC_HAVE_SPOOLES) && !defined(PETSC_USE_SINGLE) && !defined(PETSC_USE_COMPLEX)
354      ierr = MatSeqAIJFactorInfo_Spooles(A,viewer);CHKERRQ(ierr);
355 #endif
356      PetscFunctionReturn(0);
357   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
358     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
359     for (i=0; i<m; i++) {
360       ierr = PetscViewerASCIIPrintf(viewer,"row %d:",i);CHKERRQ(ierr);
361       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
362 #if defined(PETSC_USE_COMPLEX)
363         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
364           ierr = PetscViewerASCIIPrintf(viewer," (%d, %g + %g i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
365         } else 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 (PetscRealPart(a->a[j]) != 0.0) {
368           ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
369         }
370 #else
371         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);}
372 #endif
373       }
374       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
375     }
376     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
377   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
378     int nzd=0,fshift=1,*sptr;
379     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
380     ierr = PetscMalloc((m+1)*sizeof(int),&sptr);CHKERRQ(ierr);
381     for (i=0; i<m; i++) {
382       sptr[i] = nzd+1;
383       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
384         if (a->j[j] >= i) {
385 #if defined(PETSC_USE_COMPLEX)
386           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
387 #else
388           if (a->a[j] != 0.0) nzd++;
389 #endif
390         }
391       }
392     }
393     sptr[m] = nzd+1;
394     ierr = PetscViewerASCIIPrintf(viewer," %d %d\n\n",m,nzd);CHKERRQ(ierr);
395     for (i=0; i<m+1; i+=6) {
396       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);}
397       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);}
398       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);}
399       else if (i+1<m) {ierr = PetscViewerASCIIPrintf(viewer," %d %d %d\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);}
400       else if (i<m)   {ierr = PetscViewerASCIIPrintf(viewer," %d %d\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);}
401       else            {ierr = PetscViewerASCIIPrintf(viewer," %d\n",sptr[i]);CHKERRQ(ierr);}
402     }
403     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
404     ierr = PetscFree(sptr);CHKERRQ(ierr);
405     for (i=0; i<m; i++) {
406       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
407         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %d ",a->j[j]+fshift);CHKERRQ(ierr);}
408       }
409       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
410     }
411     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
412     for (i=0; i<m; i++) {
413       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
414         if (a->j[j] >= i) {
415 #if defined(PETSC_USE_COMPLEX)
416           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
417             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
418           }
419 #else
420           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",a->a[j]);CHKERRQ(ierr);}
421 #endif
422         }
423       }
424       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
425     }
426     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
427   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
428     int         cnt = 0,jcnt;
429     PetscScalar value;
430 
431     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
432     for (i=0; i<m; i++) {
433       jcnt = 0;
434       for (j=0; j<A->n; j++) {
435         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
436           value = a->a[cnt++];
437           jcnt++;
438         } else {
439           value = 0.0;
440         }
441 #if defined(PETSC_USE_COMPLEX)
442         ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",PetscRealPart(value),PetscImaginaryPart(value));CHKERRQ(ierr);
443 #else
444         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",value);CHKERRQ(ierr);
445 #endif
446       }
447       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
448     }
449     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
450   } else {
451     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
452     for (i=0; i<m; i++) {
453       ierr = PetscViewerASCIIPrintf(viewer,"row %d:",i);CHKERRQ(ierr);
454       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
455 #if defined(PETSC_USE_COMPLEX)
456         if (PetscImaginaryPart(a->a[j]) > 0.0) {
457           ierr = PetscViewerASCIIPrintf(viewer," (%d, %g + %g i)",a->j[j]+shift,PetscRealPart(a->a[j]),PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
458         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
459           ierr = PetscViewerASCIIPrintf(viewer," (%d, %g - %g i)",a->j[j]+shift,PetscRealPart(a->a[j]),-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
460         } else {
461           ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,PetscRealPart(a->a[j]));CHKERRQ(ierr);
462         }
463 #else
464         ierr = PetscViewerASCIIPrintf(viewer," (%d, %g) ",a->j[j]+shift,a->a[j]);CHKERRQ(ierr);
465 #endif
466       }
467       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
468     }
469     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
470   }
471   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
472   PetscFunctionReturn(0);
473 }
474 
475 #undef __FUNCT__
476 #define __FUNCT__ "MatView_SeqAIJ_Draw_Zoom"
477 int MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
478 {
479   Mat               A = (Mat) Aa;
480   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
481   int               ierr,i,j,m = A->m,shift = a->indexshift,color;
482   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r,maxv = 0.0;
483   PetscViewer       viewer;
484   PetscViewerFormat format;
485 
486   PetscFunctionBegin;
487   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
488   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
489 
490   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
491   /* loop over matrix elements drawing boxes */
492 
493   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
494     /* Blue for negative, Cyan for zero and  Red for positive */
495     color = PETSC_DRAW_BLUE;
496     for (i=0; i<m; i++) {
497       y_l = m - i - 1.0; y_r = y_l + 1.0;
498       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
499         x_l = a->j[j] + shift; x_r = x_l + 1.0;
500 #if defined(PETSC_USE_COMPLEX)
501         if (PetscRealPart(a->a[j]) >=  0.) continue;
502 #else
503         if (a->a[j] >=  0.) continue;
504 #endif
505         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
506       }
507     }
508     color = PETSC_DRAW_CYAN;
509     for (i=0; i<m; i++) {
510       y_l = m - i - 1.0; y_r = y_l + 1.0;
511       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
512         x_l = a->j[j] + shift; x_r = x_l + 1.0;
513         if (a->a[j] !=  0.) continue;
514         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
515       }
516     }
517     color = PETSC_DRAW_RED;
518     for (i=0; i<m; i++) {
519       y_l = m - i - 1.0; y_r = y_l + 1.0;
520       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
521         x_l = a->j[j] + shift; x_r = x_l + 1.0;
522 #if defined(PETSC_USE_COMPLEX)
523         if (PetscRealPart(a->a[j]) <=  0.) continue;
524 #else
525         if (a->a[j] <=  0.) continue;
526 #endif
527         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
528       }
529     }
530   } else {
531     /* use contour shading to indicate magnitude of values */
532     /* first determine max of all nonzero values */
533     int    nz = a->nz,count;
534     PetscDraw   popup;
535     PetscReal scale;
536 
537     for (i=0; i<nz; i++) {
538       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
539     }
540     scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv;
541     ierr  = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
542     if (popup) {ierr  = PetscDrawScalePopup(popup,0.0,maxv);CHKERRQ(ierr);}
543     count = 0;
544     for (i=0; i<m; i++) {
545       y_l = m - i - 1.0; y_r = y_l + 1.0;
546       for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
547         x_l = a->j[j] + shift; x_r = x_l + 1.0;
548         color = PETSC_DRAW_BASIC_COLORS + (int)(scale*PetscAbsScalar(a->a[count]));
549         ierr  = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
550         count++;
551       }
552     }
553   }
554   PetscFunctionReturn(0);
555 }
556 
557 #undef __FUNCT__
558 #define __FUNCT__ "MatView_SeqAIJ_Draw"
559 int MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
560 {
561   int        ierr;
562   PetscDraw  draw;
563   PetscReal  xr,yr,xl,yl,h,w;
564   PetscTruth isnull;
565 
566   PetscFunctionBegin;
567   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
568   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
569   if (isnull) PetscFunctionReturn(0);
570 
571   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
572   xr  = A->n; yr = A->m; h = yr/10.0; w = xr/10.0;
573   xr += w;    yr += h;  xl = -w;     yl = -h;
574   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
575   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
576   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
577   PetscFunctionReturn(0);
578 }
579 
580 #undef __FUNCT__
581 #define __FUNCT__ "MatView_SeqAIJ"
582 int MatView_SeqAIJ(Mat A,PetscViewer viewer)
583 {
584   Mat_SeqAIJ  *a = (Mat_SeqAIJ*)A->data;
585   int         ierr;
586   PetscTruth  issocket,isascii,isbinary,isdraw;
587 
588   PetscFunctionBegin;
589   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);CHKERRQ(ierr);
590   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
591   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);CHKERRQ(ierr);
592   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
593   if (issocket) {
594     if (a->indexshift) {
595       SETERRQ(1,"Can only socket send sparse matrix with 0 based indexing");
596     }
597     ierr = PetscViewerSocketPutSparse_Private(viewer,A->m,A->n,a->nz,a->a,a->i,a->j);CHKERRQ(ierr);
598   } else if (isascii) {
599     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
600   } else if (isbinary) {
601     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
602   } else if (isdraw) {
603     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
604   } else {
605     SETERRQ1(1,"Viewer type %s not supported by SeqAIJ matrices",((PetscObject)viewer)->type_name);
606   }
607   PetscFunctionReturn(0);
608 }
609 
610 EXTERN int Mat_AIJ_CheckInode(Mat,PetscTruth);
611 EXTERN int MatUseSuperLU_DIST_MPIAIJ(Mat);
612 EXTERN int MatUseSpooles_SeqAIJ(Mat);
613 #undef __FUNCT__
614 #define __FUNCT__ "MatAssemblyEnd_SeqAIJ"
615 int MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
616 {
617   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
618   int          fshift = 0,i,j,*ai = a->i,*aj = a->j,*imax = a->imax,ierr;
619   int          m = A->m,*ip,N,*ailen = a->ilen,shift = a->indexshift,rmax = 0;
620   PetscScalar  *aa = a->a,*ap;
621 #if defined(PETSC_HAVE_SUPERLUDIST) || defined(PETSC_HAVE_SPOOLES)
622   PetscTruth   flag;
623 #endif
624 
625   PetscFunctionBegin;
626   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
627 
628   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
629   for (i=1; i<m; i++) {
630     /* move each row back by the amount of empty slots (fshift) before it*/
631     fshift += imax[i-1] - ailen[i-1];
632     rmax   = PetscMax(rmax,ailen[i]);
633     if (fshift) {
634       ip = aj + ai[i] + shift;
635       ap = aa + ai[i] + shift;
636       N  = ailen[i];
637       for (j=0; j<N; j++) {
638         ip[j-fshift] = ip[j];
639         ap[j-fshift] = ap[j];
640       }
641     }
642     ai[i] = ai[i-1] + ailen[i-1];
643   }
644   if (m) {
645     fshift += imax[m-1] - ailen[m-1];
646     ai[m]  = ai[m-1] + ailen[m-1];
647   }
648   /* reset ilen and imax for each row */
649   for (i=0; i<m; i++) {
650     ailen[i] = imax[i] = ai[i+1] - ai[i];
651   }
652   a->nz = ai[m] + shift;
653 
654   /* diagonals may have moved, so kill the diagonal pointers */
655   if (fshift && a->diag) {
656     ierr = PetscFree(a->diag);CHKERRQ(ierr);
657     PetscLogObjectMemory(A,-(m+1)*sizeof(int));
658     a->diag = 0;
659   }
660   PetscLogInfo(A,"MatAssemblyEnd_SeqAIJ:Matrix size: %d X %d; storage space: %d unneeded,%d used\n",m,A->n,fshift,a->nz);
661   PetscLogInfo(A,"MatAssemblyEnd_SeqAIJ:Number of mallocs during MatSetValues() is %d\n",a->reallocs);
662   PetscLogInfo(A,"MatAssemblyEnd_SeqAIJ:Most nonzeros in any row is %d\n",rmax);
663   a->reallocs          = 0;
664   A->info.nz_unneeded  = (double)fshift;
665   a->rmax              = rmax;
666 
667   /* check out for identical nodes. If found, use inode functions */
668   ierr = Mat_AIJ_CheckInode(A,(PetscTruth)(!fshift));CHKERRQ(ierr);
669 
670 #if defined(PETSC_HAVE_SUPERLUDIST)
671   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_superlu_dist",&flag);CHKERRQ(ierr);
672   if (flag) { ierr = MatUseSuperLU_DIST_MPIAIJ(A);CHKERRQ(ierr); }
673 #endif
674 
675 #if defined(PETSC_HAVE_SPOOLES)
676   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_spooles",&flag);CHKERRQ(ierr);
677   if (flag) { ierr = MatUseSpooles_SeqAIJ(A);CHKERRQ(ierr); }
678 #endif
679 
680   PetscFunctionReturn(0);
681 }
682 
683 #undef __FUNCT__
684 #define __FUNCT__ "MatZeroEntries_SeqAIJ"
685 int MatZeroEntries_SeqAIJ(Mat A)
686 {
687   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
688   int        ierr;
689 
690   PetscFunctionBegin;
691   ierr = PetscMemzero(a->a,(a->i[A->m]+a->indexshift)*sizeof(PetscScalar));CHKERRQ(ierr);
692   PetscFunctionReturn(0);
693 }
694 
695 #undef __FUNCT__
696 #define __FUNCT__ "MatDestroy_SeqAIJ"
697 int MatDestroy_SeqAIJ(Mat A)
698 {
699   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
700   int        ierr;
701 
702   PetscFunctionBegin;
703 #if defined(PETSC_USE_LOG)
704   PetscLogObjectState((PetscObject)A,"Rows=%d, Cols=%d, NZ=%d",A->m,A->n,a->nz);
705 #endif
706   if (a->freedata) {
707     ierr = PetscFree(a->a);CHKERRQ(ierr);
708     if (!a->singlemalloc) {
709       ierr = PetscFree(a->i);CHKERRQ(ierr);
710       ierr = PetscFree(a->j);CHKERRQ(ierr);
711     }
712   }
713   if (a->row) {
714     ierr = ISDestroy(a->row);CHKERRQ(ierr);
715   }
716   if (a->col) {
717     ierr = ISDestroy(a->col);CHKERRQ(ierr);
718   }
719   if (a->diag) {ierr = PetscFree(a->diag);CHKERRQ(ierr);}
720   if (a->ilen) {ierr = PetscFree(a->ilen);CHKERRQ(ierr);}
721   if (a->imax) {ierr = PetscFree(a->imax);CHKERRQ(ierr);}
722   if (a->idiag) {ierr = PetscFree(a->idiag);CHKERRQ(ierr);}
723   if (a->solve_work) {ierr = PetscFree(a->solve_work);CHKERRQ(ierr);}
724   if (a->inode.size) {ierr = PetscFree(a->inode.size);CHKERRQ(ierr);}
725   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);}
726   if (a->saved_values) {ierr = PetscFree(a->saved_values);CHKERRQ(ierr);}
727   if (a->coloring) {ierr = ISColoringDestroy(a->coloring);CHKERRQ(ierr);}
728   ierr = PetscFree(a);CHKERRQ(ierr);
729   PetscFunctionReturn(0);
730 }
731 
732 #undef __FUNCT__
733 #define __FUNCT__ "MatCompress_SeqAIJ"
734 int MatCompress_SeqAIJ(Mat A)
735 {
736   PetscFunctionBegin;
737   PetscFunctionReturn(0);
738 }
739 
740 #undef __FUNCT__
741 #define __FUNCT__ "MatSetOption_SeqAIJ"
742 int MatSetOption_SeqAIJ(Mat A,MatOption op)
743 {
744   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
745 
746   PetscFunctionBegin;
747   switch (op) {
748     case MAT_ROW_ORIENTED:
749       a->roworiented       = PETSC_TRUE;
750       break;
751     case MAT_KEEP_ZEROED_ROWS:
752       a->keepzeroedrows    = PETSC_TRUE;
753       break;
754     case MAT_COLUMN_ORIENTED:
755       a->roworiented       = PETSC_FALSE;
756       break;
757     case MAT_COLUMNS_SORTED:
758       a->sorted            = PETSC_TRUE;
759       break;
760     case MAT_COLUMNS_UNSORTED:
761       a->sorted            = PETSC_FALSE;
762       break;
763     case MAT_NO_NEW_NONZERO_LOCATIONS:
764       a->nonew             = 1;
765       break;
766     case MAT_NEW_NONZERO_LOCATION_ERR:
767       a->nonew             = -1;
768       break;
769     case MAT_NEW_NONZERO_ALLOCATION_ERR:
770       a->nonew             = -2;
771       break;
772     case MAT_YES_NEW_NONZERO_LOCATIONS:
773       a->nonew             = 0;
774       break;
775     case MAT_IGNORE_ZERO_ENTRIES:
776       a->ignorezeroentries = PETSC_TRUE;
777       break;
778     case MAT_USE_INODES:
779       a->inode.use         = PETSC_TRUE;
780       break;
781     case MAT_DO_NOT_USE_INODES:
782       a->inode.use         = PETSC_FALSE;
783       break;
784     case MAT_ROWS_SORTED:
785     case MAT_ROWS_UNSORTED:
786     case MAT_YES_NEW_DIAGONALS:
787     case MAT_IGNORE_OFF_PROC_ENTRIES:
788     case MAT_USE_HASH_TABLE:
789     case MAT_USE_SINGLE_PRECISION_SOLVES:
790       PetscLogInfo(A,"MatSetOption_SeqAIJ:Option ignored\n");
791       break;
792     case MAT_NO_NEW_DIAGONALS:
793       SETERRQ(PETSC_ERR_SUP,"MAT_NO_NEW_DIAGONALS");
794     case MAT_INODE_LIMIT_1:
795       a->inode.limit  = 1;
796       break;
797     case MAT_INODE_LIMIT_2:
798       a->inode.limit  = 2;
799       break;
800     case MAT_INODE_LIMIT_3:
801       a->inode.limit  = 3;
802       break;
803     case MAT_INODE_LIMIT_4:
804       a->inode.limit  = 4;
805       break;
806     case MAT_INODE_LIMIT_5:
807       a->inode.limit  = 5;
808       break;
809     default:
810       SETERRQ(PETSC_ERR_SUP,"unknown option");
811   }
812   PetscFunctionReturn(0);
813 }
814 
815 #undef __FUNCT__
816 #define __FUNCT__ "MatGetDiagonal_SeqAIJ"
817 int MatGetDiagonal_SeqAIJ(Mat A,Vec v)
818 {
819   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
820   int          i,j,n,shift = a->indexshift,ierr;
821   PetscScalar  *x,zero = 0.0;
822 
823   PetscFunctionBegin;
824   ierr = VecSet(&zero,v);CHKERRQ(ierr);
825   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
826   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
827   if (n != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
828   for (i=0; i<A->m; i++) {
829     for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
830       if (a->j[j]+shift == i) {
831         x[i] = a->a[j];
832         break;
833       }
834     }
835   }
836   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
837   PetscFunctionReturn(0);
838 }
839 
840 
841 #undef __FUNCT__
842 #define __FUNCT__ "MatMultTransposeAdd_SeqAIJ"
843 int MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
844 {
845   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
846   PetscScalar  *x,*y;
847   int          ierr,m = A->m,shift = a->indexshift;
848 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
849   PetscScalar  *v,alpha;
850   int          n,i,*idx;
851 #endif
852 
853   PetscFunctionBegin;
854   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
855   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
856   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
857   y = y + shift; /* shift for Fortran start by 1 indexing */
858 
859 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
860   fortranmulttransposeaddaij_(&m,x,a->i,a->j+shift,a->a+shift,y);
861 #else
862   for (i=0; i<m; i++) {
863     idx   = a->j + a->i[i] + shift;
864     v     = a->a + a->i[i] + shift;
865     n     = a->i[i+1] - a->i[i];
866     alpha = x[i];
867     while (n-->0) {y[*idx++] += alpha * *v++;}
868   }
869 #endif
870   PetscLogFlops(2*a->nz);
871   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
872   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
873   PetscFunctionReturn(0);
874 }
875 
876 #undef __FUNCT__
877 #define __FUNCT__ "MatMultTranspose_SeqAIJ"
878 int MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
879 {
880   PetscScalar  zero = 0.0;
881   int          ierr;
882 
883   PetscFunctionBegin;
884   ierr = VecSet(&zero,yy);CHKERRQ(ierr);
885   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
886   PetscFunctionReturn(0);
887 }
888 
889 
890 #undef __FUNCT__
891 #define __FUNCT__ "MatMult_SeqAIJ"
892 int MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
893 {
894   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
895   PetscScalar  *x,*y,*v,sum;
896   int          ierr,m = A->m,*idx,shift = a->indexshift,*ii;
897 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
898   int          n,i,jrow,j;
899 #endif
900 
901 #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
902 #pragma disjoint(*x,*y,*v)
903 #endif
904 
905   PetscFunctionBegin;
906   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
907   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
908   x    = x + shift;    /* shift for Fortran start by 1 indexing */
909   idx  = a->j;
910   v    = a->a;
911   ii   = a->i;
912 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
913   fortranmultaij_(&m,x,ii,idx+shift,v+shift,y);
914 #else
915   v    += shift; /* shift for Fortran start by 1 indexing */
916   idx  += shift;
917   for (i=0; i<m; i++) {
918     jrow = ii[i];
919     n    = ii[i+1] - jrow;
920     sum  = 0.0;
921     for (j=0; j<n; j++) {
922       sum += v[jrow]*x[idx[jrow]]; jrow++;
923      }
924     y[i] = sum;
925   }
926 #endif
927   PetscLogFlops(2*a->nz - m);
928   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
929   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
930   PetscFunctionReturn(0);
931 }
932 
933 #undef __FUNCT__
934 #define __FUNCT__ "MatMultAdd_SeqAIJ"
935 int MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
936 {
937   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
938   PetscScalar  *x,*y,*z,*v,sum;
939   int          ierr,m = A->m,*idx,shift = a->indexshift,*ii;
940 #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
941   int          n,i,jrow,j;
942 #endif
943 
944   PetscFunctionBegin;
945   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
946   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
947   if (zz != yy) {
948     ierr = VecGetArray(zz,&z);CHKERRQ(ierr);
949   } else {
950     z = y;
951   }
952   x    = x + shift; /* shift for Fortran start by 1 indexing */
953   idx  = a->j;
954   v    = a->a;
955   ii   = a->i;
956 #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
957   fortranmultaddaij_(&m,x,ii,idx+shift,v+shift,y,z);
958 #else
959   v   += shift; /* shift for Fortran start by 1 indexing */
960   idx += shift;
961   for (i=0; i<m; i++) {
962     jrow = ii[i];
963     n    = ii[i+1] - jrow;
964     sum  = y[i];
965     for (j=0; j<n; j++) {
966       sum += v[jrow]*x[idx[jrow]]; jrow++;
967      }
968     z[i] = sum;
969   }
970 #endif
971   PetscLogFlops(2*a->nz);
972   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
973   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
974   if (zz != yy) {
975     ierr = VecRestoreArray(zz,&z);CHKERRQ(ierr);
976   }
977   PetscFunctionReturn(0);
978 }
979 
980 /*
981      Adds diagonal pointers to sparse matrix structure.
982 */
983 #undef __FUNCT__
984 #define __FUNCT__ "MatMarkDiagonal_SeqAIJ"
985 int MatMarkDiagonal_SeqAIJ(Mat A)
986 {
987   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
988   int        i,j,*diag,m = A->m,shift = a->indexshift,ierr;
989 
990   PetscFunctionBegin;
991   if (a->diag) PetscFunctionReturn(0);
992 
993   ierr = PetscMalloc((m+1)*sizeof(int),&diag);CHKERRQ(ierr);
994   PetscLogObjectMemory(A,(m+1)*sizeof(int));
995   for (i=0; i<A->m; i++) {
996     diag[i] = a->i[i+1];
997     for (j=a->i[i]+shift; j<a->i[i+1]+shift; j++) {
998       if (a->j[j]+shift == i) {
999         diag[i] = j - shift;
1000         break;
1001       }
1002     }
1003   }
1004   a->diag = diag;
1005   PetscFunctionReturn(0);
1006 }
1007 
1008 /*
1009      Checks for missing diagonals
1010 */
1011 #undef __FUNCT__
1012 #define __FUNCT__ "MatMissingDiagonal_SeqAIJ"
1013 int MatMissingDiagonal_SeqAIJ(Mat A)
1014 {
1015   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1016   int        *diag,*jj = a->j,i,shift = a->indexshift,ierr;
1017 
1018   PetscFunctionBegin;
1019   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1020   diag = a->diag;
1021   for (i=0; i<A->m; i++) {
1022     if (jj[diag[i]+shift] != i-shift) {
1023       SETERRQ1(1,"Matrix is missing diagonal number %d",i);
1024     }
1025   }
1026   PetscFunctionReturn(0);
1027 }
1028 
1029 #undef __FUNCT__
1030 #define __FUNCT__ "MatRelax_SeqAIJ"
1031 int MatRelax_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,int its,int lits,Vec xx)
1032 {
1033   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
1034   PetscScalar  *x,*b,*bs, d,*xs,sum,*v = a->a,*t=0,scale,*ts,*xb,*idiag=0;
1035   int          ierr,*idx,*diag,n = A->n,m = A->m,i,shift = a->indexshift;
1036 
1037   PetscFunctionBegin;
1038   its = its*lits;
1039   if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %d and local its %d both positive",its,lits);
1040 
1041   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
1042   if (xx != bb) {
1043     ierr = VecGetArray(bb,&b);CHKERRQ(ierr);
1044   } else {
1045     b = x;
1046   }
1047 
1048   if (!a->diag) {ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);}
1049   diag = a->diag;
1050   xs   = x + shift; /* shifted by one for index start of a or a->j*/
1051   if (flag == SOR_APPLY_UPPER) {
1052    /* apply (U + D/omega) to the vector */
1053     bs = b + shift;
1054     for (i=0; i<m; i++) {
1055         d    = fshift + a->a[diag[i] + shift];
1056         n    = a->i[i+1] - diag[i] - 1;
1057 	PetscLogFlops(2*n-1);
1058         idx  = a->j + diag[i] + (!shift);
1059         v    = a->a + diag[i] + (!shift);
1060         sum  = b[i]*d/omega;
1061         SPARSEDENSEDOT(sum,bs,v,idx,n);
1062         x[i] = sum;
1063     }
1064     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1065     if (bb != xx) {ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);}
1066     PetscFunctionReturn(0);
1067   }
1068 
1069   /* setup workspace for Eisenstat */
1070   if (flag & SOR_EISENSTAT) {
1071     if (!a->idiag) {
1072       ierr     = PetscMalloc(2*m*sizeof(PetscScalar),&a->idiag);CHKERRQ(ierr);
1073       a->ssor  = a->idiag + m;
1074       v        = a->a;
1075       for (i=0; i<m; i++) { a->idiag[i] = 1.0/v[diag[i]];}
1076     }
1077     t     = a->ssor;
1078     idiag = a->idiag;
1079   }
1080     /* Let  A = L + U + D; where L is lower trianglar,
1081     U is upper triangular, E is diagonal; This routine applies
1082 
1083             (L + E)^{-1} A (U + E)^{-1}
1084 
1085     to a vector efficiently using Eisenstat's trick. This is for
1086     the case of SSOR preconditioner, so E is D/omega where omega
1087     is the relaxation factor.
1088     */
1089 
1090   if (flag == SOR_APPLY_LOWER) {
1091     SETERRQ(PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
1092   } else if ((flag & SOR_EISENSTAT) && omega == 1.0 && shift == 0 && fshift == 0.0) {
1093     /* special case for omega = 1.0 saves flops and some integer ops */
1094     PetscScalar *v2;
1095 
1096     v2    = a->a;
1097     /*  x = (E + U)^{-1} b */
1098     for (i=m-1; i>=0; i--) {
1099       n    = a->i[i+1] - diag[i] - 1;
1100       idx  = a->j + diag[i] + 1;
1101       v    = a->a + diag[i] + 1;
1102       sum  = b[i];
1103       SPARSEDENSEMDOT(sum,xs,v,idx,n);
1104       x[i] = sum*idiag[i];
1105 
1106       /*  t = b - (2*E - D)x */
1107       t[i] = b[i] - (v2[diag[i]])*x[i];
1108     }
1109 
1110     /*  t = (E + L)^{-1}t */
1111     diag = a->diag;
1112     for (i=0; i<m; i++) {
1113       n    = diag[i] - a->i[i];
1114       idx  = a->j + a->i[i];
1115       v    = a->a + a->i[i];
1116       sum  = t[i];
1117       SPARSEDENSEMDOT(sum,t,v,idx,n);
1118       t[i]  = sum*idiag[i];
1119 
1120       /*  x = x + t */
1121       x[i] += t[i];
1122     }
1123 
1124     PetscLogFlops(3*m-1 + 2*a->nz);
1125     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1126     if (bb != xx) {ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);}
1127     PetscFunctionReturn(0);
1128   } else if (flag & SOR_EISENSTAT) {
1129     /* Let  A = L + U + D; where L is lower trianglar,
1130     U is upper triangular, E is diagonal; This routine applies
1131 
1132             (L + E)^{-1} A (U + E)^{-1}
1133 
1134     to a vector efficiently using Eisenstat's trick. This is for
1135     the case of SSOR preconditioner, so E is D/omega where omega
1136     is the relaxation factor.
1137     */
1138     scale = (2.0/omega) - 1.0;
1139 
1140     /*  x = (E + U)^{-1} b */
1141     for (i=m-1; i>=0; i--) {
1142       d    = fshift + a->a[diag[i] + shift];
1143       n    = a->i[i+1] - diag[i] - 1;
1144       idx  = a->j + diag[i] + (!shift);
1145       v    = a->a + diag[i] + (!shift);
1146       sum  = b[i];
1147       SPARSEDENSEMDOT(sum,xs,v,idx,n);
1148       x[i] = omega*(sum/d);
1149     }
1150 
1151     /*  t = b - (2*E - D)x */
1152     v = a->a;
1153     for (i=0; i<m; i++) { t[i] = b[i] - scale*(v[*diag++ + shift])*x[i]; }
1154 
1155     /*  t = (E + L)^{-1}t */
1156     ts = t + shift; /* shifted by one for index start of a or a->j*/
1157     diag = a->diag;
1158     for (i=0; i<m; i++) {
1159       d    = fshift + a->a[diag[i]+shift];
1160       n    = diag[i] - a->i[i];
1161       idx  = a->j + a->i[i] + shift;
1162       v    = a->a + a->i[i] + shift;
1163       sum  = t[i];
1164       SPARSEDENSEMDOT(sum,ts,v,idx,n);
1165       t[i] = omega*(sum/d);
1166       /*  x = x + t */
1167       x[i] += t[i];
1168     }
1169 
1170     PetscLogFlops(6*m-1 + 2*a->nz);
1171     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1172     if (bb != xx) {ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);}
1173     PetscFunctionReturn(0);
1174   }
1175   if (flag & SOR_ZERO_INITIAL_GUESS) {
1176     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1177 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1178       fortranrelaxaijforwardzero_(&m,&omega,x,a->i,a->j,diag,a->a,b);
1179 #else
1180       for (i=0; i<m; i++) {
1181         d    = fshift + a->a[diag[i]+shift];
1182         n    = diag[i] - a->i[i];
1183 	PetscLogFlops(2*n-1);
1184         idx  = a->j + a->i[i] + shift;
1185         v    = a->a + a->i[i] + shift;
1186         sum  = b[i];
1187         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1188         x[i] = omega*(sum/d);
1189       }
1190 #endif
1191       xb = x;
1192     } else xb = b;
1193     if ((flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) &&
1194         (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP)) {
1195       for (i=0; i<m; i++) {
1196         x[i] *= a->a[diag[i]+shift];
1197       }
1198       PetscLogFlops(m);
1199     }
1200     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1201 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1202       fortranrelaxaijbackwardzero_(&m,&omega,x,a->i,a->j,diag,a->a,xb);
1203 #else
1204       for (i=m-1; i>=0; i--) {
1205         d    = fshift + a->a[diag[i] + shift];
1206         n    = a->i[i+1] - diag[i] - 1;
1207 	PetscLogFlops(2*n-1);
1208         idx  = a->j + diag[i] + (!shift);
1209         v    = a->a + diag[i] + (!shift);
1210         sum  = xb[i];
1211         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1212         x[i] = omega*(sum/d);
1213       }
1214 #endif
1215     }
1216     its--;
1217   }
1218   while (its--) {
1219     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
1220 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1221       fortranrelaxaijforward_(&m,&omega,x,a->i,a->j,diag,a->a,b);
1222 #else
1223       for (i=0; i<m; i++) {
1224         d    = fshift + a->a[diag[i]+shift];
1225         n    = a->i[i+1] - a->i[i];
1226 	PetscLogFlops(2*n-1);
1227         idx  = a->j + a->i[i] + shift;
1228         v    = a->a + a->i[i] + shift;
1229         sum  = b[i];
1230         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1231         x[i] = (1. - omega)*x[i] + omega*(sum + a->a[diag[i]+shift]*x[i])/d;
1232       }
1233 #endif
1234     }
1235     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
1236 #if defined(PETSC_USE_FORTRAN_KERNEL_RELAXAIJ)
1237       fortranrelaxaijbackward_(&m,&omega,x,a->i,a->j,diag,a->a,b);
1238 #else
1239       for (i=m-1; i>=0; i--) {
1240         d    = fshift + a->a[diag[i] + shift];
1241         n    = a->i[i+1] - a->i[i];
1242 	PetscLogFlops(2*n-1);
1243         idx  = a->j + a->i[i] + shift;
1244         v    = a->a + a->i[i] + shift;
1245         sum  = b[i];
1246         SPARSEDENSEMDOT(sum,xs,v,idx,n);
1247         x[i] = (1. - omega)*x[i] + omega*(sum + a->a[diag[i]+shift]*x[i])/d;
1248       }
1249 #endif
1250     }
1251   }
1252   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1253   if (bb != xx) {ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);}
1254   PetscFunctionReturn(0);
1255 }
1256 
1257 #undef __FUNCT__
1258 #define __FUNCT__ "MatGetInfo_SeqAIJ"
1259 int MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
1260 {
1261   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1262 
1263   PetscFunctionBegin;
1264   info->rows_global    = (double)A->m;
1265   info->columns_global = (double)A->n;
1266   info->rows_local     = (double)A->m;
1267   info->columns_local  = (double)A->n;
1268   info->block_size     = 1.0;
1269   info->nz_allocated   = (double)a->maxnz;
1270   info->nz_used        = (double)a->nz;
1271   info->nz_unneeded    = (double)(a->maxnz - a->nz);
1272   info->assemblies     = (double)A->num_ass;
1273   info->mallocs        = (double)a->reallocs;
1274   info->memory         = A->mem;
1275   if (A->factor) {
1276     info->fill_ratio_given  = A->info.fill_ratio_given;
1277     info->fill_ratio_needed = A->info.fill_ratio_needed;
1278     info->factor_mallocs    = A->info.factor_mallocs;
1279   } else {
1280     info->fill_ratio_given  = 0;
1281     info->fill_ratio_needed = 0;
1282     info->factor_mallocs    = 0;
1283   }
1284   PetscFunctionReturn(0);
1285 }
1286 
1287 EXTERN int MatLUFactorSymbolic_SeqAIJ(Mat,IS,IS,MatLUInfo*,Mat*);
1288 EXTERN int MatLUFactorNumeric_SeqAIJ(Mat,Mat*);
1289 EXTERN int MatLUFactor_SeqAIJ(Mat,IS,IS,MatLUInfo*);
1290 EXTERN int MatSolve_SeqAIJ(Mat,Vec,Vec);
1291 EXTERN int MatSolveAdd_SeqAIJ(Mat,Vec,Vec,Vec);
1292 EXTERN int MatSolveTranspose_SeqAIJ(Mat,Vec,Vec);
1293 EXTERN int MatSolveTransposeAdd_SeqAIJ(Mat,Vec,Vec,Vec);
1294 
1295 #undef __FUNCT__
1296 #define __FUNCT__ "MatZeroRows_SeqAIJ"
1297 int MatZeroRows_SeqAIJ(Mat A,IS is,PetscScalar *diag)
1298 {
1299   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1300   int         i,ierr,N,*rows,m = A->m - 1,shift = a->indexshift;
1301 
1302   PetscFunctionBegin;
1303   ierr = ISGetLocalSize(is,&N);CHKERRQ(ierr);
1304   ierr = ISGetIndices(is,&rows);CHKERRQ(ierr);
1305   if (a->keepzeroedrows) {
1306     for (i=0; i<N; i++) {
1307       if (rows[i] < 0 || rows[i] > m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"row out of range");
1308       ierr = PetscMemzero(&a->a[a->i[rows[i]]+shift],a->ilen[rows[i]]*sizeof(PetscScalar));CHKERRQ(ierr);
1309     }
1310     if (diag) {
1311       ierr = MatMissingDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1312       ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1313       for (i=0; i<N; i++) {
1314         a->a[a->diag[rows[i]]] = *diag;
1315       }
1316     }
1317   } else {
1318     if (diag) {
1319       for (i=0; i<N; i++) {
1320         if (rows[i] < 0 || rows[i] > m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"row out of range");
1321         if (a->ilen[rows[i]] > 0) {
1322           a->ilen[rows[i]]          = 1;
1323           a->a[a->i[rows[i]]+shift] = *diag;
1324           a->j[a->i[rows[i]]+shift] = rows[i]+shift;
1325         } else { /* in case row was completely empty */
1326           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],diag,INSERT_VALUES);CHKERRQ(ierr);
1327         }
1328       }
1329     } else {
1330       for (i=0; i<N; i++) {
1331         if (rows[i] < 0 || rows[i] > m) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"row out of range");
1332         a->ilen[rows[i]] = 0;
1333       }
1334     }
1335   }
1336   ierr = ISRestoreIndices(is,&rows);CHKERRQ(ierr);
1337   ierr = MatAssemblyEnd_SeqAIJ(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1338   PetscFunctionReturn(0);
1339 }
1340 
1341 #undef __FUNCT__
1342 #define __FUNCT__ "MatGetRow_SeqAIJ"
1343 int MatGetRow_SeqAIJ(Mat A,int row,int *nz,int **idx,PetscScalar **v)
1344 {
1345   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1346   int        *itmp,i,shift = a->indexshift,ierr;
1347 
1348   PetscFunctionBegin;
1349   if (row < 0 || row >= A->m) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Row %d out of range",row);
1350 
1351   *nz = a->i[row+1] - a->i[row];
1352   if (v) *v = a->a + a->i[row] + shift;
1353   if (idx) {
1354     itmp = a->j + a->i[row] + shift;
1355     if (*nz && shift) {
1356       ierr = PetscMalloc((*nz)*sizeof(int),idx);CHKERRQ(ierr);
1357       for (i=0; i<(*nz); i++) {(*idx)[i] = itmp[i] + shift;}
1358     } else if (*nz) {
1359       *idx = itmp;
1360     }
1361     else *idx = 0;
1362   }
1363   PetscFunctionReturn(0);
1364 }
1365 
1366 #undef __FUNCT__
1367 #define __FUNCT__ "MatRestoreRow_SeqAIJ"
1368 int MatRestoreRow_SeqAIJ(Mat A,int row,int *nz,int **idx,PetscScalar **v)
1369 {
1370   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1371   int ierr;
1372 
1373   PetscFunctionBegin;
1374   if (idx) {if (*idx && a->indexshift) {ierr = PetscFree(*idx);CHKERRQ(ierr);}}
1375   PetscFunctionReturn(0);
1376 }
1377 
1378 #undef __FUNCT__
1379 #define __FUNCT__ "MatNorm_SeqAIJ"
1380 int MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
1381 {
1382   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
1383   PetscScalar  *v = a->a;
1384   PetscReal    sum = 0.0;
1385   int          i,j,shift = a->indexshift,ierr;
1386 
1387   PetscFunctionBegin;
1388   if (type == NORM_FROBENIUS) {
1389     for (i=0; i<a->nz; i++) {
1390 #if defined(PETSC_USE_COMPLEX)
1391       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1392 #else
1393       sum += (*v)*(*v); v++;
1394 #endif
1395     }
1396     *nrm = sqrt(sum);
1397   } else if (type == NORM_1) {
1398     PetscReal *tmp;
1399     int    *jj = a->j;
1400     ierr = PetscMalloc((A->n+1)*sizeof(PetscReal),&tmp);CHKERRQ(ierr);
1401     ierr = PetscMemzero(tmp,A->n*sizeof(PetscReal));CHKERRQ(ierr);
1402     *nrm = 0.0;
1403     for (j=0; j<a->nz; j++) {
1404         tmp[*jj++ + shift] += PetscAbsScalar(*v);  v++;
1405     }
1406     for (j=0; j<A->n; j++) {
1407       if (tmp[j] > *nrm) *nrm = tmp[j];
1408     }
1409     ierr = PetscFree(tmp);CHKERRQ(ierr);
1410   } else if (type == NORM_INFINITY) {
1411     *nrm = 0.0;
1412     for (j=0; j<A->m; j++) {
1413       v = a->a + a->i[j] + shift;
1414       sum = 0.0;
1415       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
1416         sum += PetscAbsScalar(*v); v++;
1417       }
1418       if (sum > *nrm) *nrm = sum;
1419     }
1420   } else {
1421     SETERRQ(PETSC_ERR_SUP,"No support for two norm");
1422   }
1423   PetscFunctionReturn(0);
1424 }
1425 
1426 #undef __FUNCT__
1427 #define __FUNCT__ "MatTranspose_SeqAIJ"
1428 int MatTranspose_SeqAIJ(Mat A,Mat *B)
1429 {
1430   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
1431   Mat          C;
1432   int          i,ierr,*aj = a->j,*ai = a->i,m = A->m,len,*col;
1433   int          shift = a->indexshift;
1434   PetscScalar  *array = a->a;
1435 
1436   PetscFunctionBegin;
1437   if (!B && m != A->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Square matrix only for in-place");
1438   ierr = PetscMalloc((1+A->n)*sizeof(int),&col);CHKERRQ(ierr);
1439   ierr = PetscMemzero(col,(1+A->n)*sizeof(int));CHKERRQ(ierr);
1440   if (shift) {
1441     for (i=0; i<ai[m]-1; i++) aj[i] -= 1;
1442   }
1443   for (i=0; i<ai[m]+shift; i++) col[aj[i]] += 1;
1444   ierr = MatCreateSeqAIJ(A->comm,A->n,m,0,col,&C);CHKERRQ(ierr);
1445   ierr = PetscFree(col);CHKERRQ(ierr);
1446   for (i=0; i<m; i++) {
1447     len    = ai[i+1]-ai[i];
1448     ierr   = MatSetValues(C,len,aj,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
1449     array += len;
1450     aj    += len;
1451   }
1452   if (shift) {
1453     for (i=0; i<ai[m]-1; i++) aj[i] += 1;
1454   }
1455 
1456   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1457   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1458 
1459   if (B) {
1460     *B = C;
1461   } else {
1462     ierr = MatHeaderCopy(A,C);CHKERRQ(ierr);
1463   }
1464   PetscFunctionReturn(0);
1465 }
1466 
1467 #undef __FUNCT__
1468 #define __FUNCT__ "MatDiagonalScale_SeqAIJ"
1469 int MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
1470 {
1471   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
1472   PetscScalar  *l,*r,x,*v;
1473   int          ierr,i,j,m = A->m,n = A->n,M,nz = a->nz,*jj,shift = a->indexshift;
1474 
1475   PetscFunctionBegin;
1476   if (ll) {
1477     /* The local size is used so that VecMPI can be passed to this routine
1478        by MatDiagonalScale_MPIAIJ */
1479     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
1480     if (m != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
1481     ierr = VecGetArray(ll,&l);CHKERRQ(ierr);
1482     v = a->a;
1483     for (i=0; i<m; i++) {
1484       x = l[i];
1485       M = a->i[i+1] - a->i[i];
1486       for (j=0; j<M; j++) { (*v++) *= x;}
1487     }
1488     ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr);
1489     PetscLogFlops(nz);
1490   }
1491   if (rr) {
1492     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
1493     if (n != A->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
1494     ierr = VecGetArray(rr,&r);CHKERRQ(ierr);
1495     v = a->a; jj = a->j;
1496     for (i=0; i<nz; i++) {
1497       (*v++) *= r[*jj++ + shift];
1498     }
1499     ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr);
1500     PetscLogFlops(nz);
1501   }
1502   PetscFunctionReturn(0);
1503 }
1504 
1505 #undef __FUNCT__
1506 #define __FUNCT__ "MatGetSubMatrix_SeqAIJ"
1507 int MatGetSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,int csize,MatReuse scall,Mat *B)
1508 {
1509   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data,*c;
1510   int          *smap,i,k,kstart,kend,ierr,oldcols = A->n,*lens;
1511   int          row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
1512   int          *irow,*icol,nrows,ncols,shift = a->indexshift,*ssmap;
1513   int          *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
1514   PetscScalar  *a_new,*mat_a;
1515   Mat          C;
1516   PetscTruth   stride;
1517 
1518   PetscFunctionBegin;
1519   ierr = ISSorted(isrow,(PetscTruth*)&i);CHKERRQ(ierr);
1520   if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"ISrow is not sorted");
1521   ierr = ISSorted(iscol,(PetscTruth*)&i);CHKERRQ(ierr);
1522   if (!i) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"IScol is not sorted");
1523 
1524   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
1525   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
1526   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
1527 
1528   ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
1529   ierr = ISStride(iscol,&stride);CHKERRQ(ierr);
1530   if (stride && step == 1) {
1531     /* special case of contiguous rows */
1532     ierr   = PetscMalloc((2*nrows+1)*sizeof(int),&lens);CHKERRQ(ierr);
1533     starts = lens + nrows;
1534     /* loop over new rows determining lens and starting points */
1535     for (i=0; i<nrows; i++) {
1536       kstart  = ai[irow[i]]+shift;
1537       kend    = kstart + ailen[irow[i]];
1538       for (k=kstart; k<kend; k++) {
1539         if (aj[k]+shift >= first) {
1540           starts[i] = k;
1541           break;
1542 	}
1543       }
1544       sum = 0;
1545       while (k < kend) {
1546         if (aj[k++]+shift >= first+ncols) break;
1547         sum++;
1548       }
1549       lens[i] = sum;
1550     }
1551     /* create submatrix */
1552     if (scall == MAT_REUSE_MATRIX) {
1553       int n_cols,n_rows;
1554       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
1555       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
1556       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
1557       C = *B;
1558     } else {
1559       ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr);
1560     }
1561     c = (Mat_SeqAIJ*)C->data;
1562 
1563     /* loop over rows inserting into submatrix */
1564     a_new    = c->a;
1565     j_new    = c->j;
1566     i_new    = c->i;
1567     i_new[0] = -shift;
1568     for (i=0; i<nrows; i++) {
1569       ii    = starts[i];
1570       lensi = lens[i];
1571       for (k=0; k<lensi; k++) {
1572         *j_new++ = aj[ii+k] - first;
1573       }
1574       ierr = PetscMemcpy(a_new,a->a + starts[i],lensi*sizeof(PetscScalar));CHKERRQ(ierr);
1575       a_new      += lensi;
1576       i_new[i+1]  = i_new[i] + lensi;
1577       c->ilen[i]  = lensi;
1578     }
1579     ierr = PetscFree(lens);CHKERRQ(ierr);
1580   } else {
1581     ierr  = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
1582     ierr  = PetscMalloc((1+oldcols)*sizeof(int),&smap);CHKERRQ(ierr);
1583     ssmap = smap + shift;
1584     ierr  = PetscMalloc((1+nrows)*sizeof(int),&lens);CHKERRQ(ierr);
1585     ierr  = PetscMemzero(smap,oldcols*sizeof(int));CHKERRQ(ierr);
1586     for (i=0; i<ncols; i++) smap[icol[i]] = i+1;
1587     /* determine lens of each row */
1588     for (i=0; i<nrows; i++) {
1589       kstart  = ai[irow[i]]+shift;
1590       kend    = kstart + a->ilen[irow[i]];
1591       lens[i] = 0;
1592       for (k=kstart; k<kend; k++) {
1593         if (ssmap[aj[k]]) {
1594           lens[i]++;
1595         }
1596       }
1597     }
1598     /* Create and fill new matrix */
1599     if (scall == MAT_REUSE_MATRIX) {
1600       PetscTruth equal;
1601 
1602       c = (Mat_SeqAIJ *)((*B)->data);
1603       if ((*B)->m  != nrows || (*B)->n != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
1604       ierr = PetscMemcmp(c->ilen,lens,(*B)->m*sizeof(int),&equal);CHKERRQ(ierr);
1605       if (!equal) {
1606         SETERRQ(PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
1607       }
1608       ierr = PetscMemzero(c->ilen,(*B)->m*sizeof(int));CHKERRQ(ierr);
1609       C = *B;
1610     } else {
1611       ierr = MatCreateSeqAIJ(A->comm,nrows,ncols,0,lens,&C);CHKERRQ(ierr);
1612     }
1613     c = (Mat_SeqAIJ *)(C->data);
1614     for (i=0; i<nrows; i++) {
1615       row    = irow[i];
1616       kstart = ai[row]+shift;
1617       kend   = kstart + a->ilen[row];
1618       mat_i  = c->i[i]+shift;
1619       mat_j  = c->j + mat_i;
1620       mat_a  = c->a + mat_i;
1621       mat_ilen = c->ilen + i;
1622       for (k=kstart; k<kend; k++) {
1623         if ((tcol=ssmap[a->j[k]])) {
1624           *mat_j++ = tcol - (!shift);
1625           *mat_a++ = a->a[k];
1626           (*mat_ilen)++;
1627 
1628         }
1629       }
1630     }
1631     /* Free work space */
1632     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
1633     ierr = PetscFree(smap);CHKERRQ(ierr);
1634     ierr = PetscFree(lens);CHKERRQ(ierr);
1635   }
1636   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1637   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1638 
1639   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
1640   *B = C;
1641   PetscFunctionReturn(0);
1642 }
1643 
1644 /*
1645 */
1646 #undef __FUNCT__
1647 #define __FUNCT__ "MatILUFactor_SeqAIJ"
1648 int MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,MatILUInfo *info)
1649 {
1650   Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data;
1651   int        ierr;
1652   Mat        outA;
1653   PetscTruth row_identity,col_identity;
1654 
1655   PetscFunctionBegin;
1656   if (info && info->levels != 0) SETERRQ(PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
1657   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
1658   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
1659   if (!row_identity || !col_identity) {
1660     SETERRQ(1,"Row and column permutations must be identity for in-place ILU");
1661   }
1662 
1663   outA          = inA;
1664   inA->factor   = FACTOR_LU;
1665   a->row        = row;
1666   a->col        = col;
1667   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
1668   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
1669 
1670   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
1671   if (a->icol) {ierr = ISDestroy(a->icol);CHKERRQ(ierr);} /* need to remove old one */
1672   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
1673   PetscLogObjectParent(inA,a->icol);
1674 
1675   if (!a->solve_work) { /* this matrix may have been factored before */
1676      ierr = PetscMalloc((inA->m+1)*sizeof(PetscScalar),&a->solve_work);CHKERRQ(ierr);
1677   }
1678 
1679   if (!a->diag) {
1680     ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
1681   }
1682   ierr = MatLUFactorNumeric_SeqAIJ(inA,&outA);CHKERRQ(ierr);
1683   PetscFunctionReturn(0);
1684 }
1685 
1686 #include "petscblaslapack.h"
1687 #undef __FUNCT__
1688 #define __FUNCT__ "MatScale_SeqAIJ"
1689 int MatScale_SeqAIJ(PetscScalar *alpha,Mat inA)
1690 {
1691   Mat_SeqAIJ *a = (Mat_SeqAIJ*)inA->data;
1692   int        one = 1;
1693 
1694   PetscFunctionBegin;
1695   BLscal_(&a->nz,alpha,a->a,&one);
1696   PetscLogFlops(a->nz);
1697   PetscFunctionReturn(0);
1698 }
1699 
1700 #undef __FUNCT__
1701 #define __FUNCT__ "MatGetSubMatrices_SeqAIJ"
1702 int MatGetSubMatrices_SeqAIJ(Mat A,int n,IS *irow,IS *icol,MatReuse scall,Mat **B)
1703 {
1704   int ierr,i;
1705 
1706   PetscFunctionBegin;
1707   if (scall == MAT_INITIAL_MATRIX) {
1708     ierr = PetscMalloc((n+1)*sizeof(Mat),B);CHKERRQ(ierr);
1709   }
1710 
1711   for (i=0; i<n; i++) {
1712     ierr = MatGetSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
1713   }
1714   PetscFunctionReturn(0);
1715 }
1716 
1717 #undef __FUNCT__
1718 #define __FUNCT__ "MatGetBlockSize_SeqAIJ"
1719 int MatGetBlockSize_SeqAIJ(Mat A,int *bs)
1720 {
1721   PetscFunctionBegin;
1722   *bs = 1;
1723   PetscFunctionReturn(0);
1724 }
1725 
1726 #undef __FUNCT__
1727 #define __FUNCT__ "MatIncreaseOverlap_SeqAIJ"
1728 int MatIncreaseOverlap_SeqAIJ(Mat A,int is_max,IS *is,int ov)
1729 {
1730   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1731   int        shift,row,i,j,k,l,m,n,*idx,ierr,*nidx,isz,val;
1732   int        start,end,*ai,*aj;
1733   PetscBT    table;
1734 
1735   PetscFunctionBegin;
1736   shift = a->indexshift;
1737   m     = A->m;
1738   ai    = a->i;
1739   aj    = a->j+shift;
1740 
1741   if (ov < 0)  SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"illegal overlap value used");
1742 
1743   ierr = PetscMalloc((m+1)*sizeof(int),&nidx);CHKERRQ(ierr);
1744   ierr = PetscBTCreate(m,table);CHKERRQ(ierr);
1745 
1746   for (i=0; i<is_max; i++) {
1747     /* Initialize the two local arrays */
1748     isz  = 0;
1749     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
1750 
1751     /* Extract the indices, assume there can be duplicate entries */
1752     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
1753     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
1754 
1755     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
1756     for (j=0; j<n ; ++j){
1757       if(!PetscBTLookupSet(table,idx[j])) { nidx[isz++] = idx[j];}
1758     }
1759     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
1760     ierr = ISDestroy(is[i]);CHKERRQ(ierr);
1761 
1762     k = 0;
1763     for (j=0; j<ov; j++){ /* for each overlap */
1764       n = isz;
1765       for (; k<n ; k++){ /* do only those rows in nidx[k], which are not done yet */
1766         row   = nidx[k];
1767         start = ai[row];
1768         end   = ai[row+1];
1769         for (l = start; l<end ; l++){
1770           val = aj[l] + shift;
1771           if (!PetscBTLookupSet(table,val)) {nidx[isz++] = val;}
1772         }
1773       }
1774     }
1775     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,(is+i));CHKERRQ(ierr);
1776   }
1777   ierr = PetscBTDestroy(table);CHKERRQ(ierr);
1778   ierr = PetscFree(nidx);CHKERRQ(ierr);
1779   PetscFunctionReturn(0);
1780 }
1781 
1782 /* -------------------------------------------------------------- */
1783 #undef __FUNCT__
1784 #define __FUNCT__ "MatPermute_SeqAIJ"
1785 int MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
1786 {
1787   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
1788   PetscScalar  *vwork;
1789   int          i,ierr,nz,m = A->m,n = A->n,*cwork;
1790   int          *row,*col,*cnew,j,*lens;
1791   IS           icolp,irowp;
1792 
1793   PetscFunctionBegin;
1794   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
1795   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
1796   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
1797   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
1798 
1799   /* determine lengths of permuted rows */
1800   ierr = PetscMalloc((m+1)*sizeof(int),&lens);CHKERRQ(ierr);
1801   for (i=0; i<m; i++) {
1802     lens[row[i]] = a->i[i+1] - a->i[i];
1803   }
1804   ierr = MatCreateSeqAIJ(A->comm,m,n,0,lens,B);CHKERRQ(ierr);
1805   ierr = PetscFree(lens);CHKERRQ(ierr);
1806 
1807   ierr = PetscMalloc(n*sizeof(int),&cnew);CHKERRQ(ierr);
1808   for (i=0; i<m; i++) {
1809     ierr = MatGetRow(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
1810     for (j=0; j<nz; j++) { cnew[j] = col[cwork[j]];}
1811     ierr = MatSetValues(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
1812     ierr = MatRestoreRow(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
1813   }
1814   ierr = PetscFree(cnew);CHKERRQ(ierr);
1815   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1816   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1817   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
1818   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
1819   ierr = ISDestroy(irowp);CHKERRQ(ierr);
1820   ierr = ISDestroy(icolp);CHKERRQ(ierr);
1821   PetscFunctionReturn(0);
1822 }
1823 
1824 #undef __FUNCT__
1825 #define __FUNCT__ "MatPrintHelp_SeqAIJ"
1826 int MatPrintHelp_SeqAIJ(Mat A)
1827 {
1828   static PetscTruth called = PETSC_FALSE;
1829   MPI_Comm          comm = A->comm;
1830   int               ierr;
1831 
1832   PetscFunctionBegin;
1833   if (called) {PetscFunctionReturn(0);} else called = PETSC_TRUE;
1834   ierr = (*PetscHelpPrintf)(comm," Options for MATSEQAIJ and MATMPIAIJ matrix formats (the defaults):\n");CHKERRQ(ierr);
1835   ierr = (*PetscHelpPrintf)(comm,"  -mat_lu_pivotthreshold <threshold>: Set pivoting threshold\n");CHKERRQ(ierr);
1836   ierr = (*PetscHelpPrintf)(comm,"  -mat_aij_oneindex: internal indices begin at 1 instead of the default 0.\n");CHKERRQ(ierr);
1837   ierr = (*PetscHelpPrintf)(comm,"  -mat_aij_no_inode: Do not use inodes\n");CHKERRQ(ierr);
1838   ierr = (*PetscHelpPrintf)(comm,"  -mat_aij_inode_limit <limit>: Set inode limit (max limit=5)\n");CHKERRQ(ierr);
1839 #if defined(PETSC_HAVE_ESSL)
1840   ierr = (*PetscHelpPrintf)(comm,"  -mat_aij_essl: Use IBM sparse LU factorization and solve.\n");CHKERRQ(ierr);
1841 #endif
1842 #if defined(PETSC_HAVE_LUSOL)
1843   ierr = (*PetscHelpPrintf)(comm,"  -mat_aij_lusol: Use the Stanford LUSOL sparse factorization and solve.\n");CHKERRQ(ierr);
1844 #endif
1845 #if defined(PETSC_HAVE_MATLAB_ENGINE) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
1846   ierr = (*PetscHelpPrintf)(comm,"  -mat_aij_matlab: Use Matlab engine sparse LU factorization and solve.\n");CHKERRQ(ierr);
1847 #endif
1848   PetscFunctionReturn(0);
1849 }
1850 EXTERN int MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg);
1851 EXTERN int MatFDColoringCreate_SeqAIJ(Mat,ISColoring,MatFDColoring);
1852 EXTERN int MatILUDTFactor_SeqAIJ(Mat,MatILUInfo*,IS,IS,Mat*);
1853 #undef __FUNCT__
1854 #define __FUNCT__ "MatCopy_SeqAIJ"
1855 int MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
1856 {
1857   int        ierr;
1858   PetscTruth flg;
1859 
1860   PetscFunctionBegin;
1861   ierr = PetscTypeCompare((PetscObject)B,MATSEQAIJ,&flg);CHKERRQ(ierr);
1862   if (str == SAME_NONZERO_PATTERN && flg) {
1863     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1864     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
1865 
1866     if (a->i[A->m]+a->indexshift != b->i[B->m]+a->indexshift) {
1867       SETERRQ(1,"Number of nonzeros in two matrices are different");
1868     }
1869     ierr = PetscMemcpy(b->a,a->a,(a->i[A->m]+a->indexshift)*sizeof(PetscScalar));CHKERRQ(ierr);
1870   } else {
1871     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
1872   }
1873   PetscFunctionReturn(0);
1874 }
1875 
1876 #undef __FUNCT__
1877 #define __FUNCT__ "MatSetUpPreallocation_SeqAIJ"
1878 int MatSetUpPreallocation_SeqAIJ(Mat A)
1879 {
1880   int        ierr;
1881 
1882   PetscFunctionBegin;
1883   ierr =  MatSeqAIJSetPreallocation(A,PETSC_DEFAULT,0);CHKERRQ(ierr);
1884   PetscFunctionReturn(0);
1885 }
1886 
1887 #undef __FUNCT__
1888 #define __FUNCT__ "MatGetArray_SeqAIJ"
1889 int MatGetArray_SeqAIJ(Mat A,PetscScalar **array)
1890 {
1891   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
1892   PetscFunctionBegin;
1893   *array = a->a;
1894   PetscFunctionReturn(0);
1895 }
1896 
1897 #undef __FUNCT__
1898 #define __FUNCT__ "MatRestoreArray_SeqAIJ"
1899 int MatRestoreArray_SeqAIJ(Mat A,PetscScalar **array)
1900 {
1901   PetscFunctionBegin;
1902   PetscFunctionReturn(0);
1903 }
1904 
1905 #undef __FUNCT__
1906 #define __FUNCT__ "MatFDColoringApply_SeqAIJ"
1907 int MatFDColoringApply_SeqAIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
1908 {
1909   int           (*f)(void *,Vec,Vec,void*) = (int (*)(void *,Vec,Vec,void *))coloring->f;
1910   int           k,ierr,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
1911   PetscScalar   dx,mone = -1.0,*y,*xx,*w3_array;
1912   PetscScalar   *vscale_array;
1913   PetscReal     epsilon = coloring->error_rel,umin = coloring->umin;
1914   Vec           w1,w2,w3;
1915   void          *fctx = coloring->fctx;
1916   PetscTruth    flg;
1917 
1918   PetscFunctionBegin;
1919   if (!coloring->w1) {
1920     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
1921     PetscLogObjectParent(coloring,coloring->w1);
1922     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
1923     PetscLogObjectParent(coloring,coloring->w2);
1924     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
1925     PetscLogObjectParent(coloring,coloring->w3);
1926   }
1927   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
1928 
1929   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
1930   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
1931   if (flg) {
1932     PetscLogInfo(coloring,"MatFDColoringApply_SeqAIJ: Not calling MatZeroEntries()\n");
1933   } else {
1934     ierr = MatZeroEntries(J);CHKERRQ(ierr);
1935   }
1936 
1937   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
1938   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
1939 
1940   /*
1941        This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets
1942      coloring->F for the coarser grids from the finest
1943   */
1944   if (coloring->F) {
1945     ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr);
1946     ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr);
1947     if (m1 != m2) {
1948       coloring->F = 0;
1949     }
1950   }
1951 
1952   if (coloring->F) {
1953     w1          = coloring->F;
1954     coloring->F = 0;
1955   } else {
1956     ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr);
1957   }
1958 
1959   /*
1960       Compute all the scale factors and share with other processors
1961   */
1962   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
1963   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
1964   for (k=0; k<coloring->ncolors; k++) {
1965     /*
1966        Loop over each column associated with color adding the
1967        perturbation to the vector w3.
1968     */
1969     for (l=0; l<coloring->ncolumns[k]; l++) {
1970       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
1971       dx  = xx[col];
1972       if (dx == 0.0) dx = 1.0;
1973 #if !defined(PETSC_USE_COMPLEX)
1974       if (dx < umin && dx >= 0.0)      dx = umin;
1975       else if (dx < 0.0 && dx > -umin) dx = -umin;
1976 #else
1977       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
1978       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
1979 #endif
1980       dx                *= epsilon;
1981       vscale_array[col] = 1.0/dx;
1982     }
1983   }
1984   vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
1985   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1986   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1987 
1988   /*  ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
1989       ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/
1990 
1991   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
1992   else                        vscaleforrow = coloring->columnsforrow;
1993 
1994   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
1995   /*
1996       Loop over each color
1997   */
1998   for (k=0; k<coloring->ncolors; k++) {
1999     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
2000     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
2001     /*
2002        Loop over each column associated with color adding the
2003        perturbation to the vector w3.
2004     */
2005     for (l=0; l<coloring->ncolumns[k]; l++) {
2006       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
2007       dx  = xx[col];
2008       if (dx == 0.0) dx = 1.0;
2009 #if !defined(PETSC_USE_COMPLEX)
2010       if (dx < umin && dx >= 0.0)      dx = umin;
2011       else if (dx < 0.0 && dx > -umin) dx = -umin;
2012 #else
2013       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
2014       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
2015 #endif
2016       dx            *= epsilon;
2017       if (!PetscAbsScalar(dx)) SETERRQ(1,"Computed 0 differencing parameter");
2018       w3_array[col] += dx;
2019     }
2020     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
2021 
2022     /*
2023        Evaluate function at x1 + dx (here dx is a vector of perturbations)
2024     */
2025 
2026     ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
2027     ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
2028 
2029     /*
2030        Loop over rows of vector, putting results into Jacobian matrix
2031     */
2032     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
2033     for (l=0; l<coloring->nrows[k]; l++) {
2034       row    = coloring->rows[k][l];
2035       col    = coloring->columnsforrow[k][l];
2036       y[row] *= vscale_array[vscaleforrow[k][l]];
2037       srow   = row + start;
2038       ierr   = MatSetValues_SeqAIJ(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
2039     }
2040     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
2041   }
2042   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
2043   xx = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
2044   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2045   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2046   PetscFunctionReturn(0);
2047 }
2048 
2049 #include "petscblaslapack.h"
2050 
2051 #undef __FUNCT__
2052 #define __FUNCT__ "MatAXPY_SeqAIJ"
2053 int MatAXPY_SeqAIJ(PetscScalar *a,Mat X,Mat Y,MatStructure str)
2054 {
2055   int        ierr,one=1;
2056   Mat_SeqAIJ *x  = (Mat_SeqAIJ *)X->data,*y = (Mat_SeqAIJ *)Y->data;
2057 
2058   PetscFunctionBegin;
2059   if (str == SAME_NONZERO_PATTERN) {
2060     BLaxpy_(&x->nz,a,x->a,&one,y->a,&one);
2061   } else {
2062     ierr = MatAXPY_Basic(a,X,Y,str);CHKERRQ(ierr);
2063   }
2064   PetscFunctionReturn(0);
2065 }
2066 
2067 
2068 /* -------------------------------------------------------------------*/
2069 static struct _MatOps MatOps_Values = {MatSetValues_SeqAIJ,
2070        MatGetRow_SeqAIJ,
2071        MatRestoreRow_SeqAIJ,
2072        MatMult_SeqAIJ,
2073        MatMultAdd_SeqAIJ,
2074        MatMultTranspose_SeqAIJ,
2075        MatMultTransposeAdd_SeqAIJ,
2076        MatSolve_SeqAIJ,
2077        MatSolveAdd_SeqAIJ,
2078        MatSolveTranspose_SeqAIJ,
2079        MatSolveTransposeAdd_SeqAIJ,
2080        MatLUFactor_SeqAIJ,
2081        0,
2082        MatRelax_SeqAIJ,
2083        MatTranspose_SeqAIJ,
2084        MatGetInfo_SeqAIJ,
2085        MatEqual_SeqAIJ,
2086        MatGetDiagonal_SeqAIJ,
2087        MatDiagonalScale_SeqAIJ,
2088        MatNorm_SeqAIJ,
2089        0,
2090        MatAssemblyEnd_SeqAIJ,
2091        MatCompress_SeqAIJ,
2092        MatSetOption_SeqAIJ,
2093        MatZeroEntries_SeqAIJ,
2094        MatZeroRows_SeqAIJ,
2095        MatLUFactorSymbolic_SeqAIJ,
2096        MatLUFactorNumeric_SeqAIJ,
2097        0,
2098        0,
2099        MatSetUpPreallocation_SeqAIJ,
2100        MatILUFactorSymbolic_SeqAIJ,
2101        0,
2102        MatGetArray_SeqAIJ,
2103        MatRestoreArray_SeqAIJ,
2104        MatDuplicate_SeqAIJ,
2105        0,
2106        0,
2107        MatILUFactor_SeqAIJ,
2108        0,
2109        MatAXPY_SeqAIJ,
2110        MatGetSubMatrices_SeqAIJ,
2111        MatIncreaseOverlap_SeqAIJ,
2112        MatGetValues_SeqAIJ,
2113        MatCopy_SeqAIJ,
2114        MatPrintHelp_SeqAIJ,
2115        MatScale_SeqAIJ,
2116        0,
2117        0,
2118        MatILUDTFactor_SeqAIJ,
2119        MatGetBlockSize_SeqAIJ,
2120        MatGetRowIJ_SeqAIJ,
2121        MatRestoreRowIJ_SeqAIJ,
2122        MatGetColumnIJ_SeqAIJ,
2123        MatRestoreColumnIJ_SeqAIJ,
2124        MatFDColoringCreate_SeqAIJ,
2125        0,
2126        0,
2127        MatPermute_SeqAIJ,
2128        0,
2129        0,
2130        MatDestroy_SeqAIJ,
2131        MatView_SeqAIJ,
2132        MatGetPetscMaps_Petsc,
2133        0,
2134        0,
2135        0,
2136        0,
2137        0,
2138        0,
2139        0,
2140        0,
2141        MatSetColoring_SeqAIJ,
2142        MatSetValuesAdic_SeqAIJ,
2143        MatSetValuesAdifor_SeqAIJ,
2144        MatFDColoringApply_SeqAIJ};
2145 
2146 EXTERN int MatUseSuperLU_SeqAIJ(Mat);
2147 EXTERN int MatUseEssl_SeqAIJ(Mat);
2148 EXTERN int MatUseLUSOL_SeqAIJ(Mat);
2149 EXTERN int MatUseMatlab_SeqAIJ(Mat);
2150 EXTERN int MatUseDXML_SeqAIJ(Mat);
2151 
2152 EXTERN_C_BEGIN
2153 #undef __FUNCT__
2154 #define __FUNCT__ "MatSeqAIJSetColumnIndices_SeqAIJ"
2155 
2156 int MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,int *indices)
2157 {
2158   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2159   int        i,nz,n;
2160 
2161   PetscFunctionBegin;
2162 
2163   nz = aij->maxnz;
2164   n  = mat->n;
2165   for (i=0; i<nz; i++) {
2166     aij->j[i] = indices[i];
2167   }
2168   aij->nz = nz;
2169   for (i=0; i<n; i++) {
2170     aij->ilen[i] = aij->imax[i];
2171   }
2172 
2173   PetscFunctionReturn(0);
2174 }
2175 EXTERN_C_END
2176 
2177 #undef __FUNCT__
2178 #define __FUNCT__ "MatSeqAIJSetColumnIndices"
2179 /*@
2180     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
2181        in the matrix.
2182 
2183   Input Parameters:
2184 +  mat - the SeqAIJ matrix
2185 -  indices - the column indices
2186 
2187   Level: advanced
2188 
2189   Notes:
2190     This can be called if you have precomputed the nonzero structure of the
2191   matrix and want to provide it to the matrix object to improve the performance
2192   of the MatSetValues() operation.
2193 
2194     You MUST have set the correct numbers of nonzeros per row in the call to
2195   MatCreateSeqAIJ().
2196 
2197     MUST be called before any calls to MatSetValues();
2198 
2199     The indices should start with zero, not one.
2200 
2201 @*/
2202 int MatSeqAIJSetColumnIndices(Mat mat,int *indices)
2203 {
2204   int ierr,(*f)(Mat,int *);
2205 
2206   PetscFunctionBegin;
2207   PetscValidHeaderSpecific(mat,MAT_COOKIE);
2208   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatSeqAIJSetColumnIndices_C",(void (**)(void))&f);CHKERRQ(ierr);
2209   if (f) {
2210     ierr = (*f)(mat,indices);CHKERRQ(ierr);
2211   } else {
2212     SETERRQ(1,"Wrong type of matrix to set column indices");
2213   }
2214   PetscFunctionReturn(0);
2215 }
2216 
2217 /* ----------------------------------------------------------------------------------------*/
2218 
2219 EXTERN_C_BEGIN
2220 #undef __FUNCT__
2221 #define __FUNCT__ "MatStoreValues_SeqAIJ"
2222 int MatStoreValues_SeqAIJ(Mat mat)
2223 {
2224   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2225   int        nz = aij->i[mat->m]+aij->indexshift,ierr;
2226 
2227   PetscFunctionBegin;
2228   if (aij->nonew != 1) {
2229     SETERRQ(1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
2230   }
2231 
2232   /* allocate space for values if not already there */
2233   if (!aij->saved_values) {
2234     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&aij->saved_values);CHKERRQ(ierr);
2235   }
2236 
2237   /* copy values over */
2238   ierr = PetscMemcpy(aij->saved_values,aij->a,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2239   PetscFunctionReturn(0);
2240 }
2241 EXTERN_C_END
2242 
2243 #undef __FUNCT__
2244 #define __FUNCT__ "MatStoreValues"
2245 /*@
2246     MatStoreValues - Stashes a copy of the matrix values; this allows, for
2247        example, reuse of the linear part of a Jacobian, while recomputing the
2248        nonlinear portion.
2249 
2250    Collect on Mat
2251 
2252   Input Parameters:
2253 .  mat - the matrix (currently on AIJ matrices support this option)
2254 
2255   Level: advanced
2256 
2257   Common Usage, with SNESSolve():
2258 $    Create Jacobian matrix
2259 $    Set linear terms into matrix
2260 $    Apply boundary conditions to matrix, at this time matrix must have
2261 $      final nonzero structure (i.e. setting the nonlinear terms and applying
2262 $      boundary conditions again will not change the nonzero structure
2263 $    ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS);
2264 $    ierr = MatStoreValues(mat);
2265 $    Call SNESSetJacobian() with matrix
2266 $    In your Jacobian routine
2267 $      ierr = MatRetrieveValues(mat);
2268 $      Set nonlinear terms in matrix
2269 
2270   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
2271 $    // build linear portion of Jacobian
2272 $    ierr = MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS);
2273 $    ierr = MatStoreValues(mat);
2274 $    loop over nonlinear iterations
2275 $       ierr = MatRetrieveValues(mat);
2276 $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
2277 $       // call MatAssemblyBegin/End() on matrix
2278 $       Solve linear system with Jacobian
2279 $    endloop
2280 
2281   Notes:
2282     Matrix must already be assemblied before calling this routine
2283     Must set the matrix option MatSetOption(mat,MAT_NO_NEW_NONZERO_LOCATIONS); before
2284     calling this routine.
2285 
2286 .seealso: MatRetrieveValues()
2287 
2288 @*/
2289 int MatStoreValues(Mat mat)
2290 {
2291   int ierr,(*f)(Mat);
2292 
2293   PetscFunctionBegin;
2294   PetscValidHeaderSpecific(mat,MAT_COOKIE);
2295   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2296   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2297 
2298   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatStoreValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2299   if (f) {
2300     ierr = (*f)(mat);CHKERRQ(ierr);
2301   } else {
2302     SETERRQ(1,"Wrong type of matrix to store values");
2303   }
2304   PetscFunctionReturn(0);
2305 }
2306 
2307 EXTERN_C_BEGIN
2308 #undef __FUNCT__
2309 #define __FUNCT__ "MatRetrieveValues_SeqAIJ"
2310 int MatRetrieveValues_SeqAIJ(Mat mat)
2311 {
2312   Mat_SeqAIJ *aij = (Mat_SeqAIJ *)mat->data;
2313   int        nz = aij->i[mat->m]+aij->indexshift,ierr;
2314 
2315   PetscFunctionBegin;
2316   if (aij->nonew != 1) {
2317     SETERRQ(1,"Must call MatSetOption(A,MAT_NO_NEW_NONZERO_LOCATIONS);first");
2318   }
2319   if (!aij->saved_values) {
2320     SETERRQ(1,"Must call MatStoreValues(A);first");
2321   }
2322 
2323   /* copy values over */
2324   ierr = PetscMemcpy(aij->a,aij->saved_values,nz*sizeof(PetscScalar));CHKERRQ(ierr);
2325   PetscFunctionReturn(0);
2326 }
2327 EXTERN_C_END
2328 
2329 #undef __FUNCT__
2330 #define __FUNCT__ "MatRetrieveValues"
2331 /*@
2332     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
2333        example, reuse of the linear part of a Jacobian, while recomputing the
2334        nonlinear portion.
2335 
2336    Collect on Mat
2337 
2338   Input Parameters:
2339 .  mat - the matrix (currently on AIJ matrices support this option)
2340 
2341   Level: advanced
2342 
2343 .seealso: MatStoreValues()
2344 
2345 @*/
2346 int MatRetrieveValues(Mat mat)
2347 {
2348   int ierr,(*f)(Mat);
2349 
2350   PetscFunctionBegin;
2351   PetscValidHeaderSpecific(mat,MAT_COOKIE);
2352   if (!mat->assembled) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
2353   if (mat->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2354 
2355   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatRetrieveValues_C",(void (**)(void))&f);CHKERRQ(ierr);
2356   if (f) {
2357     ierr = (*f)(mat);CHKERRQ(ierr);
2358   } else {
2359     SETERRQ(1,"Wrong type of matrix to retrieve values");
2360   }
2361   PetscFunctionReturn(0);
2362 }
2363 
2364 /*
2365    This allows SeqAIJ matrices to be passed to the matlab engine
2366 */
2367 #if defined(PETSC_HAVE_MATLAB_ENGINE) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
2368 #include "engine.h"   /* Matlab include file */
2369 #include "mex.h"      /* Matlab include file */
2370 EXTERN_C_BEGIN
2371 #undef __FUNCT__
2372 #define __FUNCT__ "MatMatlabEnginePut_SeqAIJ"
2373 int MatMatlabEnginePut_SeqAIJ(PetscObject obj,void *engine)
2374 {
2375   int         ierr,i,*ai,*aj;
2376   Mat         B = (Mat)obj;
2377   PetscScalar *array;
2378   mxArray     *mat;
2379   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)B->data;
2380 
2381   PetscFunctionBegin;
2382   mat  = mxCreateSparse(B->n,B->m,aij->nz,mxREAL);
2383   ierr = PetscMemcpy(mxGetPr(mat),aij->a,aij->nz*sizeof(PetscScalar));CHKERRQ(ierr);
2384   /* Matlab stores by column, not row so we pass in the transpose of the matrix */
2385   ierr = PetscMemcpy(mxGetIr(mat),aij->j,aij->nz*sizeof(int));CHKERRQ(ierr);
2386   ierr = PetscMemcpy(mxGetJc(mat),aij->i,(B->m+1)*sizeof(int));CHKERRQ(ierr);
2387 
2388   /* Matlab indices start at 0 for sparse (what a surprise) */
2389   if (aij->indexshift) {
2390     for (i=0; i<B->m+1; i++) {
2391       ai[i]--;
2392     }
2393     for (i=0; i<aij->nz; i++) {
2394       aj[i]--;
2395     }
2396   }
2397   ierr = PetscObjectName(obj);CHKERRQ(ierr);
2398   mxSetName(mat,obj->name);
2399   engPutArray((Engine *)engine,mat);
2400   PetscFunctionReturn(0);
2401 }
2402 EXTERN_C_END
2403 
2404 EXTERN_C_BEGIN
2405 #undef __FUNCT__
2406 #define __FUNCT__ "MatMatlabEngineGet_SeqAIJ"
2407 int MatMatlabEngineGet_SeqAIJ(PetscObject obj,void *engine)
2408 {
2409   int        ierr,ii;
2410   Mat        mat = (Mat)obj;
2411   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
2412   mxArray    *mmat;
2413 
2414   PetscFunctionBegin;
2415   ierr = PetscFree(aij->a);CHKERRQ(ierr);
2416   aij->indexshift = 0;
2417 
2418   mmat = engGetArray((Engine *)engine,obj->name);
2419 
2420   aij->nz           = (mxGetJc(mmat))[mat->m];
2421   ierr              = PetscMalloc(aij->nz*(sizeof(int)+sizeof(PetscScalar))+(mat->m+1)*sizeof(int),&aij->a);CHKERRQ(ierr);
2422   aij->j            = (int*)(aij->a + aij->nz);
2423   aij->i            = aij->j + aij->nz;
2424   aij->singlemalloc = PETSC_TRUE;
2425   aij->freedata     = PETSC_TRUE;
2426 
2427   ierr = PetscMemcpy(aij->a,mxGetPr(mmat),aij->nz*sizeof(PetscScalar));CHKERRQ(ierr);
2428   /* Matlab stores by column, not row so we pass in the transpose of the matrix */
2429   ierr = PetscMemcpy(aij->j,mxGetIr(mmat),aij->nz*sizeof(int));CHKERRQ(ierr);
2430   ierr = PetscMemcpy(aij->i,mxGetJc(mmat),(mat->m+1)*sizeof(int));CHKERRQ(ierr);
2431 
2432   for (ii=0; ii<mat->m; ii++) {
2433     aij->ilen[ii] = aij->imax[ii] = aij->i[ii+1] - aij->i[ii];
2434   }
2435 
2436   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2437   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2438 
2439   PetscFunctionReturn(0);
2440 }
2441 EXTERN_C_END
2442 #endif
2443 
2444 /* --------------------------------------------------------------------------------*/
2445 #define SKIP_ALLOCATION -4
2446 
2447 #undef __FUNCT__
2448 #define __FUNCT__ "MatCreateSeqAIJ"
2449 /*@C
2450    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
2451    (the default parallel PETSc format).  For good matrix assembly performance
2452    the user should preallocate the matrix storage by setting the parameter nz
2453    (or the array nnz).  By setting these parameters accurately, performance
2454    during matrix assembly can be increased by more than a factor of 50.
2455 
2456    Collective on MPI_Comm
2457 
2458    Input Parameters:
2459 +  comm - MPI communicator, set to PETSC_COMM_SELF
2460 .  m - number of rows
2461 .  n - number of columns
2462 .  nz - number of nonzeros per row (same for all rows)
2463 -  nnz - array containing the number of nonzeros in the various rows
2464          (possibly different for each row) or PETSC_NULL
2465 
2466    Output Parameter:
2467 .  A - the matrix
2468 
2469    Notes:
2470    The AIJ format (also called the Yale sparse matrix format or
2471    compressed row storage), is fully compatible with standard Fortran 77
2472    storage.  That is, the stored row and column indices can begin at
2473    either one (as in Fortran) or zero.  See the users' manual for details.
2474 
2475    Specify the preallocated storage with either nz or nnz (not both).
2476    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2477    allocation.  For large problems you MUST preallocate memory or you
2478    will get TERRIBLE performance, see the users' manual chapter on matrices.
2479 
2480    By default, this format uses inodes (identical nodes) when possible, to
2481    improve numerical efficiency of matrix-vector products and solves. We
2482    search for consecutive rows with the same nonzero structure, thereby
2483    reusing matrix information to achieve increased efficiency.
2484 
2485    Options Database Keys:
2486 +  -mat_aij_no_inode  - Do not use inodes
2487 .  -mat_aij_inode_limit <limit> - Sets inode limit (max limit=5)
2488 -  -mat_aij_oneindex - Internally use indexing starting at 1
2489         rather than 0.  Note that when calling MatSetValues(),
2490         the user still MUST index entries starting at 0!
2491 
2492    Level: intermediate
2493 
2494 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
2495 
2496 @*/
2497 int MatCreateSeqAIJ(MPI_Comm comm,int m,int n,int nz,int *nnz,Mat *A)
2498 {
2499   int ierr;
2500 
2501   PetscFunctionBegin;
2502   ierr = MatCreate(comm,m,n,m,n,A);CHKERRQ(ierr);
2503   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
2504   ierr = MatSeqAIJSetPreallocation(*A,nz,nnz);CHKERRQ(ierr);
2505   PetscFunctionReturn(0);
2506 }
2507 
2508 #undef __FUNCT__
2509 #define __FUNCT__ "MatSeqAIJSetPreallocation"
2510 /*@C
2511    MatSeqAIJSetPreallocation - For good matrix assembly performance
2512    the user should preallocate the matrix storage by setting the parameter nz
2513    (or the array nnz).  By setting these parameters accurately, performance
2514    during matrix assembly can be increased by more than a factor of 50.
2515 
2516    Collective on MPI_Comm
2517 
2518    Input Parameters:
2519 +  comm - MPI communicator, set to PETSC_COMM_SELF
2520 .  m - number of rows
2521 .  n - number of columns
2522 .  nz - number of nonzeros per row (same for all rows)
2523 -  nnz - array containing the number of nonzeros in the various rows
2524          (possibly different for each row) or PETSC_NULL
2525 
2526    Output Parameter:
2527 .  A - the matrix
2528 
2529    Notes:
2530    The AIJ format (also called the Yale sparse matrix format or
2531    compressed row storage), is fully compatible with standard Fortran 77
2532    storage.  That is, the stored row and column indices can begin at
2533    either one (as in Fortran) or zero.  See the users' manual for details.
2534 
2535    Specify the preallocated storage with either nz or nnz (not both).
2536    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
2537    allocation.  For large problems you MUST preallocate memory or you
2538    will get TERRIBLE performance, see the users' manual chapter on matrices.
2539 
2540    By default, this format uses inodes (identical nodes) when possible, to
2541    improve numerical efficiency of matrix-vector products and solves. We
2542    search for consecutive rows with the same nonzero structure, thereby
2543    reusing matrix information to achieve increased efficiency.
2544 
2545    Options Database Keys:
2546 +  -mat_aij_no_inode  - Do not use inodes
2547 .  -mat_aij_inode_limit <limit> - Sets inode limit (max limit=5)
2548 -  -mat_aij_oneindex - Internally use indexing starting at 1
2549         rather than 0.  Note that when calling MatSetValues(),
2550         the user still MUST index entries starting at 0!
2551 
2552    Level: intermediate
2553 
2554 .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
2555 
2556 @*/
2557 int MatSeqAIJSetPreallocation(Mat B,int nz,int *nnz)
2558 {
2559   Mat_SeqAIJ *b;
2560   int        i,len,ierr;
2561   PetscTruth flg2,skipallocation = PETSC_FALSE;
2562 
2563   PetscFunctionBegin;
2564   ierr = PetscTypeCompare((PetscObject)B,MATSEQAIJ,&flg2);CHKERRQ(ierr);
2565   if (!flg2) PetscFunctionReturn(0);
2566 
2567   if (nz == SKIP_ALLOCATION) {
2568     skipallocation = PETSC_TRUE;
2569     nz             = 0;
2570   }
2571 
2572   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
2573   if (nz < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %d",nz);
2574   if (nnz) {
2575     for (i=0; i<B->m; i++) {
2576       if (nnz[i] < 0) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %d value %d",i,nnz[i]);
2577       if (nnz[i] > B->n) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %d value %d rowlength %d",i,nnz[i],B->n);
2578     }
2579   }
2580 
2581   B->preallocated = PETSC_TRUE;
2582   b = (Mat_SeqAIJ*)B->data;
2583 
2584   ierr = PetscMalloc((B->m+1)*sizeof(int),&b->imax);CHKERRQ(ierr);
2585   if (!nnz) {
2586     if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
2587     else if (nz <= 0)        nz = 1;
2588     for (i=0; i<B->m; i++) b->imax[i] = nz;
2589     nz = nz*B->m;
2590   } else {
2591     nz = 0;
2592     for (i=0; i<B->m; i++) {b->imax[i] = nnz[i]; nz += nnz[i];}
2593   }
2594 
2595   if (!skipallocation) {
2596     /* allocate the matrix space */
2597     len             = nz*(sizeof(int) + sizeof(PetscScalar)) + (B->m+1)*sizeof(int);
2598     ierr            = PetscMalloc(len,&b->a);CHKERRQ(ierr);
2599     b->j            = (int*)(b->a + nz);
2600     ierr            = PetscMemzero(b->j,nz*sizeof(int));CHKERRQ(ierr);
2601     b->i            = b->j + nz;
2602     b->singlemalloc = PETSC_TRUE;
2603     b->freedata     = PETSC_TRUE;
2604   } else {
2605     b->freedata     = PETSC_FALSE;
2606   }
2607 
2608   b->i[0] = -b->indexshift;
2609   for (i=1; i<B->m+1; i++) {
2610     b->i[i] = b->i[i-1] + b->imax[i-1];
2611   }
2612 
2613   /* b->ilen will count nonzeros in each row so far. */
2614   ierr = PetscMalloc((B->m+1)*sizeof(int),&b->ilen);CHKERRQ(ierr);
2615   PetscLogObjectMemory(B,len+2*(B->m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ));
2616   for (i=0; i<B->m; i++) { b->ilen[i] = 0;}
2617 
2618   b->nz                = 0;
2619   b->maxnz             = nz;
2620   B->info.nz_unneeded  = (double)b->maxnz;
2621   PetscFunctionReturn(0);
2622 }
2623 
2624 EXTERN_C_BEGIN
2625 #undef __FUNCT__
2626 #define __FUNCT__ "MatCreate_SeqAIJ"
2627 int MatCreate_SeqAIJ(Mat B)
2628 {
2629   Mat_SeqAIJ *b;
2630   int        ierr,size;
2631   PetscTruth flg;
2632 
2633   PetscFunctionBegin;
2634   ierr = MPI_Comm_size(B->comm,&size);CHKERRQ(ierr);
2635   if (size > 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
2636 
2637   B->m = B->M = PetscMax(B->m,B->M);
2638   B->n = B->N = PetscMax(B->n,B->N);
2639 
2640   ierr = PetscNew(Mat_SeqAIJ,&b);CHKERRQ(ierr);
2641   B->data             = (void*)b;
2642   ierr = PetscMemzero(b,sizeof(Mat_SeqAIJ));CHKERRQ(ierr);
2643   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
2644   B->factor           = 0;
2645   B->lupivotthreshold = 1.0;
2646   B->mapping          = 0;
2647   ierr = PetscOptionsGetReal(PETSC_NULL,"-mat_lu_pivotthreshold",&B->lupivotthreshold,PETSC_NULL);CHKERRQ(ierr);
2648   ierr = PetscOptionsHasName(PETSC_NULL,"-pc_ilu_preserve_row_sums",&b->ilu_preserve_row_sums);CHKERRQ(ierr);
2649   b->row              = 0;
2650   b->col              = 0;
2651   b->icol             = 0;
2652   b->indexshift       = 0;
2653   b->reallocs         = 0;
2654   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_oneindex",&flg);CHKERRQ(ierr);
2655   if (flg) b->indexshift = -1;
2656 
2657   ierr = PetscMapCreateMPI(B->comm,B->m,B->m,&B->rmap);CHKERRQ(ierr);
2658   ierr = PetscMapCreateMPI(B->comm,B->n,B->n,&B->cmap);CHKERRQ(ierr);
2659 
2660   b->sorted            = PETSC_FALSE;
2661   b->ignorezeroentries = PETSC_FALSE;
2662   b->roworiented       = PETSC_TRUE;
2663   b->nonew             = 0;
2664   b->diag              = 0;
2665   b->solve_work        = 0;
2666   B->spptr             = 0;
2667   b->inode.use         = PETSC_TRUE;
2668   b->inode.node_count  = 0;
2669   b->inode.size        = 0;
2670   b->inode.limit       = 5;
2671   b->inode.max_limit   = 5;
2672   b->saved_values      = 0;
2673   b->idiag             = 0;
2674   b->ssor              = 0;
2675   b->keepzeroedrows    = PETSC_FALSE;
2676 
2677   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
2678 
2679 #if defined(PETSC_HAVE_SUPERLU)
2680   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_superlu",&flg);CHKERRQ(ierr);
2681   if (flg) { ierr = MatUseSuperLU_SeqAIJ(B);CHKERRQ(ierr); }
2682 #endif
2683   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_essl",&flg);CHKERRQ(ierr);
2684   if (flg) { ierr = MatUseEssl_SeqAIJ(B);CHKERRQ(ierr); }
2685   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_lusol",&flg);CHKERRQ(ierr);
2686   if (flg) { ierr = MatUseLUSOL_SeqAIJ(B);CHKERRQ(ierr); }
2687   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_matlab",&flg);CHKERRQ(ierr);
2688   if (flg) {ierr = MatUseMatlab_SeqAIJ(B);CHKERRQ(ierr);}
2689   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_aij_dxml",&flg);CHKERRQ(ierr);
2690   if (flg) {
2691     if (!b->indexshift) SETERRQ(PETSC_ERR_LIB,"need -mat_aij_oneindex with -mat_aij_dxml");
2692     ierr = MatUseDXML_SeqAIJ(B);CHKERRQ(ierr);
2693   }
2694   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqAIJSetColumnIndices_C",
2695                                      "MatSeqAIJSetColumnIndices_SeqAIJ",
2696                                      MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
2697   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C",
2698                                      "MatStoreValues_SeqAIJ",
2699                                      MatStoreValues_SeqAIJ);CHKERRQ(ierr);
2700   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C",
2701                                      "MatRetrieveValues_SeqAIJ",
2702                                      MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
2703 #if defined(PETSC_HAVE_MATLAB_ENGINE) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
2704   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEnginePut_C","MatMatlabEnginePut_SeqAIJ",MatMatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
2705   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"PetscMatlabEngineGet_C","MatMatlabEngineGet_SeqAIJ",MatMatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
2706 #endif
2707   PetscFunctionReturn(0);
2708 }
2709 EXTERN_C_END
2710 
2711 #undef __FUNCT__
2712 #define __FUNCT__ "MatDuplicate_SeqAIJ"
2713 int MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
2714 {
2715   Mat        C;
2716   Mat_SeqAIJ *c,*a = (Mat_SeqAIJ*)A->data;
2717   int        i,len,m = A->m,shift = a->indexshift,ierr;
2718 
2719   PetscFunctionBegin;
2720   *B = 0;
2721   ierr = MatCreate(A->comm,A->m,A->n,A->m,A->n,&C);CHKERRQ(ierr);
2722   ierr = MatSetType(C,MATSEQAIJ);CHKERRQ(ierr);
2723   c    = (Mat_SeqAIJ*)C->data;
2724 
2725   C->factor         = A->factor;
2726   c->row            = 0;
2727   c->col            = 0;
2728   c->icol           = 0;
2729   c->indexshift     = shift;
2730   c->keepzeroedrows = a->keepzeroedrows;
2731   C->assembled      = PETSC_TRUE;
2732 
2733   C->M          = A->m;
2734   C->N          = A->n;
2735 
2736   ierr = PetscMalloc((m+1)*sizeof(int),&c->imax);CHKERRQ(ierr);
2737   ierr = PetscMalloc((m+1)*sizeof(int),&c->ilen);CHKERRQ(ierr);
2738   for (i=0; i<m; i++) {
2739     c->imax[i] = a->imax[i];
2740     c->ilen[i] = a->ilen[i];
2741   }
2742 
2743   /* allocate the matrix space */
2744   c->singlemalloc = PETSC_TRUE;
2745   len   = (m+1)*sizeof(int)+(a->i[m])*(sizeof(PetscScalar)+sizeof(int));
2746   ierr  = PetscMalloc(len,&c->a);CHKERRQ(ierr);
2747   c->j  = (int*)(c->a + a->i[m] + shift);
2748   c->i  = c->j + a->i[m] + shift;
2749   ierr = PetscMemcpy(c->i,a->i,(m+1)*sizeof(int));CHKERRQ(ierr);
2750   if (m > 0) {
2751     ierr = PetscMemcpy(c->j,a->j,(a->i[m]+shift)*sizeof(int));CHKERRQ(ierr);
2752     if (cpvalues == MAT_COPY_VALUES) {
2753       ierr = PetscMemcpy(c->a,a->a,(a->i[m]+shift)*sizeof(PetscScalar));CHKERRQ(ierr);
2754     } else {
2755       ierr = PetscMemzero(c->a,(a->i[m]+shift)*sizeof(PetscScalar));CHKERRQ(ierr);
2756     }
2757   }
2758 
2759   PetscLogObjectMemory(C,len+2*(m+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_SeqAIJ));
2760   c->sorted      = a->sorted;
2761   c->roworiented = a->roworiented;
2762   c->nonew       = a->nonew;
2763   c->ilu_preserve_row_sums = a->ilu_preserve_row_sums;
2764   c->saved_values = 0;
2765   c->idiag        = 0;
2766   c->ssor         = 0;
2767   c->ignorezeroentries = a->ignorezeroentries;
2768   c->freedata     = PETSC_TRUE;
2769 
2770   if (a->diag) {
2771     ierr = PetscMalloc((m+1)*sizeof(int),&c->diag);CHKERRQ(ierr);
2772     PetscLogObjectMemory(C,(m+1)*sizeof(int));
2773     for (i=0; i<m; i++) {
2774       c->diag[i] = a->diag[i];
2775     }
2776   } else c->diag        = 0;
2777   c->inode.use          = a->inode.use;
2778   c->inode.limit        = a->inode.limit;
2779   c->inode.max_limit    = a->inode.max_limit;
2780   if (a->inode.size){
2781     ierr                = PetscMalloc((m+1)*sizeof(int),&c->inode.size);CHKERRQ(ierr);
2782     c->inode.node_count = a->inode.node_count;
2783     ierr                = PetscMemcpy(c->inode.size,a->inode.size,(m+1)*sizeof(int));CHKERRQ(ierr);
2784   } else {
2785     c->inode.size       = 0;
2786     c->inode.node_count = 0;
2787   }
2788   c->nz                 = a->nz;
2789   c->maxnz              = a->maxnz;
2790   c->solve_work         = 0;
2791   C->spptr              = 0;      /* Dangerous -I'm throwing away a->spptr */
2792   C->preallocated       = PETSC_TRUE;
2793 
2794   *B = C;
2795   ierr = PetscFListDuplicate(A->qlist,&C->qlist);CHKERRQ(ierr);
2796   PetscFunctionReturn(0);
2797 }
2798 
2799 EXTERN_C_BEGIN
2800 #undef __FUNCT__
2801 #define __FUNCT__ "MatLoad_SeqAIJ"
2802 int MatLoad_SeqAIJ(PetscViewer viewer,MatType type,Mat *A)
2803 {
2804   Mat_SeqAIJ   *a;
2805   Mat          B;
2806   int          i,nz,ierr,fd,header[4],size,*rowlengths = 0,M,N,shift;
2807   MPI_Comm     comm;
2808 
2809   PetscFunctionBegin;
2810   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
2811   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
2812   if (size > 1) SETERRQ(PETSC_ERR_ARG_SIZ,"view must have one processor");
2813   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
2814   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
2815   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
2816   M = header[1]; N = header[2]; nz = header[3];
2817 
2818   if (nz < 0) {
2819     SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
2820   }
2821 
2822   /* read in row lengths */
2823   ierr = PetscMalloc(M*sizeof(int),&rowlengths);CHKERRQ(ierr);
2824   ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
2825 
2826   /* create our matrix */
2827   ierr = MatCreateSeqAIJ(comm,M,N,0,rowlengths,A);CHKERRQ(ierr);
2828   B = *A;
2829   a = (Mat_SeqAIJ*)B->data;
2830   shift = a->indexshift;
2831 
2832   /* read in column indices and adjust for Fortran indexing*/
2833   ierr = PetscBinaryRead(fd,a->j,nz,PETSC_INT);CHKERRQ(ierr);
2834   if (shift) {
2835     for (i=0; i<nz; i++) {
2836       a->j[i] += 1;
2837     }
2838   }
2839 
2840   /* read in nonzero values */
2841   ierr = PetscBinaryRead(fd,a->a,nz,PETSC_SCALAR);CHKERRQ(ierr);
2842 
2843   /* set matrix "i" values */
2844   a->i[0] = -shift;
2845   for (i=1; i<= M; i++) {
2846     a->i[i]      = a->i[i-1] + rowlengths[i-1];
2847     a->ilen[i-1] = rowlengths[i-1];
2848   }
2849   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
2850 
2851   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2852   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2853   PetscFunctionReturn(0);
2854 }
2855 EXTERN_C_END
2856 
2857 #undef __FUNCT__
2858 #define __FUNCT__ "MatEqual_SeqAIJ"
2859 int MatEqual_SeqAIJ(Mat A,Mat B,PetscTruth* flg)
2860 {
2861   Mat_SeqAIJ *a = (Mat_SeqAIJ *)A->data,*b = (Mat_SeqAIJ *)B->data;
2862   int        ierr;
2863   PetscTruth flag;
2864 
2865   PetscFunctionBegin;
2866   ierr = PetscTypeCompare((PetscObject)B,MATSEQAIJ,&flag);CHKERRQ(ierr);
2867   if (!flag) SETERRQ(PETSC_ERR_ARG_INCOMP,"Matrices must be same type");
2868 
2869   /* If the  matrix dimensions are not equal,or no of nonzeros or shift */
2870   if ((A->m != B->m) || (A->n != B->n) ||(a->nz != b->nz)|| (a->indexshift != b->indexshift)) {
2871     *flg = PETSC_FALSE;
2872     PetscFunctionReturn(0);
2873   }
2874 
2875   /* if the a->i are the same */
2876   ierr = PetscMemcmp(a->i,b->i,(A->m+1)*sizeof(int),flg);CHKERRQ(ierr);
2877   if (*flg == PETSC_FALSE) PetscFunctionReturn(0);
2878 
2879   /* if a->j are the same */
2880   ierr = PetscMemcmp(a->j,b->j,(a->nz)*sizeof(int),flg);CHKERRQ(ierr);
2881   if (*flg == PETSC_FALSE) PetscFunctionReturn(0);
2882 
2883   /* if a->a are the same */
2884   ierr = PetscMemcmp(a->a,b->a,(a->nz)*sizeof(PetscScalar),flg);CHKERRQ(ierr);
2885 
2886   PetscFunctionReturn(0);
2887 
2888 }
2889 
2890 #undef __FUNCT__
2891 #define __FUNCT__ "MatCreateSeqAIJWithArrays"
2892 /*@C
2893      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
2894               provided by the user.
2895 
2896       Coolective on MPI_Comm
2897 
2898    Input Parameters:
2899 +   comm - must be an MPI communicator of size 1
2900 .   m - number of rows
2901 .   n - number of columns
2902 .   i - row indices
2903 .   j - column indices
2904 -   a - matrix values
2905 
2906    Output Parameter:
2907 .   mat - the matrix
2908 
2909    Level: intermediate
2910 
2911    Notes:
2912        The i, j, and a arrays are not copied by this routine, the user must free these arrays
2913     once the matrix is destroyed
2914 
2915        You cannot set new nonzero locations into this matrix, that will generate an error.
2916 
2917        The i and j indices can be either 0- or 1 based
2918 
2919 .seealso: MatCreate(), MatCreateMPIAIJ(), MatCreateSeqAIJ()
2920 
2921 @*/
2922 int MatCreateSeqAIJWithArrays(MPI_Comm comm,int m,int n,int* i,int*j,PetscScalar *a,Mat *mat)
2923 {
2924   int        ierr,ii;
2925   Mat_SeqAIJ *aij;
2926 
2927   PetscFunctionBegin;
2928   ierr = MatCreateSeqAIJ(comm,m,n,SKIP_ALLOCATION,0,mat);CHKERRQ(ierr);
2929   aij  = (Mat_SeqAIJ*)(*mat)->data;
2930 
2931   if (i[0] == 1) {
2932     aij->indexshift = -1;
2933   } else if (i[0]) {
2934     SETERRQ(1,"i (row indices) do not start with 0 or 1");
2935   }
2936   aij->i = i;
2937   aij->j = j;
2938   aij->a = a;
2939   aij->singlemalloc = PETSC_FALSE;
2940   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
2941   aij->freedata     = PETSC_FALSE;
2942 
2943   for (ii=0; ii<m; ii++) {
2944     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
2945 #if defined(PETSC_USE_BOPT_g)
2946     if (i[ii+1] - i[ii] < 0) SETERRQ2(1,"Negative row length in i (row indices) row = %d length = %d",ii,i[ii+1] - i[ii]);
2947 #endif
2948   }
2949 #if defined(PETSC_USE_BOPT_g)
2950   for (ii=0; ii<aij->i[m]; ii++) {
2951     if (j[ii] < -aij->indexshift) SETERRQ2(1,"Negative column index at location = %d index = %d",ii,j[ii]);
2952     if (j[ii] > n - 1 -aij->indexshift) SETERRQ2(1,"Column index to large at location = %d index = %d",ii,j[ii]);
2953   }
2954 #endif
2955 
2956   /* changes indices to start at 0 */
2957   if (i[0]) {
2958     aij->indexshift = 0;
2959     for (ii=0; ii<m; ii++) {
2960       i[ii]--;
2961     }
2962     for (ii=0; ii<i[m]; ii++) {
2963       j[ii]--;
2964     }
2965   }
2966 
2967   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2968   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2969   PetscFunctionReturn(0);
2970 }
2971 
2972 #undef __FUNCT__
2973 #define __FUNCT__ "MatSetColoring_SeqAIJ"
2974 int MatSetColoring_SeqAIJ(Mat A,ISColoring coloring)
2975 {
2976   int        ierr;
2977   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2978 
2979   PetscFunctionBegin;
2980   ierr        = ISColoringReference(coloring);CHKERRQ(ierr);
2981   a->coloring = coloring;
2982   PetscFunctionReturn(0);
2983 }
2984 
2985 #if defined(PETSC_HAVE_ADIC) && !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_SINGLE)
2986 EXTERN_C_BEGIN
2987 #include "adic/ad_utils.h"
2988 EXTERN_C_END
2989 
2990 #undef __FUNCT__
2991 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ"
2992 int MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
2993 {
2994   Mat_SeqAIJ  *a = (Mat_SeqAIJ*)A->data;
2995   int         m = A->m,*ii = a->i,*jj = a->j,nz,i,*color,j,nlen;
2996   PetscScalar *v = a->a,*values;
2997   char        *cadvalues = (char *)advalues;
2998 
2999   PetscFunctionBegin;
3000   if (!a->coloring) SETERRQ(1,"Coloring not set for matrix");
3001   nlen  = PetscADGetDerivTypeSize();
3002   color = a->coloring->colors;
3003   /* loop over rows */
3004   for (i=0; i<m; i++) {
3005     nz = ii[i+1] - ii[i];
3006     /* loop over columns putting computed value into matrix */
3007     values = PetscADGetGradArray(cadvalues);
3008     for (j=0; j<nz; j++) {
3009       *v++ = values[color[*jj++]];
3010     }
3011     cadvalues += nlen; /* jump to next row of derivatives */
3012   }
3013   PetscFunctionReturn(0);
3014 }
3015 
3016 #else
3017 
3018 #undef __FUNCT__
3019 #define __FUNCT__ "MatSetValuesAdic_SeqAIJ"
3020 int MatSetValuesAdic_SeqAIJ(Mat A,void *advalues)
3021 {
3022   PetscFunctionBegin;
3023   SETERRQ(1,"PETSc installed without ADIC");
3024 }
3025 
3026 #endif
3027 
3028 #undef __FUNCT__
3029 #define __FUNCT__ "MatSetValuesAdifor_SeqAIJ"
3030 int MatSetValuesAdifor_SeqAIJ(Mat A,int nl,void *advalues)
3031 {
3032   Mat_SeqAIJ   *a = (Mat_SeqAIJ*)A->data;
3033   int          m = A->m,*ii = a->i,*jj = a->j,nz,i,*color,j;
3034   PetscScalar  *v = a->a,*values = (PetscScalar *)advalues;
3035 
3036   PetscFunctionBegin;
3037   if (!a->coloring) SETERRQ(1,"Coloring not set for matrix");
3038   color = a->coloring->colors;
3039   /* loop over rows */
3040   for (i=0; i<m; i++) {
3041     nz = ii[i+1] - ii[i];
3042     /* loop over columns putting computed value into matrix */
3043     for (j=0; j<nz; j++) {
3044       *v++ = values[color[*jj++]];
3045     }
3046     values += nl; /* jump to next row of derivatives */
3047   }
3048   PetscFunctionReturn(0);
3049 }
3050 
3051