xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 17ab2063d7a783d54277ff0521cec1a5109958dd)
1*17ab2063SBarry Smith #ifndef lint
2*17ab2063SBarry Smith static char vcid[] = "$Id: aij.c,v 1.90 1995/09/21 20:10:56 bsmith Exp bsmith $";
3*17ab2063SBarry Smith #endif
4*17ab2063SBarry Smith 
5*17ab2063SBarry Smith #include "aij.h"
6*17ab2063SBarry Smith #include "vec/vecimpl.h"
7*17ab2063SBarry Smith #include "inline/spops.h"
8*17ab2063SBarry Smith 
9*17ab2063SBarry Smith extern int MatToSymmetricIJ_SeqAIJ(Mat_SeqAIJ*,int**,int**);
10*17ab2063SBarry Smith 
11*17ab2063SBarry Smith static int MatGetReordering_SeqAIJ(Mat mat,MatOrdering type,IS *rperm, IS *cperm)
12*17ab2063SBarry Smith {
13*17ab2063SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *) mat->data;
14*17ab2063SBarry Smith   int     ierr, *ia, *ja;
15*17ab2063SBarry Smith 
16*17ab2063SBarry Smith   if (!aij->assembled)
17*17ab2063SBarry Smith     SETERRQ(1,"MatGetReordering_SeqAIJ:Cannot reorder unassembled matrix");
18*17ab2063SBarry Smith 
19*17ab2063SBarry Smith   ierr = MatToSymmetricIJ_SeqAIJ( aij, &ia, &ja ); CHKERRQ(ierr);
20*17ab2063SBarry Smith   ierr = MatGetReordering_IJ(aij->n,ia,ja,type,rperm,cperm); CHKERRQ(ierr);
21*17ab2063SBarry Smith   PETSCFREE(ia); PETSCFREE(ja);
22*17ab2063SBarry Smith   return 0;
23*17ab2063SBarry Smith }
24*17ab2063SBarry Smith 
25*17ab2063SBarry Smith #define CHUNCKSIZE   10
26*17ab2063SBarry Smith 
27*17ab2063SBarry Smith /* This version has row oriented v  */
28*17ab2063SBarry Smith static int MatSetValues_SeqAIJ(Mat matin,int m,int *idxm,int n,
29*17ab2063SBarry Smith                             int *idxn,Scalar *v,InsertMode  addv)
30*17ab2063SBarry Smith {
31*17ab2063SBarry Smith   Mat_SeqAIJ *mat = (Mat_SeqAIJ *) matin->data;
32*17ab2063SBarry Smith   int    *rp,k,a,b,t,ii,row,nrow,i,col,l,rmax, N, sorted = mat->sorted;
33*17ab2063SBarry Smith   int    *imax = mat->imax, *ai = mat->i, *ailen = mat->ilen;
34*17ab2063SBarry Smith   int    *aj = mat->j, nonew = mat->nonew;
35*17ab2063SBarry Smith   Scalar *ap,value, *aa = mat->a;
36*17ab2063SBarry Smith    int shift = mat->indexshift;
37*17ab2063SBarry Smith 
38*17ab2063SBarry Smith   for ( k=0; k<m; k++ ) { /* loop over added rows */
39*17ab2063SBarry Smith     row  = idxm[k];
40*17ab2063SBarry Smith     if (row < 0) SETERRQ(1,"MatSetValues_SeqAIJ:Negative row");
41*17ab2063SBarry Smith     if (row >= mat->m) SETERRQ(1,"MatSetValues_SeqAIJ:Row too large");
42*17ab2063SBarry Smith     rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
43*17ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
44*17ab2063SBarry Smith     a = 0;
45*17ab2063SBarry Smith     for ( l=0; l<n; l++ ) { /* loop over added columns */
46*17ab2063SBarry Smith       if (idxn[l] < 0) SETERRQ(1,"MatSetValues_SeqAIJ:Negative column");
47*17ab2063SBarry Smith       if (idxn[l] >= mat->n)
48*17ab2063SBarry Smith         SETERRQ(1,"MatSetValues_SeqAIJ:Column too large");
49*17ab2063SBarry Smith       col = idxn[l] - shift; value = *v++;
50*17ab2063SBarry Smith       if (!sorted) a = 0; b = nrow;
51*17ab2063SBarry Smith       while (b-a > 5) {
52*17ab2063SBarry Smith         t = (b+a)/2;
53*17ab2063SBarry Smith         if (rp[t] > col) b = t;
54*17ab2063SBarry Smith         else             a = t;
55*17ab2063SBarry Smith       }
56*17ab2063SBarry Smith       for ( i=a; i<b; i++ ) {
57*17ab2063SBarry Smith         if (rp[i] > col) break;
58*17ab2063SBarry Smith         if (rp[i] == col) {
59*17ab2063SBarry Smith           if (addv == ADD_VALUES) ap[i] += value;
60*17ab2063SBarry Smith           else                    ap[i] = value;
61*17ab2063SBarry Smith           goto noinsert;
62*17ab2063SBarry Smith         }
63*17ab2063SBarry Smith       }
64*17ab2063SBarry Smith       if (nonew) goto noinsert;
65*17ab2063SBarry Smith       if (nrow >= rmax) {
66*17ab2063SBarry Smith         /* there is no extra room in row, therefore enlarge */
67*17ab2063SBarry Smith         int    new_nz = ai[mat->m] + CHUNCKSIZE,len,*new_i,*new_j;
68*17ab2063SBarry Smith         Scalar *new_a;
69*17ab2063SBarry Smith 
70*17ab2063SBarry Smith         /* malloc new storage space */
71*17ab2063SBarry Smith         len     = new_nz*(sizeof(int)+sizeof(Scalar))+(mat->m+1)*sizeof(int);
72*17ab2063SBarry Smith         new_a  = (Scalar *) PETSCMALLOC( len ); CHKPTRQ(new_a);
73*17ab2063SBarry Smith         new_j  = (int *) (new_a + new_nz);
74*17ab2063SBarry Smith         new_i  = new_j + new_nz;
75*17ab2063SBarry Smith 
76*17ab2063SBarry Smith         /* copy over old data into new slots */
77*17ab2063SBarry Smith         for ( ii=0; ii<row+1; ii++ ) {new_i[ii] = ai[ii];}
78*17ab2063SBarry Smith         for ( ii=row+1; ii<mat->m+1; ii++ ) {new_i[ii] = ai[ii]+CHUNCKSIZE;}
79*17ab2063SBarry Smith         PETSCMEMCPY(new_j,aj,(ai[row]+nrow+shift)*sizeof(int));
80*17ab2063SBarry Smith         len = (new_nz - CHUNCKSIZE - ai[row] - nrow - shift);
81*17ab2063SBarry Smith         PETSCMEMCPY(new_j+ai[row]+shift+nrow+CHUNCKSIZE,aj+ai[row]+shift+nrow,
82*17ab2063SBarry Smith                                                            len*sizeof(int));
83*17ab2063SBarry Smith         PETSCMEMCPY(new_a,aa,(ai[row]+nrow+shift)*sizeof(Scalar));
84*17ab2063SBarry Smith         PETSCMEMCPY(new_a+ai[row]+shift+nrow+CHUNCKSIZE,aa+ai[row]+shift+nrow,
85*17ab2063SBarry Smith                                                          len*sizeof(Scalar));
86*17ab2063SBarry Smith         /* free up old matrix storage */
87*17ab2063SBarry Smith         PETSCFREE(mat->a); if (!mat->singlemalloc) {PETSCFREE(mat->i);PETSCFREE(mat->j);}
88*17ab2063SBarry Smith         aa = mat->a = new_a; ai = mat->i = new_i; aj = mat->j = new_j;
89*17ab2063SBarry Smith         mat->singlemalloc = 1;
90*17ab2063SBarry Smith 
91*17ab2063SBarry Smith         rp   = aj + ai[row] + shift; ap = aa + ai[row] + shift;
92*17ab2063SBarry Smith         rmax = imax[row] = imax[row] + CHUNCKSIZE;
93*17ab2063SBarry Smith         PLogObjectMemory(matin,CHUNCKSIZE*(sizeof(int) + sizeof(Scalar)));
94*17ab2063SBarry Smith         mat->maxnz += CHUNCKSIZE;
95*17ab2063SBarry Smith       }
96*17ab2063SBarry Smith       N = nrow++ - 1; mat->nz++;
97*17ab2063SBarry Smith       /* this has too many shifts here; but alternative was slower*/
98*17ab2063SBarry Smith       for ( ii=N; ii>=i; ii-- ) {/* shift values up*/
99*17ab2063SBarry Smith         rp[ii+1] = rp[ii];
100*17ab2063SBarry Smith         ap[ii+1] = ap[ii];
101*17ab2063SBarry Smith       }
102*17ab2063SBarry Smith       rp[i] = col;
103*17ab2063SBarry Smith       ap[i] = value;
104*17ab2063SBarry Smith       noinsert:;
105*17ab2063SBarry Smith       a = i + 1;
106*17ab2063SBarry Smith     }
107*17ab2063SBarry Smith     ailen[row] = nrow;
108*17ab2063SBarry Smith   }
109*17ab2063SBarry Smith   return 0;
110*17ab2063SBarry Smith }
111*17ab2063SBarry Smith 
112*17ab2063SBarry Smith #include "draw.h"
113*17ab2063SBarry Smith #include "pinclude/pviewer.h"
114*17ab2063SBarry Smith 
115*17ab2063SBarry Smith static int MatView_SeqAIJ(PetscObject obj,Viewer ptr)
116*17ab2063SBarry Smith {
117*17ab2063SBarry Smith   Mat         aijin = (Mat) obj;
118*17ab2063SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ *) aijin->data;
119*17ab2063SBarry Smith   int         ierr, i,j, m = aij->m;
120*17ab2063SBarry Smith   PetscObject vobj = (PetscObject) ptr;
121*17ab2063SBarry Smith   double      xl,yl,xr,yr,w,h;
122*17ab2063SBarry Smith    int shift = aij->indexshift;
123*17ab2063SBarry Smith 
124*17ab2063SBarry Smith   if (!aij->assembled)
125*17ab2063SBarry Smith     SETERRQ(1,"MatView_SeqAIJ:Cannot view unassembled matrix");
126*17ab2063SBarry Smith   if (!ptr) { /* so that viewers may be used from debuggers */
127*17ab2063SBarry Smith     ptr = STDOUT_VIEWER_SELF; vobj = (PetscObject) ptr;
128*17ab2063SBarry Smith   }
129*17ab2063SBarry Smith   if (vobj->cookie == DRAW_COOKIE && vobj->type == NULLWINDOW) return 0;
130*17ab2063SBarry Smith   if (vobj && vobj->cookie == VIEWER_COOKIE && vobj->type == MATLAB_VIEWER) {
131*17ab2063SBarry Smith     return ViewerMatlabPutSparse_Private(ptr,aij->m,aij->n,aij->nz,aij->a,
132*17ab2063SBarry Smith                                  aij->i,aij->j);
133*17ab2063SBarry Smith   }
134*17ab2063SBarry Smith   if (vobj && vobj->cookie == DRAW_COOKIE) {
135*17ab2063SBarry Smith     DrawCtx draw = (DrawCtx) ptr;
136*17ab2063SBarry Smith     xr = aij->n; yr = aij->m; h = yr/10.0; w = xr/10.0;
137*17ab2063SBarry Smith     xr += w; yr += h; xl = -w; yl = -h;
138*17ab2063SBarry Smith     ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
139*17ab2063SBarry Smith     /* loop over matrix elements drawing boxes */
140*17ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
141*17ab2063SBarry Smith       yl = m - i - 1.0; yr = yl + 1.0;
142*17ab2063SBarry Smith       for ( j=aij->i[i]+shift; j<aij->i[i+1]+shift; j++ ) {
143*17ab2063SBarry Smith         xl = aij->j[j] + shift; xr = xl + 1.0;
144*17ab2063SBarry Smith         DrawRectangle(draw,xl,yl,xr,yr,DRAW_BLACK,DRAW_BLACK,DRAW_BLACK,
145*17ab2063SBarry Smith                                                              DRAW_BLACK);
146*17ab2063SBarry Smith       }
147*17ab2063SBarry Smith     }
148*17ab2063SBarry Smith     DrawFlush(draw);
149*17ab2063SBarry Smith     return 0;
150*17ab2063SBarry Smith   }
151*17ab2063SBarry Smith   else {
152*17ab2063SBarry Smith     FILE *fd;
153*17ab2063SBarry Smith     char *outputname;
154*17ab2063SBarry Smith     int format;
155*17ab2063SBarry Smith 
156*17ab2063SBarry Smith     ierr = ViewerFileGetPointer_Private(ptr,&fd); CHKERRQ(ierr);
157*17ab2063SBarry Smith     ierr = ViewerFileGetOutputname_Private(ptr,&outputname); CHKERRQ(ierr);
158*17ab2063SBarry Smith     ierr = ViewerFileGetFormat_Private(ptr,&format);
159*17ab2063SBarry Smith     if (format == FILE_FORMAT_INFO) {
160*17ab2063SBarry Smith       /* do nothing for now */
161*17ab2063SBarry Smith     }
162*17ab2063SBarry Smith     else if (format == FILE_FORMAT_MATLAB) {
163*17ab2063SBarry Smith       int nz, nzalloc, mem;
164*17ab2063SBarry Smith       MatGetInfo(aijin,MAT_LOCAL,&nz,&nzalloc,&mem);
165*17ab2063SBarry Smith       fprintf(fd,"%% Size = %d %d \n",m,aij->n);
166*17ab2063SBarry Smith       fprintf(fd,"%% Nonzeros = %d \n",nz);
167*17ab2063SBarry Smith       fprintf(fd,"zzz = zeros(%d,3);\n",nz);
168*17ab2063SBarry Smith       fprintf(fd,"zzz = [\n");
169*17ab2063SBarry Smith 
170*17ab2063SBarry Smith       for (i=0; i<m; i++) {
171*17ab2063SBarry Smith         for ( j=aij->i[i]+shift; j<aij->i[i+1]+shift; j++ ) {
172*17ab2063SBarry Smith #if defined(PETSC_COMPLEX)
173*17ab2063SBarry Smith           fprintf(fd,"%d %d  %18.16e  %18.16e \n",
174*17ab2063SBarry Smith                i+1,aij->j[j],real(aij->a[j]),imag(aij->a[j]));
175*17ab2063SBarry Smith #else
176*17ab2063SBarry Smith           fprintf(fd,"%d %d  %18.16e\n", i+1, aij->j[j], aij->a[j]);
177*17ab2063SBarry Smith #endif
178*17ab2063SBarry Smith         }
179*17ab2063SBarry Smith       }
180*17ab2063SBarry Smith       fprintf(fd,"];\n %s = spconvert(zzz);\n",outputname);
181*17ab2063SBarry Smith     }
182*17ab2063SBarry Smith     else {
183*17ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
184*17ab2063SBarry Smith         fprintf(fd,"row %d:",i);
185*17ab2063SBarry Smith         for ( j=aij->i[i]+shift; j<aij->i[i+1]+shift; j++ ) {
186*17ab2063SBarry Smith #if defined(PETSC_COMPLEX)
187*17ab2063SBarry Smith           if (imag(aij->a[j]) != 0.0) {
188*17ab2063SBarry Smith             fprintf(fd," %d %g + %g i",
189*17ab2063SBarry Smith               aij->j[j]+shift,real(aij->a[j]),imag(aij->a[j]));
190*17ab2063SBarry Smith           }
191*17ab2063SBarry Smith           else {
192*17ab2063SBarry Smith             fprintf(fd," %d %g ",aij->j[j]+shift,real(aij->a[j]));
193*17ab2063SBarry Smith           }
194*17ab2063SBarry Smith #else
195*17ab2063SBarry Smith           fprintf(fd," %d %g ",aij->j[j]+shift,aij->a[j]);
196*17ab2063SBarry Smith #endif
197*17ab2063SBarry Smith         }
198*17ab2063SBarry Smith         fprintf(fd,"\n");
199*17ab2063SBarry Smith       }
200*17ab2063SBarry Smith     }
201*17ab2063SBarry Smith     fflush(fd);
202*17ab2063SBarry Smith   }
203*17ab2063SBarry Smith   return 0;
204*17ab2063SBarry Smith }
205*17ab2063SBarry Smith 
206*17ab2063SBarry Smith static int MatAssemblyEnd_SeqAIJ(Mat aijin,MatAssemblyType mode)
207*17ab2063SBarry Smith {
208*17ab2063SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *) aijin->data;
209*17ab2063SBarry Smith   int    fshift = 0,i,j,*ai = aij->i, *aj = aij->j, *imax = aij->imax;
210*17ab2063SBarry Smith   int    m = aij->m, *ip, N, *ailen = aij->ilen;
211*17ab2063SBarry Smith   Scalar *a = aij->a, *ap;
212*17ab2063SBarry Smith    int shift = aij->indexshift;
213*17ab2063SBarry Smith 
214*17ab2063SBarry Smith   if (mode == FLUSH_ASSEMBLY) return 0;
215*17ab2063SBarry Smith 
216*17ab2063SBarry Smith   for ( i=1; i<m; i++ ) {
217*17ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
218*17ab2063SBarry Smith     if (fshift) {
219*17ab2063SBarry Smith       ip = aj + ai[i] + shift; ap = a + ai[i] + shift;
220*17ab2063SBarry Smith       N = ailen[i];
221*17ab2063SBarry Smith       for ( j=0; j<N; j++ ) {
222*17ab2063SBarry Smith         ip[j-fshift] = ip[j];
223*17ab2063SBarry Smith         ap[j-fshift] = ap[j];
224*17ab2063SBarry Smith       }
225*17ab2063SBarry Smith     }
226*17ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
227*17ab2063SBarry Smith   }
228*17ab2063SBarry Smith   if (m) {
229*17ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
230*17ab2063SBarry Smith     ai[m] = ai[m-1] + ailen[m-1];
231*17ab2063SBarry Smith   }
232*17ab2063SBarry Smith   /* reset ilen and imax for each row */
233*17ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
234*17ab2063SBarry Smith     ailen[i] = imax[i] = ai[i+1] - ai[i];
235*17ab2063SBarry Smith   }
236*17ab2063SBarry Smith   aij->nz = ai[m] + shift;
237*17ab2063SBarry Smith 
238*17ab2063SBarry Smith   /* diagonals may have moved, so kill the diagonal pointers */
239*17ab2063SBarry Smith   if (fshift && aij->diag) {
240*17ab2063SBarry Smith     PETSCFREE(aij->diag);
241*17ab2063SBarry Smith     PLogObjectMemory(aijin,-(m+1)*sizeof(int));
242*17ab2063SBarry Smith     aij->diag = 0;
243*17ab2063SBarry Smith   }
244*17ab2063SBarry Smith   aij->assembled = 1;
245*17ab2063SBarry Smith   return 0;
246*17ab2063SBarry Smith }
247*17ab2063SBarry Smith 
248*17ab2063SBarry Smith static int MatZeroEntries_SeqAIJ(Mat mat)
249*17ab2063SBarry Smith {
250*17ab2063SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *) mat->data;
251*17ab2063SBarry Smith    int shift = aij->indexshift;
252*17ab2063SBarry Smith   Scalar  *a = aij->a;
253*17ab2063SBarry Smith   int     i,n = aij->i[aij->m]+shift;
254*17ab2063SBarry Smith 
255*17ab2063SBarry Smith   for ( i=0; i<n; i++ ) a[i] = 0.0;
256*17ab2063SBarry Smith   return 0;
257*17ab2063SBarry Smith 
258*17ab2063SBarry Smith }
259*17ab2063SBarry Smith int MatDestroy_SeqAIJ(PetscObject obj)
260*17ab2063SBarry Smith {
261*17ab2063SBarry Smith   Mat mat         = (Mat) obj;
262*17ab2063SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *) mat->data;
263*17ab2063SBarry Smith #if defined(PETSC_LOG)
264*17ab2063SBarry Smith   PLogObjectState(obj,"Rows=%d, Cols=%d, NZ=%d",aij->m,aij->n,aij->nz);
265*17ab2063SBarry Smith #endif
266*17ab2063SBarry Smith   PETSCFREE(aij->a);
267*17ab2063SBarry Smith   if (!aij->singlemalloc) { PETSCFREE(aij->i); PETSCFREE(aij->j);}
268*17ab2063SBarry Smith   if (aij->diag) PETSCFREE(aij->diag);
269*17ab2063SBarry Smith   if (aij->ilen) PETSCFREE(aij->ilen);
270*17ab2063SBarry Smith   if (aij->imax) PETSCFREE(aij->imax);
271*17ab2063SBarry Smith   if (aij->solve_work) PETSCFREE(aij->solve_work);
272*17ab2063SBarry Smith   PETSCFREE(aij);
273*17ab2063SBarry Smith   PLogObjectDestroy(mat);
274*17ab2063SBarry Smith   PETSCHEADERDESTROY(mat);
275*17ab2063SBarry Smith   return 0;
276*17ab2063SBarry Smith }
277*17ab2063SBarry Smith 
278*17ab2063SBarry Smith static int MatCompress_SeqAIJ(Mat aijin)
279*17ab2063SBarry Smith {
280*17ab2063SBarry Smith   return 0;
281*17ab2063SBarry Smith }
282*17ab2063SBarry Smith 
283*17ab2063SBarry Smith static int MatSetOption_SeqAIJ(Mat aijin,MatOption op)
284*17ab2063SBarry Smith {
285*17ab2063SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *) aijin->data;
286*17ab2063SBarry Smith   if      (op == ROW_ORIENTED)              aij->roworiented = 1;
287*17ab2063SBarry Smith   else if (op == COLUMN_ORIENTED)           aij->roworiented = 0;
288*17ab2063SBarry Smith   else if (op == COLUMNS_SORTED)            aij->sorted      = 1;
289*17ab2063SBarry Smith   /* doesn't care about sorted rows */
290*17ab2063SBarry Smith   else if (op == NO_NEW_NONZERO_LOCATIONS)  aij->nonew       = 1;
291*17ab2063SBarry Smith   else if (op == YES_NEW_NONZERO_LOCATIONS) aij->nonew       = 0;
292*17ab2063SBarry Smith 
293*17ab2063SBarry Smith   if (op == COLUMN_ORIENTED)
294*17ab2063SBarry Smith     SETERRQ(1,"MatSetOption_SeqAIJ:Column oriented input not supported");
295*17ab2063SBarry Smith   return 0;
296*17ab2063SBarry Smith }
297*17ab2063SBarry Smith 
298*17ab2063SBarry Smith static int MatGetDiagonal_SeqAIJ(Mat aijin,Vec v)
299*17ab2063SBarry Smith {
300*17ab2063SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *) aijin->data;
301*17ab2063SBarry Smith   int    i,j, n;
302*17ab2063SBarry Smith   Scalar *x, zero = 0.0;
303*17ab2063SBarry Smith    int shift = aij->indexshift;
304*17ab2063SBarry Smith 
305*17ab2063SBarry Smith   if (!aij->assembled) SETERRQ(1,
306*17ab2063SBarry Smith     "MatGetDiagonal_SeqAIJ:Cannot get diagonal of unassembled matrix");
307*17ab2063SBarry Smith   VecSet(&zero,v);
308*17ab2063SBarry Smith   VecGetArray(v,&x); VecGetLocalSize(v,&n);
309*17ab2063SBarry Smith   if (n != aij->m)
310*17ab2063SBarry Smith     SETERRQ(1,"MatGetDiagonal_SeqAIJ:Nonconforming matrix and vector");
311*17ab2063SBarry Smith   for ( i=0; i<aij->m; i++ ) {
312*17ab2063SBarry Smith     for ( j=aij->i[i]+shift; j<aij->i[i+1]+shift; j++ ) {
313*17ab2063SBarry Smith       if (aij->j[j]+shift == i) {
314*17ab2063SBarry Smith         x[i] = aij->a[j];
315*17ab2063SBarry Smith         break;
316*17ab2063SBarry Smith       }
317*17ab2063SBarry Smith     }
318*17ab2063SBarry Smith   }
319*17ab2063SBarry Smith   return 0;
320*17ab2063SBarry Smith }
321*17ab2063SBarry Smith 
322*17ab2063SBarry Smith /* -------------------------------------------------------*/
323*17ab2063SBarry Smith /* Should check that shapes of vectors and matrices match */
324*17ab2063SBarry Smith /* -------------------------------------------------------*/
325*17ab2063SBarry Smith static int MatMultTrans_SeqAIJ(Mat aijin,Vec xx,Vec yy)
326*17ab2063SBarry Smith {
327*17ab2063SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *) aijin->data;
328*17ab2063SBarry Smith   Scalar  *x, *y, *v, alpha;
329*17ab2063SBarry Smith   int     m = aij->m, n, i, *idx;
330*17ab2063SBarry Smith    int shift = aij->indexshift;
331*17ab2063SBarry Smith 
332*17ab2063SBarry Smith   if (!aij->assembled)
333*17ab2063SBarry Smith     SETERRQ(1,"MatMultTrans_SeqAIJ:Cannot multiply unassembled matrix");
334*17ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
335*17ab2063SBarry Smith   PETSCMEMSET(y,0,aij->n*sizeof(Scalar));
336*17ab2063SBarry Smith   y = y + shift; /* shift for Fortran start by 1 indexing */
337*17ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
338*17ab2063SBarry Smith     idx   = aij->j + aij->i[i] + shift;
339*17ab2063SBarry Smith     v     = aij->a + aij->i[i] + shift;
340*17ab2063SBarry Smith     n     = aij->i[i+1] - aij->i[i];
341*17ab2063SBarry Smith     alpha = x[i];
342*17ab2063SBarry Smith     /* should inline */
343*17ab2063SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
344*17ab2063SBarry Smith   }
345*17ab2063SBarry Smith   PLogFlops(2*aij->nz - aij->n);
346*17ab2063SBarry Smith   return 0;
347*17ab2063SBarry Smith }
348*17ab2063SBarry Smith static int MatMultTransAdd_SeqAIJ(Mat aijin,Vec xx,Vec zz,Vec yy)
349*17ab2063SBarry Smith {
350*17ab2063SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *) aijin->data;
351*17ab2063SBarry Smith   Scalar  *x, *y, *v, alpha;
352*17ab2063SBarry Smith   int     m = aij->m, n, i, *idx;
353*17ab2063SBarry Smith    int shift = aij->indexshift;
354*17ab2063SBarry Smith 
355*17ab2063SBarry Smith   if (!aij->assembled)
356*17ab2063SBarry Smith     SETERRQ(1,"MatMultTransAdd_SeqAIJ:Cannot multiply unassembled matrix");
357*17ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
358*17ab2063SBarry Smith   if (zz != yy) VecCopy(zz,yy);
359*17ab2063SBarry Smith   y = y + shift; /* shift for Fortran start by 1 indexing */
360*17ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
361*17ab2063SBarry Smith     idx   = aij->j + aij->i[i] + shift;
362*17ab2063SBarry Smith     v     = aij->a + aij->i[i] + shift;
363*17ab2063SBarry Smith     n     = aij->i[i+1] - aij->i[i];
364*17ab2063SBarry Smith     alpha = x[i];
365*17ab2063SBarry Smith     /* should inline */
366*17ab2063SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
367*17ab2063SBarry Smith   }
368*17ab2063SBarry Smith   return 0;
369*17ab2063SBarry Smith }
370*17ab2063SBarry Smith 
371*17ab2063SBarry Smith static int MatMult_SeqAIJ(Mat aijin,Vec xx,Vec yy)
372*17ab2063SBarry Smith {
373*17ab2063SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *) aijin->data;
374*17ab2063SBarry Smith   Scalar     *x, *y, *v, sum;
375*17ab2063SBarry Smith   int        m = aij->m, n, i, *idx;
376*17ab2063SBarry Smith   int        shift = aij->indexshift,ii;
377*17ab2063SBarry Smith 
378*17ab2063SBarry Smith   if (!aij->assembled)
379*17ab2063SBarry Smith     SETERRQ(1,"MatMult_SeqAIJ:Cannot multiply unassembled matrix");
380*17ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
381*17ab2063SBarry Smith   x = x + shift; /* shift for Fortran start by 1 indexing */
382*17ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
383*17ab2063SBarry Smith     idx  = aij->j + aij->i[i] + shift;
384*17ab2063SBarry Smith     v    = aij->a + aij->i[i] + shift;
385*17ab2063SBarry Smith     n    = aij->i[i+1] - aij->i[i];
386*17ab2063SBarry Smith     sum  = 0.0;
387*17ab2063SBarry Smith     /* SPARSEDENSEDOT(sum,x,v,idx,n);  */
388*17ab2063SBarry Smith     while (n--) sum += *v++ * x[*idx++];
389*17ab2063SBarry Smith     /* for ( j=n-1; j>-1; j--) sum += v[j]*x[idx[j]]; */
390*17ab2063SBarry Smith     y[i] = sum;
391*17ab2063SBarry Smith   }
392*17ab2063SBarry Smith   PLogFlops(2*aij->nz - m);
393*17ab2063SBarry Smith   return 0;
394*17ab2063SBarry Smith }
395*17ab2063SBarry Smith 
396*17ab2063SBarry Smith static int MatMultAdd_SeqAIJ(Mat aijin,Vec xx,Vec yy,Vec zz)
397*17ab2063SBarry Smith {
398*17ab2063SBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ *) aijin->data;
399*17ab2063SBarry Smith   Scalar  *x, *y, *z, *v, sum;
400*17ab2063SBarry Smith   int     m = aij->m, n, i, *idx;
401*17ab2063SBarry Smith    int shift = aij->indexshift;
402*17ab2063SBarry Smith 
403*17ab2063SBarry Smith   if (!aij->assembled)
404*17ab2063SBarry Smith     SETERRQ(1,"MatMultAdd_SeqAIJ:Cannot multiply unassembled matrix");
405*17ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z);
406*17ab2063SBarry Smith   x = x + shift; /* shift for Fortran start by 1 indexing */
407*17ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
408*17ab2063SBarry Smith     idx  = aij->j + aij->i[i] + shift;
409*17ab2063SBarry Smith     v    = aij->a + aij->i[i] + shift;
410*17ab2063SBarry Smith     n    = aij->i[i+1] - aij->i[i];
411*17ab2063SBarry Smith     sum  = y[i];
412*17ab2063SBarry Smith     SPARSEDENSEDOT(sum,x,v,idx,n);
413*17ab2063SBarry Smith     z[i] = sum;
414*17ab2063SBarry Smith   }
415*17ab2063SBarry Smith   PLogFlops(2*aij->nz);
416*17ab2063SBarry Smith   return 0;
417*17ab2063SBarry Smith }
418*17ab2063SBarry Smith 
419*17ab2063SBarry Smith /*
420*17ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
421*17ab2063SBarry Smith */
422*17ab2063SBarry Smith 
423*17ab2063SBarry Smith int MatMarkDiag_SeqAIJ(Mat mat)
424*17ab2063SBarry Smith {
425*17ab2063SBarry Smith    Mat_SeqAIJ *aij = (Mat_SeqAIJ *) mat->data;
426*17ab2063SBarry Smith   int    i,j, *diag, m = aij->m;
427*17ab2063SBarry Smith    int shift = aij->indexshift;
428*17ab2063SBarry Smith 
429*17ab2063SBarry Smith   if (!aij->assembled) SETERRQ(1,"MatMarkDiag_SeqAIJ:unassembled matrix");
430*17ab2063SBarry Smith   diag = (int *) PETSCMALLOC( (m+1)*sizeof(int)); CHKPTRQ(diag);
431*17ab2063SBarry Smith   PLogObjectMemory(mat,(m+1)*sizeof(int));
432*17ab2063SBarry Smith   for ( i=0; i<aij->m; i++ ) {
433*17ab2063SBarry Smith     for ( j=aij->i[i]+shift; j<aij->i[i+1]+shift; j++ ) {
434*17ab2063SBarry Smith       if (aij->j[j]+shift == i) {
435*17ab2063SBarry Smith         diag[i] = j - shift;
436*17ab2063SBarry Smith         break;
437*17ab2063SBarry Smith       }
438*17ab2063SBarry Smith     }
439*17ab2063SBarry Smith   }
440*17ab2063SBarry Smith   aij->diag = diag;
441*17ab2063SBarry Smith   return 0;
442*17ab2063SBarry Smith }
443*17ab2063SBarry Smith 
444*17ab2063SBarry Smith static int MatRelax_SeqAIJ(Mat matin,Vec bb,double omega,MatSORType flag,
445*17ab2063SBarry Smith                         double fshift,int its,Vec xx)
446*17ab2063SBarry Smith {
447*17ab2063SBarry Smith   Mat_SeqAIJ *mat = (Mat_SeqAIJ *) matin->data;
448*17ab2063SBarry Smith   Scalar *x, *b, *bs,  d, *xs, sum, *v = mat->a,*t,scale,*ts, *xb;
449*17ab2063SBarry Smith   int    ierr, *idx, *diag;
450*17ab2063SBarry Smith   int    n = mat->n, m = mat->m, i;
451*17ab2063SBarry Smith    int shift = mat->indexshift;
452*17ab2063SBarry Smith 
453*17ab2063SBarry Smith   VecGetArray(xx,&x); VecGetArray(bb,&b);
454*17ab2063SBarry Smith   if (!mat->diag) {if ((ierr = MatMarkDiag_SeqAIJ(matin))) return ierr;}
455*17ab2063SBarry Smith   diag = mat->diag;
456*17ab2063SBarry Smith   xs = x + shift; /* shifted by one for index start of a or mat->j*/
457*17ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
458*17ab2063SBarry Smith    /* apply ( U + D/omega) to the vector */
459*17ab2063SBarry Smith     bs = b + shift;
460*17ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
461*17ab2063SBarry Smith         d    = fshift + mat->a[diag[i] + shift];
462*17ab2063SBarry Smith         n    = mat->i[i+1] - diag[i] - 1;
463*17ab2063SBarry Smith         idx  = mat->j + diag[i] + (!shift);
464*17ab2063SBarry Smith         v    = mat->a + diag[i] + (!shift);
465*17ab2063SBarry Smith         sum  = b[i]*d/omega;
466*17ab2063SBarry Smith         SPARSEDENSEDOT(sum,bs,v,idx,n);
467*17ab2063SBarry Smith         x[i] = sum;
468*17ab2063SBarry Smith     }
469*17ab2063SBarry Smith     return 0;
470*17ab2063SBarry Smith   }
471*17ab2063SBarry Smith   if (flag == SOR_APPLY_LOWER) {
472*17ab2063SBarry Smith     SETERRQ(1,"MatRelax_SeqAIJ:SOR_APPLY_LOWER is not done");
473*17ab2063SBarry Smith   }
474*17ab2063SBarry Smith   if (flag & SOR_EISENSTAT) {
475*17ab2063SBarry Smith     /* Let  A = L + U + D; where L is lower trianglar,
476*17ab2063SBarry Smith     U is upper triangular, E is diagonal; This routine applies
477*17ab2063SBarry Smith 
478*17ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
479*17ab2063SBarry Smith 
480*17ab2063SBarry Smith     to a vector efficiently using Eisenstat's trick. This is for
481*17ab2063SBarry Smith     the case of SSOR preconditioner, so E is D/omega where omega
482*17ab2063SBarry Smith     is the relaxation factor.
483*17ab2063SBarry Smith     */
484*17ab2063SBarry Smith     t = (Scalar *) PETSCMALLOC( m*sizeof(Scalar) ); CHKPTRQ(t);
485*17ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
486*17ab2063SBarry Smith 
487*17ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
488*17ab2063SBarry Smith     for ( i=m-1; i>=0; i-- ) {
489*17ab2063SBarry Smith       d    = fshift + mat->a[diag[i] + shift];
490*17ab2063SBarry Smith       n    = mat->i[i+1] - diag[i] - 1;
491*17ab2063SBarry Smith       idx  = mat->j + diag[i] + (!shift);
492*17ab2063SBarry Smith       v    = mat->a + diag[i] + (!shift);
493*17ab2063SBarry Smith       sum  = b[i];
494*17ab2063SBarry Smith       SPARSEDENSEMDOT(sum,xs,v,idx,n);
495*17ab2063SBarry Smith       x[i] = omega*(sum/d);
496*17ab2063SBarry Smith     }
497*17ab2063SBarry Smith 
498*17ab2063SBarry Smith     /*  t = b - (2*E - D)x */
499*17ab2063SBarry Smith     v = mat->a;
500*17ab2063SBarry Smith     for ( i=0; i<m; i++ ) { t[i] = b[i] - scale*(v[*diag++ + shift])*x[i]; }
501*17ab2063SBarry Smith 
502*17ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
503*17ab2063SBarry Smith     ts = t + shift; /* shifted by one for index start of a or mat->j*/
504*17ab2063SBarry Smith     diag = mat->diag;
505*17ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
506*17ab2063SBarry Smith       d    = fshift + mat->a[diag[i]+shift];
507*17ab2063SBarry Smith       n    = diag[i] - mat->i[i];
508*17ab2063SBarry Smith       idx  = mat->j + mat->i[i] + shift;
509*17ab2063SBarry Smith       v    = mat->a + mat->i[i] + shift;
510*17ab2063SBarry Smith       sum  = t[i];
511*17ab2063SBarry Smith       SPARSEDENSEMDOT(sum,ts,v,idx,n);
512*17ab2063SBarry Smith       t[i] = omega*(sum/d);
513*17ab2063SBarry Smith     }
514*17ab2063SBarry Smith 
515*17ab2063SBarry Smith     /*  x = x + t */
516*17ab2063SBarry Smith     for ( i=0; i<m; i++ ) { x[i] += t[i]; }
517*17ab2063SBarry Smith     PETSCFREE(t);
518*17ab2063SBarry Smith     return 0;
519*17ab2063SBarry Smith   }
520*17ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
521*17ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
522*17ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
523*17ab2063SBarry Smith         d    = fshift + mat->a[diag[i]+shift];
524*17ab2063SBarry Smith         n    = diag[i] - mat->i[i];
525*17ab2063SBarry Smith         idx  = mat->j + mat->i[i] + shift;
526*17ab2063SBarry Smith         v    = mat->a + mat->i[i] + shift;
527*17ab2063SBarry Smith         sum  = b[i];
528*17ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
529*17ab2063SBarry Smith         x[i] = omega*(sum/d);
530*17ab2063SBarry Smith       }
531*17ab2063SBarry Smith       xb = x;
532*17ab2063SBarry Smith     }
533*17ab2063SBarry Smith     else xb = b;
534*17ab2063SBarry Smith     if ((flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) &&
535*17ab2063SBarry Smith         (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP)) {
536*17ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
537*17ab2063SBarry Smith         x[i] *= mat->a[diag[i]+shift];
538*17ab2063SBarry Smith       }
539*17ab2063SBarry Smith     }
540*17ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
541*17ab2063SBarry Smith       for ( i=m-1; i>=0; i-- ) {
542*17ab2063SBarry Smith         d    = fshift + mat->a[diag[i] + shift];
543*17ab2063SBarry Smith         n    = mat->i[i+1] - diag[i] - 1;
544*17ab2063SBarry Smith         idx  = mat->j + diag[i] + (!shift);
545*17ab2063SBarry Smith         v    = mat->a + diag[i] + (!shift);
546*17ab2063SBarry Smith         sum  = xb[i];
547*17ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
548*17ab2063SBarry Smith         x[i] = omega*(sum/d);
549*17ab2063SBarry Smith       }
550*17ab2063SBarry Smith     }
551*17ab2063SBarry Smith     its--;
552*17ab2063SBarry Smith   }
553*17ab2063SBarry Smith   while (its--) {
554*17ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
555*17ab2063SBarry Smith       for ( i=0; i<m; i++ ) {
556*17ab2063SBarry Smith         d    = fshift + mat->a[diag[i]+shift];
557*17ab2063SBarry Smith         n    = mat->i[i+1] - mat->i[i];
558*17ab2063SBarry Smith         idx  = mat->j + mat->i[i] + shift;
559*17ab2063SBarry Smith         v    = mat->a + mat->i[i] + shift;
560*17ab2063SBarry Smith         sum  = b[i];
561*17ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
562*17ab2063SBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum/d + x[i]);
563*17ab2063SBarry Smith       }
564*17ab2063SBarry Smith     }
565*17ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
566*17ab2063SBarry Smith       for ( i=m-1; i>=0; i-- ) {
567*17ab2063SBarry Smith         d    = fshift + mat->a[diag[i] + shift];
568*17ab2063SBarry Smith         n    = mat->i[i+1] - mat->i[i];
569*17ab2063SBarry Smith         idx  = mat->j + mat->i[i] + shift;
570*17ab2063SBarry Smith         v    = mat->a + mat->i[i] + shift;
571*17ab2063SBarry Smith         sum  = b[i];
572*17ab2063SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
573*17ab2063SBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum/d + x[i]);
574*17ab2063SBarry Smith       }
575*17ab2063SBarry Smith     }
576*17ab2063SBarry Smith   }
577*17ab2063SBarry Smith   return 0;
578*17ab2063SBarry Smith }
579*17ab2063SBarry Smith 
580*17ab2063SBarry Smith static int MatGetInfo_SeqAIJ(Mat matin,MatInfoType flag,int *nz,
581*17ab2063SBarry Smith                           int *nzalloc,int *mem)
582*17ab2063SBarry Smith {
583*17ab2063SBarry Smith   Mat_SeqAIJ *mat = (Mat_SeqAIJ *) matin->data;
584*17ab2063SBarry Smith   *nz      = mat->nz;
585*17ab2063SBarry Smith   *nzalloc = mat->maxnz;
586*17ab2063SBarry Smith   *mem     = (int)matin->mem;
587*17ab2063SBarry Smith   return 0;
588*17ab2063SBarry Smith }
589*17ab2063SBarry Smith 
590*17ab2063SBarry Smith extern int MatLUFactorSymbolic_SeqAIJ(Mat,IS,IS,double,Mat*);
591*17ab2063SBarry Smith extern int MatLUFactorNumeric_SeqAIJ(Mat,Mat*);
592*17ab2063SBarry Smith extern int MatLUFactor_SeqAIJ(Mat,IS,IS,double);
593*17ab2063SBarry Smith extern int MatSolve_SeqAIJ(Mat,Vec,Vec);
594*17ab2063SBarry Smith extern int MatSolveAdd_SeqAIJ(Mat,Vec,Vec,Vec);
595*17ab2063SBarry Smith extern int MatSolveTrans_SeqAIJ(Mat,Vec,Vec);
596*17ab2063SBarry Smith extern int MatSolveTransAdd_SeqAIJ(Mat,Vec,Vec,Vec);
597*17ab2063SBarry Smith 
598*17ab2063SBarry Smith static int MatZeroRows_SeqAIJ(Mat A,IS is,Scalar *diag)
599*17ab2063SBarry Smith {
600*17ab2063SBarry Smith   Mat_SeqAIJ *l = (Mat_SeqAIJ *) A->data;
601*17ab2063SBarry Smith   int     i,ierr,N, *rows,m = l->m - 1;
602*17ab2063SBarry Smith    int shift = l->indexshift;
603*17ab2063SBarry Smith 
604*17ab2063SBarry Smith   ierr = ISGetLocalSize(is,&N); CHKERRQ(ierr);
605*17ab2063SBarry Smith   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
606*17ab2063SBarry Smith   if (diag) {
607*17ab2063SBarry Smith     for ( i=0; i<N; i++ ) {
608*17ab2063SBarry Smith       if (rows[i] < 0 || rows[i] > m)
609*17ab2063SBarry Smith         SETERRQ(1,"MatZeroRows_SeqAIJ:row out of range");
610*17ab2063SBarry Smith       if (l->ilen[rows[i]] > 0) { /* in case row was completely empty */
611*17ab2063SBarry Smith         l->ilen[rows[i]] = 1;
612*17ab2063SBarry Smith         l->a[l->i[rows[i]]+shift] = *diag;
613*17ab2063SBarry Smith         l->j[l->i[rows[i]]+shift] = rows[i]+shift;
614*17ab2063SBarry Smith       }
615*17ab2063SBarry Smith       else {
616*17ab2063SBarry Smith         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],diag,INSERT_VALUES);
617*17ab2063SBarry Smith         CHKERRQ(ierr);
618*17ab2063SBarry Smith       }
619*17ab2063SBarry Smith     }
620*17ab2063SBarry Smith   }
621*17ab2063SBarry Smith   else {
622*17ab2063SBarry Smith     for ( i=0; i<N; i++ ) {
623*17ab2063SBarry Smith       if (rows[i] < 0 || rows[i] > m)
624*17ab2063SBarry Smith         SETERRQ(1,"MatZeroRows_SeqAIJ:row out of range");
625*17ab2063SBarry Smith       l->ilen[rows[i]] = 0;
626*17ab2063SBarry Smith     }
627*17ab2063SBarry Smith   }
628*17ab2063SBarry Smith   ISRestoreIndices(is,&rows);
629*17ab2063SBarry Smith   ierr = MatAssemblyBegin(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
630*17ab2063SBarry Smith   ierr = MatAssemblyEnd(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
631*17ab2063SBarry Smith   return 0;
632*17ab2063SBarry Smith }
633*17ab2063SBarry Smith 
634*17ab2063SBarry Smith static int MatGetSize_SeqAIJ(Mat matin,int *m,int *n)
635*17ab2063SBarry Smith {
636*17ab2063SBarry Smith   Mat_SeqAIJ *mat = (Mat_SeqAIJ *) matin->data;
637*17ab2063SBarry Smith   *m = mat->m; *n = mat->n;
638*17ab2063SBarry Smith   return 0;
639*17ab2063SBarry Smith }
640*17ab2063SBarry Smith 
641*17ab2063SBarry Smith static int MatGetOwnershipRange_SeqAIJ(Mat matin,int *m,int *n)
642*17ab2063SBarry Smith {
643*17ab2063SBarry Smith   Mat_SeqAIJ *mat = (Mat_SeqAIJ *) matin->data;
644*17ab2063SBarry Smith   *m = 0; *n = mat->m;
645*17ab2063SBarry Smith   return 0;
646*17ab2063SBarry Smith }
647*17ab2063SBarry Smith static int MatGetRow_SeqAIJ(Mat matin,int row,int *nz,int **idx,Scalar **v)
648*17ab2063SBarry Smith {
649*17ab2063SBarry Smith   Mat_SeqAIJ *mat = (Mat_SeqAIJ *) matin->data;
650*17ab2063SBarry Smith   int     *itmp,i,ierr;
651*17ab2063SBarry Smith    int shift = mat->indexshift;
652*17ab2063SBarry Smith 
653*17ab2063SBarry Smith   if (row < 0 || row >= mat->m) SETERRQ(1,"MatGetRow_SeqAIJ:Row out of range");
654*17ab2063SBarry Smith 
655*17ab2063SBarry Smith   if (!mat->assembled) {
656*17ab2063SBarry Smith     ierr = MatAssemblyBegin(matin,FINAL_ASSEMBLY); CHKERRQ(ierr);
657*17ab2063SBarry Smith     ierr = MatAssemblyEnd(matin,FINAL_ASSEMBLY); CHKERRQ(ierr);
658*17ab2063SBarry Smith   }
659*17ab2063SBarry Smith   *nz = mat->i[row+1] - mat->i[row];
660*17ab2063SBarry Smith   if (v) *v = mat->a + mat->i[row] + shift;
661*17ab2063SBarry Smith   if (idx) {
662*17ab2063SBarry Smith     if (*nz) {
663*17ab2063SBarry Smith       itmp = mat->j + mat->i[row] + shift;
664*17ab2063SBarry Smith       *idx = (int *) PETSCMALLOC( (*nz)*sizeof(int) ); CHKPTRQ(*idx);
665*17ab2063SBarry Smith       for ( i=0; i<(*nz); i++ ) {(*idx)[i] = itmp[i] + shift;}
666*17ab2063SBarry Smith     }
667*17ab2063SBarry Smith     else *idx = 0;
668*17ab2063SBarry Smith   }
669*17ab2063SBarry Smith   return 0;
670*17ab2063SBarry Smith }
671*17ab2063SBarry Smith 
672*17ab2063SBarry Smith static int MatRestoreRow_SeqAIJ(Mat matin,int row,int *nz,int **idx,Scalar **v)
673*17ab2063SBarry Smith {
674*17ab2063SBarry Smith   if (idx) {if (*idx) PETSCFREE(*idx);}
675*17ab2063SBarry Smith   return 0;
676*17ab2063SBarry Smith }
677*17ab2063SBarry Smith 
678*17ab2063SBarry Smith static int MatNorm_SeqAIJ(Mat matin,MatNormType type,double *norm)
679*17ab2063SBarry Smith {
680*17ab2063SBarry Smith   Mat_SeqAIJ *mat = (Mat_SeqAIJ *) matin->data;
681*17ab2063SBarry Smith   Scalar  *v = mat->a;
682*17ab2063SBarry Smith   double  sum = 0.0;
683*17ab2063SBarry Smith   int     i, j;
684*17ab2063SBarry Smith    int shift = mat->indexshift;
685*17ab2063SBarry Smith 
686*17ab2063SBarry Smith   if (!mat->assembled)
687*17ab2063SBarry Smith     SETERRQ(1,"MatNorm_SeqAIJ:Cannot compute norm of unassembled matrix");
688*17ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
689*17ab2063SBarry Smith     for (i=0; i<mat->nz; i++ ) {
690*17ab2063SBarry Smith #if defined(PETSC_COMPLEX)
691*17ab2063SBarry Smith       sum += real(conj(*v)*(*v)); v++;
692*17ab2063SBarry Smith #else
693*17ab2063SBarry Smith       sum += (*v)*(*v); v++;
694*17ab2063SBarry Smith #endif
695*17ab2063SBarry Smith     }
696*17ab2063SBarry Smith     *norm = sqrt(sum);
697*17ab2063SBarry Smith   }
698*17ab2063SBarry Smith   else if (type == NORM_1) {
699*17ab2063SBarry Smith     double *tmp;
700*17ab2063SBarry Smith     int    *jj = mat->j;
701*17ab2063SBarry Smith     tmp = (double *) PETSCMALLOC( mat->n*sizeof(double) ); CHKPTRQ(tmp);
702*17ab2063SBarry Smith     PETSCMEMSET(tmp,0,mat->n*sizeof(double));
703*17ab2063SBarry Smith     *norm = 0.0;
704*17ab2063SBarry Smith     for ( j=0; j<mat->nz; j++ ) {
705*17ab2063SBarry Smith #if defined(PETSC_COMPLEX)
706*17ab2063SBarry Smith         tmp[*jj++ + shift] += abs(*v++);
707*17ab2063SBarry Smith #else
708*17ab2063SBarry Smith         tmp[*jj++ + shift] += fabs(*v++);
709*17ab2063SBarry Smith #endif
710*17ab2063SBarry Smith     }
711*17ab2063SBarry Smith     for ( j=0; j<mat->n; j++ ) {
712*17ab2063SBarry Smith       if (tmp[j] > *norm) *norm = tmp[j];
713*17ab2063SBarry Smith     }
714*17ab2063SBarry Smith     PETSCFREE(tmp);
715*17ab2063SBarry Smith   }
716*17ab2063SBarry Smith   else if (type == NORM_INFINITY) {
717*17ab2063SBarry Smith     *norm = 0.0;
718*17ab2063SBarry Smith     for ( j=0; j<mat->m; j++ ) {
719*17ab2063SBarry Smith       v = mat->a + mat->i[j] + shift;
720*17ab2063SBarry Smith       sum = 0.0;
721*17ab2063SBarry Smith       for ( i=0; i<mat->i[j+1]-mat->i[j]; i++ ) {
722*17ab2063SBarry Smith #if defined(PETSC_COMPLEX)
723*17ab2063SBarry Smith         sum += abs(*v); v++;
724*17ab2063SBarry Smith #else
725*17ab2063SBarry Smith         sum += fabs(*v); v++;
726*17ab2063SBarry Smith #endif
727*17ab2063SBarry Smith       }
728*17ab2063SBarry Smith       if (sum > *norm) *norm = sum;
729*17ab2063SBarry Smith     }
730*17ab2063SBarry Smith   }
731*17ab2063SBarry Smith   else {
732*17ab2063SBarry Smith     SETERRQ(1,"MatNorm_SeqAIJ:No support for the two norm yet");
733*17ab2063SBarry Smith   }
734*17ab2063SBarry Smith   return 0;
735*17ab2063SBarry Smith }
736*17ab2063SBarry Smith 
737*17ab2063SBarry Smith static int MatTranspose_SeqAIJ(Mat A,Mat *matout)
738*17ab2063SBarry Smith {
739*17ab2063SBarry Smith   Mat_SeqAIJ *amat = (Mat_SeqAIJ *) A->data;
740*17ab2063SBarry Smith   Mat     tmat;
741*17ab2063SBarry Smith   int     i, ierr, *aj = amat->j, *ai = amat->i, m = amat->m, len, *col;
742*17ab2063SBarry Smith   Scalar  *array = amat->a;
743*17ab2063SBarry Smith    int shift = amat->indexshift;
744*17ab2063SBarry Smith 
745*17ab2063SBarry Smith   if (!matout && m != amat->n) SETERRQ(1,
746*17ab2063SBarry Smith     "MatTranspose_SeqAIJ: Cannot transpose rectangular matrix in place");
747*17ab2063SBarry Smith   col = (int *) PETSCMALLOC((1+amat->n)*sizeof(int)); CHKPTRQ(col);
748*17ab2063SBarry Smith   PETSCMEMSET(col,0,(1+amat->n)*sizeof(int));
749*17ab2063SBarry Smith   if (shift) {
750*17ab2063SBarry Smith     for ( i=0; i<ai[m]-1; i++ ) aj[i] -= 1;
751*17ab2063SBarry Smith   }
752*17ab2063SBarry Smith   for ( i=0; i<ai[m]+shift; i++ ) col[aj[i]] += 1;
753*17ab2063SBarry Smith   ierr = MatCreateSeqAIJ(A->comm,amat->n,m,0,col,&tmat); CHKERRQ(ierr);
754*17ab2063SBarry Smith   PETSCFREE(col);
755*17ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
756*17ab2063SBarry Smith     len = ai[i+1]-ai[i];
757*17ab2063SBarry Smith     ierr = MatSetValues(tmat,len,aj,1,&i,array,INSERT_VALUES); CHKERRQ(ierr);
758*17ab2063SBarry Smith     array += len; aj += len;
759*17ab2063SBarry Smith   }
760*17ab2063SBarry Smith   if (shift) {
761*17ab2063SBarry Smith     for ( i=0; i<ai[m]-1; i++ ) aj[i] += 1;
762*17ab2063SBarry Smith   }
763*17ab2063SBarry Smith 
764*17ab2063SBarry Smith   ierr = MatAssemblyBegin(tmat,FINAL_ASSEMBLY); CHKERRQ(ierr);
765*17ab2063SBarry Smith   ierr = MatAssemblyEnd(tmat,FINAL_ASSEMBLY); CHKERRQ(ierr);
766*17ab2063SBarry Smith 
767*17ab2063SBarry Smith   if (matout) {
768*17ab2063SBarry Smith     *matout = tmat;
769*17ab2063SBarry Smith   } else {
770*17ab2063SBarry Smith     /* This isn't really an in-place transpose ... but free data structures from amat */
771*17ab2063SBarry Smith     PETSCFREE(amat->a);
772*17ab2063SBarry Smith     if (!amat->singlemalloc) {PETSCFREE(amat->i); PETSCFREE(amat->j);}
773*17ab2063SBarry Smith     if (amat->diag) PETSCFREE(amat->diag);
774*17ab2063SBarry Smith     if (amat->ilen) PETSCFREE(amat->ilen);
775*17ab2063SBarry Smith     if (amat->imax) PETSCFREE(amat->imax);
776*17ab2063SBarry Smith     if (amat->solve_work) PETSCFREE(amat->solve_work);
777*17ab2063SBarry Smith     PETSCFREE(amat);
778*17ab2063SBarry Smith     PETSCMEMCPY(A,tmat,sizeof(struct _Mat));
779*17ab2063SBarry Smith     PETSCHEADERDESTROY(tmat);
780*17ab2063SBarry Smith   }
781*17ab2063SBarry Smith   return 0;
782*17ab2063SBarry Smith }
783*17ab2063SBarry Smith 
784*17ab2063SBarry Smith static int MatScale_SeqAIJ(Mat matin,Vec ll,Vec rr)
785*17ab2063SBarry Smith {
786*17ab2063SBarry Smith   Mat_SeqAIJ *mat = (Mat_SeqAIJ *) matin->data;
787*17ab2063SBarry Smith   Scalar  *l,*r,x,*v;
788*17ab2063SBarry Smith   int     i,j,m = mat->m, n = mat->n, M, nz = mat->nz, *jj;
789*17ab2063SBarry Smith    int shift = mat->indexshift;
790*17ab2063SBarry Smith 
791*17ab2063SBarry Smith   if (!mat->assembled)
792*17ab2063SBarry Smith     SETERRQ(1,"MatScale_SeqAIJ:Cannot scale unassembled matrix");
793*17ab2063SBarry Smith   if (ll) {
794*17ab2063SBarry Smith     VecGetArray(ll,&l); VecGetSize(ll,&m);
795*17ab2063SBarry Smith     if (m != mat->m)
796*17ab2063SBarry Smith       SETERRQ(1,"MatScale_SeqAIJ:Left scaling vector wrong length");
797*17ab2063SBarry Smith     v = mat->a;
798*17ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
799*17ab2063SBarry Smith       x = l[i];
800*17ab2063SBarry Smith       M = mat->i[i+1] - mat->i[i];
801*17ab2063SBarry Smith       for ( j=0; j<M; j++ ) { (*v++) *= x;}
802*17ab2063SBarry Smith     }
803*17ab2063SBarry Smith   }
804*17ab2063SBarry Smith   if (rr) {
805*17ab2063SBarry Smith     VecGetArray(rr,&r); VecGetSize(rr,&n);
806*17ab2063SBarry Smith     if (n != mat->n)
807*17ab2063SBarry Smith       SETERRQ(1,"MatScale_SeqAIJ:Right scaling vector wrong length");
808*17ab2063SBarry Smith     v = mat->a; jj = mat->j;
809*17ab2063SBarry Smith     for ( i=0; i<nz; i++ ) {
810*17ab2063SBarry Smith       (*v++) *= r[*jj++ + shift];
811*17ab2063SBarry Smith     }
812*17ab2063SBarry Smith   }
813*17ab2063SBarry Smith   return 0;
814*17ab2063SBarry Smith }
815*17ab2063SBarry Smith 
816*17ab2063SBarry Smith static int MatGetSubMatrix_SeqAIJ(Mat matin,IS isrow,IS iscol,Mat *submat)
817*17ab2063SBarry Smith {
818*17ab2063SBarry Smith   Mat_SeqAIJ *mat = (Mat_SeqAIJ *) matin->data;
819*17ab2063SBarry Smith   int        nznew, *smap, i, k, kstart, kend, ierr, oldcols = mat->n;
820*17ab2063SBarry Smith   int        *irow, *icol, nrows, ncols, *cwork;
821*17ab2063SBarry Smith   Scalar     *vwork;
822*17ab2063SBarry Smith   Mat        newmat;
823*17ab2063SBarry Smith   int        shift = mat->indexshift;
824*17ab2063SBarry Smith 
825*17ab2063SBarry Smith   if (!mat->assembled) SETERRQ(1,
826*17ab2063SBarry Smith     "MatGetSubMatrix_SeqAIJ:Cannot extract submatrix from unassembled matrix");
827*17ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow); CHKERRQ(ierr);
828*17ab2063SBarry Smith   ierr = ISGetIndices(iscol,&icol); CHKERRQ(ierr);
829*17ab2063SBarry Smith   ierr = ISGetSize(isrow,&nrows); CHKERRQ(ierr);
830*17ab2063SBarry Smith   ierr = ISGetSize(iscol,&ncols); CHKERRQ(ierr);
831*17ab2063SBarry Smith 
832*17ab2063SBarry Smith   smap = (int *) PETSCMALLOC((1+oldcols)*sizeof(int)); CHKPTRQ(smap);
833*17ab2063SBarry Smith   cwork = (int *) PETSCMALLOC((1+ncols)*sizeof(int)); CHKPTRQ(cwork);
834*17ab2063SBarry Smith   vwork = (Scalar *) PETSCMALLOC((1+ncols)*sizeof(Scalar)); CHKPTRQ(vwork);
835*17ab2063SBarry Smith   PETSCMEMSET(smap,0,oldcols*sizeof(int));
836*17ab2063SBarry Smith   for ( i=0; i<ncols; i++ ) smap[icol[i]] = i+1;
837*17ab2063SBarry Smith 
838*17ab2063SBarry Smith   /* Create and fill new matrix */
839*17ab2063SBarry Smith   ierr = MatCreateSeqAIJ(matin->comm,nrows,ncols,0,0,&newmat);
840*17ab2063SBarry Smith          CHKERRQ(ierr);
841*17ab2063SBarry Smith   for (i=0; i<nrows; i++) {
842*17ab2063SBarry Smith     nznew = 0;
843*17ab2063SBarry Smith     kstart = mat->i[irow[i]]+shift;
844*17ab2063SBarry Smith     kend = kstart + mat->ilen[irow[i]];
845*17ab2063SBarry Smith     for ( k=kstart; k<kend; k++ ) {
846*17ab2063SBarry Smith       if (smap[mat->j[k]+shift]) {
847*17ab2063SBarry Smith         cwork[nznew]   = smap[mat->j[k]+shift] - 1;
848*17ab2063SBarry Smith         vwork[nznew++] = mat->a[k];
849*17ab2063SBarry Smith       }
850*17ab2063SBarry Smith     }
851*17ab2063SBarry Smith     ierr = MatSetValues(newmat,1,&i,nznew,cwork,vwork,INSERT_VALUES);
852*17ab2063SBarry Smith            CHKERRQ(ierr);
853*17ab2063SBarry Smith   }
854*17ab2063SBarry Smith   ierr = MatAssemblyBegin(newmat,FINAL_ASSEMBLY); CHKERRQ(ierr);
855*17ab2063SBarry Smith   ierr = MatAssemblyEnd(newmat,FINAL_ASSEMBLY); CHKERRQ(ierr);
856*17ab2063SBarry Smith 
857*17ab2063SBarry Smith   /* Free work space */
858*17ab2063SBarry Smith   PETSCFREE(smap); PETSCFREE(cwork); PETSCFREE(vwork);
859*17ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow); CHKERRQ(ierr);
860*17ab2063SBarry Smith   ierr = ISRestoreIndices(iscol,&icol); CHKERRQ(ierr);
861*17ab2063SBarry Smith   *submat = newmat;
862*17ab2063SBarry Smith   return 0;
863*17ab2063SBarry Smith }
864*17ab2063SBarry Smith 
865*17ab2063SBarry Smith static int MatGetSubMatrixInPlace_SeqAIJ(Mat matin,IS rows,IS cols)
866*17ab2063SBarry Smith {
867*17ab2063SBarry Smith   /* Mat_SeqAIJ *mat = (Mat_SeqAIJ *) matin->data; */
868*17ab2063SBarry Smith 
869*17ab2063SBarry Smith   SETERRQ(1,"MatGetSubMatrixInPlace_SeqAIJ:not finished");
870*17ab2063SBarry Smith }
871*17ab2063SBarry Smith 
872*17ab2063SBarry Smith /* -------------------------------------------------------------------*/
873*17ab2063SBarry Smith extern int MatILUFactorSymbolic_SeqAIJ(Mat,IS,IS,double,int,Mat *);
874*17ab2063SBarry Smith extern int MatConvert_SeqAIJ(Mat,MatType,Mat *);
875*17ab2063SBarry Smith static int MatCopyPrivate_SeqAIJ(Mat,Mat *);
876*17ab2063SBarry Smith 
877*17ab2063SBarry Smith static struct _MatOps MatOps = {MatSetValues_SeqAIJ,
878*17ab2063SBarry Smith        MatGetRow_SeqAIJ,MatRestoreRow_SeqAIJ,
879*17ab2063SBarry Smith        MatMult_SeqAIJ,MatMultAdd_SeqAIJ,MatMultTrans_SeqAIJ,MatMultTransAdd_SeqAIJ,
880*17ab2063SBarry Smith        MatSolve_SeqAIJ,MatSolveAdd_SeqAIJ,
881*17ab2063SBarry Smith        MatSolveTrans_SeqAIJ,MatSolveTransAdd_SeqAIJ,
882*17ab2063SBarry Smith        MatLUFactor_SeqAIJ,0,
883*17ab2063SBarry Smith        MatRelax_SeqAIJ,
884*17ab2063SBarry Smith        MatTranspose_SeqAIJ,
885*17ab2063SBarry Smith        MatGetInfo_SeqAIJ,0,
886*17ab2063SBarry Smith        MatGetDiagonal_SeqAIJ,MatScale_SeqAIJ,MatNorm_SeqAIJ,
887*17ab2063SBarry Smith        0,MatAssemblyEnd_SeqAIJ,
888*17ab2063SBarry Smith        MatCompress_SeqAIJ,
889*17ab2063SBarry Smith        MatSetOption_SeqAIJ,MatZeroEntries_SeqAIJ,MatZeroRows_SeqAIJ,
890*17ab2063SBarry Smith        MatGetReordering_SeqAIJ,
891*17ab2063SBarry Smith        MatLUFactorSymbolic_SeqAIJ,MatLUFactorNumeric_SeqAIJ,0,0,
892*17ab2063SBarry Smith        MatGetSize_SeqAIJ,MatGetSize_SeqAIJ,MatGetOwnershipRange_SeqAIJ,
893*17ab2063SBarry Smith        MatILUFactorSymbolic_SeqAIJ,0,
894*17ab2063SBarry Smith        0,0,MatConvert_SeqAIJ,
895*17ab2063SBarry Smith        MatGetSubMatrix_SeqAIJ,MatGetSubMatrixInPlace_SeqAIJ,
896*17ab2063SBarry Smith        MatCopyPrivate_SeqAIJ};
897*17ab2063SBarry Smith 
898*17ab2063SBarry Smith extern int MatUseSuperLU_SeqAIJ(Mat);
899*17ab2063SBarry Smith extern int MatUseEssl_SeqAIJ(Mat);
900*17ab2063SBarry Smith extern int MatUseDXML_SeqAIJ(Mat);
901*17ab2063SBarry Smith 
902*17ab2063SBarry Smith /*@C
903*17ab2063SBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ format
904*17ab2063SBarry Smith    (the default uniprocessor PETSc format).
905*17ab2063SBarry Smith 
906*17ab2063SBarry Smith    Input Parameters:
907*17ab2063SBarry Smith .  comm - MPI communicator, set to MPI_COMM_SELF
908*17ab2063SBarry Smith .  m - number of rows
909*17ab2063SBarry Smith .  n - number of columns
910*17ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
911*17ab2063SBarry Smith .  nzz - number of nonzeros per row or null (possibly different for each row)
912*17ab2063SBarry Smith 
913*17ab2063SBarry Smith    Output Parameter:
914*17ab2063SBarry Smith .  newmat - the matrix
915*17ab2063SBarry Smith 
916*17ab2063SBarry Smith    Notes:
917*17ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
918*17ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
919*17ab2063SBarry Smith    storage.  That is, the stored row and column indices begin at
920*17ab2063SBarry Smith    one, not zero.
921*17ab2063SBarry Smith 
922*17ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
923*17ab2063SBarry Smith    Set both nz and nnz to zero for PETSc to control dynamic memory
924*17ab2063SBarry Smith    allocation.
925*17ab2063SBarry Smith 
926*17ab2063SBarry Smith .keywords: matrix, aij, compressed row, sparse
927*17ab2063SBarry Smith 
928*17ab2063SBarry Smith .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues()
929*17ab2063SBarry Smith @*/
930*17ab2063SBarry Smith int MatCreateSeqAIJ(MPI_Comm comm,int m,int n,int nz,
931*17ab2063SBarry Smith                            int *nnz, Mat *newmat)
932*17ab2063SBarry Smith {
933*17ab2063SBarry Smith   Mat        mat;
934*17ab2063SBarry Smith   Mat_SeqAIJ *aij;
935*17ab2063SBarry Smith   int        i,len,ierr;
936*17ab2063SBarry Smith   *newmat      = 0;
937*17ab2063SBarry Smith   PETSCHEADERCREATE(mat,_Mat,MAT_COOKIE,MATSEQAIJ,comm);
938*17ab2063SBarry Smith   PLogObjectCreate(mat);
939*17ab2063SBarry Smith   mat->data             = (void *) (aij = PETSCNEW(Mat_SeqAIJ)); CHKPTRQ(aij);
940*17ab2063SBarry Smith   PETSCMEMCPY(&mat->ops,&MatOps,sizeof(struct _MatOps));
941*17ab2063SBarry Smith   mat->destroy          = MatDestroy_SeqAIJ;
942*17ab2063SBarry Smith   mat->view             = MatView_SeqAIJ;
943*17ab2063SBarry Smith   mat->factor           = 0;
944*17ab2063SBarry Smith   mat->lupivotthreshold = 1.0;
945*17ab2063SBarry Smith   OptionsGetDouble(0,"-mat_lu_pivotthreshold",&mat->lupivotthreshold);
946*17ab2063SBarry Smith   aij->row              = 0;
947*17ab2063SBarry Smith   aij->col              = 0;
948*17ab2063SBarry Smith   aij->indexshift       = 0;
949*17ab2063SBarry Smith   if (OptionsHasName(0,"-mat_aij_oneindex")) aij->indexshift = -1;
950*17ab2063SBarry Smith 
951*17ab2063SBarry Smith   aij->m       = m;
952*17ab2063SBarry Smith   aij->n       = n;
953*17ab2063SBarry Smith   aij->imax    = (int *) PETSCMALLOC( (m+1)*sizeof(int) ); CHKPTRQ(aij->imax);
954*17ab2063SBarry Smith   if (!nnz) {
955*17ab2063SBarry Smith     if (nz <= 0) nz = 1;
956*17ab2063SBarry Smith     for ( i=0; i<m; i++ ) aij->imax[i] = nz;
957*17ab2063SBarry Smith     nz = nz*m;
958*17ab2063SBarry Smith   }
959*17ab2063SBarry Smith   else {
960*17ab2063SBarry Smith     nz = 0;
961*17ab2063SBarry Smith     for ( i=0; i<m; i++ ) {aij->imax[i] = nnz[i]; nz += nnz[i];}
962*17ab2063SBarry Smith   }
963*17ab2063SBarry Smith 
964*17ab2063SBarry Smith   /* allocate the matrix space */
965*17ab2063SBarry Smith   len     = nz*(sizeof(int) + sizeof(Scalar)) + (aij->m+1)*sizeof(int);
966*17ab2063SBarry Smith   aij->a  = (Scalar *) PETSCMALLOC( len ); CHKPTRQ(aij->a);
967*17ab2063SBarry Smith   aij->j  = (int *) (aij->a + nz);
968*17ab2063SBarry Smith   PETSCMEMSET(aij->j,0,nz*sizeof(int));
969*17ab2063SBarry Smith   aij->i  = aij->j + nz;
970*17ab2063SBarry Smith   aij->singlemalloc = 1;
971*17ab2063SBarry Smith 
972*17ab2063SBarry Smith   aij->i[0] = -aij->indexshift;
973*17ab2063SBarry Smith   for (i=1; i<m+1; i++) {
974*17ab2063SBarry Smith     aij->i[i] = aij->i[i-1] + aij->imax[i-1];
975*17ab2063SBarry Smith   }
976*17ab2063SBarry Smith 
977*17ab2063SBarry Smith   /* aij->ilen will count nonzeros in each row so far. */
978*17ab2063SBarry Smith   aij->ilen = (int *) PETSCMALLOC((m+1)*sizeof(int));
979*17ab2063SBarry Smith   PLogObjectMemory(mat,len + 2*(m+1)*sizeof(int) + sizeof(struct _Mat)
980*17ab2063SBarry Smith                        + sizeof(Mat_SeqAIJ));
981*17ab2063SBarry Smith   for ( i=0; i<aij->m; i++ ) { aij->ilen[i] = 0;}
982*17ab2063SBarry Smith 
983*17ab2063SBarry Smith   aij->nz          = 0;
984*17ab2063SBarry Smith   aij->maxnz       = nz;
985*17ab2063SBarry Smith   aij->sorted      = 0;
986*17ab2063SBarry Smith   aij->roworiented = 1;
987*17ab2063SBarry Smith   aij->nonew       = 0;
988*17ab2063SBarry Smith   aij->diag        = 0;
989*17ab2063SBarry Smith   aij->assembled   = 0;
990*17ab2063SBarry Smith   aij->solve_work  = 0;
991*17ab2063SBarry Smith 
992*17ab2063SBarry Smith   *newmat = mat;
993*17ab2063SBarry Smith   if (OptionsHasName(0,"-mat_aij_superlu")) {
994*17ab2063SBarry Smith     ierr = MatUseSuperLU_SeqAIJ(mat); CHKERRQ(ierr);
995*17ab2063SBarry Smith   }
996*17ab2063SBarry Smith   if (OptionsHasName(0,"-mat_aij_essl")) {
997*17ab2063SBarry Smith     ierr = MatUseEssl_SeqAIJ(mat); CHKERRQ(ierr);
998*17ab2063SBarry Smith   }
999*17ab2063SBarry Smith   if (OptionsHasName(0,"-mat_aij_dxml")) {
1000*17ab2063SBarry Smith     if (!aij->indexshift)
1001*17ab2063SBarry Smith       SETERRQ(1,"MatCreateSeqAIJ: must use -mat_aij_oneindex with -mat_aij_dxml");
1002*17ab2063SBarry Smith     ierr = MatUseDXML_SeqAIJ(mat); CHKERRQ(ierr);
1003*17ab2063SBarry Smith   }
1004*17ab2063SBarry Smith 
1005*17ab2063SBarry Smith   return 0;
1006*17ab2063SBarry Smith }
1007*17ab2063SBarry Smith 
1008*17ab2063SBarry Smith static int MatCopyPrivate_SeqAIJ(Mat matin,Mat *newmat)
1009*17ab2063SBarry Smith {
1010*17ab2063SBarry Smith   Mat     mat;
1011*17ab2063SBarry Smith   Mat_SeqAIJ *aij,*oldmat = (Mat_SeqAIJ *) matin->data;
1012*17ab2063SBarry Smith   int     i,len, m = oldmat->m;
1013*17ab2063SBarry Smith   int     shift = oldmat->indexshift;
1014*17ab2063SBarry Smith   *newmat      = 0;
1015*17ab2063SBarry Smith 
1016*17ab2063SBarry Smith   if (!oldmat->assembled)
1017*17ab2063SBarry Smith     SETERRQ(1,"MatCopyPrivate_SeqAIJ:Cannot copy unassembled matrix");
1018*17ab2063SBarry Smith   PETSCHEADERCREATE(mat,_Mat,MAT_COOKIE,MATSEQAIJ,matin->comm);
1019*17ab2063SBarry Smith   PLogObjectCreate(mat);
1020*17ab2063SBarry Smith   mat->data       = (void *) (aij = PETSCNEW(Mat_SeqAIJ)); CHKPTRQ(aij);
1021*17ab2063SBarry Smith   PETSCMEMCPY(&mat->ops,&MatOps,sizeof(struct _MatOps));
1022*17ab2063SBarry Smith   mat->destroy    = MatDestroy_SeqAIJ;
1023*17ab2063SBarry Smith   mat->view       = MatView_SeqAIJ;
1024*17ab2063SBarry Smith   mat->factor     = matin->factor;
1025*17ab2063SBarry Smith   aij->row        = 0;
1026*17ab2063SBarry Smith   aij->col        = 0;
1027*17ab2063SBarry Smith   aij->indexshift = shift;
1028*17ab2063SBarry Smith 
1029*17ab2063SBarry Smith   aij->m          = oldmat->m;
1030*17ab2063SBarry Smith   aij->n          = oldmat->n;
1031*17ab2063SBarry Smith 
1032*17ab2063SBarry Smith   aij->imax       = (int *) PETSCMALLOC((m+1)*sizeof(int)); CHKPTRQ(aij->imax);
1033*17ab2063SBarry Smith   aij->ilen       = (int *) PETSCMALLOC((m+1)*sizeof(int)); CHKPTRQ(aij->ilen);
1034*17ab2063SBarry Smith   for ( i=0; i<m; i++ ) {
1035*17ab2063SBarry Smith     aij->imax[i] = oldmat->imax[i];
1036*17ab2063SBarry Smith     aij->ilen[i] = oldmat->ilen[i];
1037*17ab2063SBarry Smith   }
1038*17ab2063SBarry Smith 
1039*17ab2063SBarry Smith   /* allocate the matrix space */
1040*17ab2063SBarry Smith   aij->singlemalloc = 1;
1041*17ab2063SBarry Smith   len     = (m+1)*sizeof(int)+(oldmat->i[m])*(sizeof(Scalar)+sizeof(int));
1042*17ab2063SBarry Smith   aij->a  = (Scalar *) PETSCMALLOC( len ); CHKPTRQ(aij->a);
1043*17ab2063SBarry Smith   aij->j  = (int *) (aij->a + oldmat->i[m] + shift);
1044*17ab2063SBarry Smith   aij->i  = aij->j + oldmat->i[m] + shift;
1045*17ab2063SBarry Smith   PETSCMEMCPY(aij->i,oldmat->i,(m+1)*sizeof(int));
1046*17ab2063SBarry Smith   if (m > 0) {
1047*17ab2063SBarry Smith     PETSCMEMCPY(aij->j,oldmat->j,(oldmat->i[m]+shift)*sizeof(int));
1048*17ab2063SBarry Smith     PETSCMEMCPY(aij->a,oldmat->a,(oldmat->i[m]+shift)*sizeof(Scalar));
1049*17ab2063SBarry Smith   }
1050*17ab2063SBarry Smith 
1051*17ab2063SBarry Smith   PLogObjectMemory(mat,len + 2*(m+1)*sizeof(int) + sizeof(struct _Mat)
1052*17ab2063SBarry Smith                        + sizeof(Mat_SeqAIJ));
1053*17ab2063SBarry Smith   aij->sorted      = oldmat->sorted;
1054*17ab2063SBarry Smith   aij->roworiented = oldmat->roworiented;
1055*17ab2063SBarry Smith   aij->nonew       = oldmat->nonew;
1056*17ab2063SBarry Smith 
1057*17ab2063SBarry Smith   if (oldmat->diag) {
1058*17ab2063SBarry Smith     aij->diag = (int *) PETSCMALLOC( (m+1)*sizeof(int) ); CHKPTRQ(aij->diag);
1059*17ab2063SBarry Smith     PLogObjectMemory(mat,(m+1)*sizeof(int));
1060*17ab2063SBarry Smith     for ( i=0; i<m; i++ ) {
1061*17ab2063SBarry Smith       aij->diag[i] = oldmat->diag[i];
1062*17ab2063SBarry Smith     }
1063*17ab2063SBarry Smith   }
1064*17ab2063SBarry Smith   else aij->diag        = 0;
1065*17ab2063SBarry Smith   aij->assembled        = 1;
1066*17ab2063SBarry Smith   aij->nz               = oldmat->nz;
1067*17ab2063SBarry Smith   aij->maxnz            = oldmat->maxnz;
1068*17ab2063SBarry Smith   aij->solve_work       = 0;
1069*17ab2063SBarry Smith   *newmat = mat;
1070*17ab2063SBarry Smith   return 0;
1071*17ab2063SBarry Smith }
1072*17ab2063SBarry Smith 
1073*17ab2063SBarry Smith #include "sysio.h"
1074*17ab2063SBarry Smith 
1075*17ab2063SBarry Smith int MatLoad_SeqAIJ(Viewer bview,MatType type,Mat *newmat)
1076*17ab2063SBarry Smith {
1077*17ab2063SBarry Smith   Mat_SeqAIJ   *aij;
1078*17ab2063SBarry Smith   Mat          mat;
1079*17ab2063SBarry Smith   int          i, nz, ierr;
1080*17ab2063SBarry Smith   int          fd;
1081*17ab2063SBarry Smith   PetscObject  vobj = (PetscObject) bview;
1082*17ab2063SBarry Smith   MPI_Comm     comm = vobj->comm;
1083*17ab2063SBarry Smith   int          header[4],numtid,*rowlengths = 0,M,N;
1084*17ab2063SBarry Smith   int          shift;
1085*17ab2063SBarry Smith 
1086*17ab2063SBarry Smith   MPI_Comm_size(comm,&numtid);
1087*17ab2063SBarry Smith   if (numtid > 1) SETERRQ(1,"MatLoad_SeqAIJ: view must have one processor");
1088*17ab2063SBarry Smith   ierr = ViewerFileGetDescriptor_Private(bview,&fd); CHKERRQ(ierr);
1089*17ab2063SBarry Smith   ierr = SYRead(fd,(char *)header,4*sizeof(int),SYINT); CHKERRQ(ierr);
1090*17ab2063SBarry Smith   if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_SeqAIJ: not matrix object");
1091*17ab2063SBarry Smith   M = header[1]; N = header[2]; nz = header[3];
1092*17ab2063SBarry Smith 
1093*17ab2063SBarry Smith   /* read in row lengths */
1094*17ab2063SBarry Smith   rowlengths = (int*) PETSCMALLOC( M*sizeof(int) ); CHKPTRQ(rowlengths);
1095*17ab2063SBarry Smith   ierr = SYRead(fd,(char *)rowlengths,M*sizeof(int),SYINT); CHKERRQ(ierr);
1096*17ab2063SBarry Smith 
1097*17ab2063SBarry Smith   /* create our matrix */
1098*17ab2063SBarry Smith   ierr = MatCreateSeqAIJ(comm,M,N,0,rowlengths,newmat); CHKERRQ(ierr);
1099*17ab2063SBarry Smith   mat = *newmat;
1100*17ab2063SBarry Smith   aij = (Mat_SeqAIJ *) mat->data;
1101*17ab2063SBarry Smith   shift = aij->indexshift;
1102*17ab2063SBarry Smith 
1103*17ab2063SBarry Smith   /* read in column indices and adjust for Fortran indexing*/
1104*17ab2063SBarry Smith   ierr = SYRead(fd,(char *)aij->j,nz*sizeof(int),SYINT); CHKERRQ(ierr);
1105*17ab2063SBarry Smith   if (shift) {
1106*17ab2063SBarry Smith     for ( i=0; i<nz; i++ ) {
1107*17ab2063SBarry Smith       aij->j[i] += 1;
1108*17ab2063SBarry Smith     }
1109*17ab2063SBarry Smith   }
1110*17ab2063SBarry Smith 
1111*17ab2063SBarry Smith   /* read in nonzero values */
1112*17ab2063SBarry Smith   ierr = SYRead(fd,(char *)aij->a,nz*sizeof(Scalar),SYSCALAR); CHKERRQ(ierr);
1113*17ab2063SBarry Smith 
1114*17ab2063SBarry Smith   /* set matrix "i" values */
1115*17ab2063SBarry Smith   aij->i[0] = -shift;
1116*17ab2063SBarry Smith   for ( i=1; i<= M; i++ ) {
1117*17ab2063SBarry Smith     aij->i[i]      = aij->i[i-1] + rowlengths[i-1];
1118*17ab2063SBarry Smith     aij->ilen[i-1] = rowlengths[i-1];
1119*17ab2063SBarry Smith   }
1120*17ab2063SBarry Smith   PETSCFREE(rowlengths);
1121*17ab2063SBarry Smith 
1122*17ab2063SBarry Smith   ierr = MatAssemblyBegin(mat,FINAL_ASSEMBLY); CHKERRQ(ierr);
1123*17ab2063SBarry Smith   ierr = MatAssemblyEnd(mat,FINAL_ASSEMBLY); CHKERRQ(ierr);
1124*17ab2063SBarry Smith   return 0;
1125*17ab2063SBarry Smith }
1126*17ab2063SBarry Smith 
1127*17ab2063SBarry Smith 
1128*17ab2063SBarry Smith 
1129