xref: /petsc/src/mat/impls/aij/mpi/mpiaij.c (revision 8a729477f87d61ca2b7a26a4d05306c0e952a6e5)
1*8a729477SBarry Smith 
2*8a729477SBarry Smith #include "aij.h"
3*8a729477SBarry Smith #include "vec/vecimpl.h"
4*8a729477SBarry Smith #include "inline/spops.h"
5*8a729477SBarry Smith 
6*8a729477SBarry Smith int SpToSymmetricIJ(Matiaij*,int**,int**);
7*8a729477SBarry Smith int SpOrderND(int,int*,int*,int*);
8*8a729477SBarry Smith int SpOrder1WD(int,int*,int*,int*);
9*8a729477SBarry Smith int SpOrderQMD(int,int*,int*,int*);
10*8a729477SBarry Smith int SpOrderRCM(int,int*,int*,int*);
11*8a729477SBarry Smith 
12*8a729477SBarry Smith static int MatAIJreorder(Mat mat,int type,IS *rperm, IS *cperm)
13*8a729477SBarry Smith {
14*8a729477SBarry Smith   Matiaij *aij = (Matiaij *) mat->data;
15*8a729477SBarry Smith   int     i, ierr, *ia, *ja, *perma;
16*8a729477SBarry Smith 
17*8a729477SBarry Smith   perma = (int *) MALLOC( aij->n*sizeof(int) ); CHKPTR(perma);
18*8a729477SBarry Smith 
19*8a729477SBarry Smith   if (ierr = SpToSymmetricIJ( aij, &ia, &ja )) SETERR(ierr,0);
20*8a729477SBarry Smith 
21*8a729477SBarry Smith   if (type == ORDER_NATURAL) {
22*8a729477SBarry Smith     for ( i=0; i<aij->n; i++ ) perma[i] = i;
23*8a729477SBarry Smith   }
24*8a729477SBarry Smith   else if (type == ORDER_ND) {
25*8a729477SBarry Smith     ierr = SpOrderND( aij->n, ia, ja, perma );
26*8a729477SBarry Smith   }
27*8a729477SBarry Smith   else if (type == ORDER_1WD) {
28*8a729477SBarry Smith     ierr = SpOrder1WD( aij->n, ia, ja, perma );
29*8a729477SBarry Smith   }
30*8a729477SBarry Smith   else if (type == ORDER_RCM) {
31*8a729477SBarry Smith     ierr = SpOrderRCM( aij->n, ia, ja, perma );
32*8a729477SBarry Smith   }
33*8a729477SBarry Smith   else if (type == ORDER_QMD) {
34*8a729477SBarry Smith     ierr = SpOrderQMD( aij->n, ia, ja, perma );
35*8a729477SBarry Smith   }
36*8a729477SBarry Smith   else SETERR(1,"Cannot performing ordering requested");
37*8a729477SBarry Smith   if (ierr) SETERR(ierr,0);
38*8a729477SBarry Smith   FREE(ia); FREE(ja);
39*8a729477SBarry Smith 
40*8a729477SBarry Smith   if (ierr = ISCreateSequential(aij->n,perma,rperm)) SETERR(ierr,0);
41*8a729477SBarry Smith   ISSetPermutation(*rperm);
42*8a729477SBarry Smith   FREE(perma);
43*8a729477SBarry Smith   *cperm = *rperm; /* so far all permutations are symmetric.*/
44*8a729477SBarry Smith   return 0;
45*8a729477SBarry Smith }
46*8a729477SBarry Smith 
47*8a729477SBarry Smith 
48*8a729477SBarry Smith #define CHUNCKSIZE 5
49*8a729477SBarry Smith 
50*8a729477SBarry Smith /* This version has row oriented v  */
51*8a729477SBarry Smith static int MatiAIJAddValues(Mat matin,Scalar *v,int m,int *idxm,int n,
52*8a729477SBarry Smith                             int *idxn)
53*8a729477SBarry Smith {
54*8a729477SBarry Smith   Matiaij *mat = (Matiaij *) matin->data;
55*8a729477SBarry Smith   int    *rp,k,a,b,t,ii,row,nrow,i,col,l,rmax, N, sorted = mat->sorted;
56*8a729477SBarry Smith   int    *imax = mat->imax, *ai = mat->i, *ailen = mat->ilen;
57*8a729477SBarry Smith   int    *aj = mat->j, nonew = mat->nonew;
58*8a729477SBarry Smith   Scalar *ap,value, *aa = mat->a;
59*8a729477SBarry Smith 
60*8a729477SBarry Smith   for ( k=0; k<m; k++ ) { /* loop over added rows */
61*8a729477SBarry Smith     row  = idxm[k];   rp   = aj + ai[row] - 1; ap = aa + ai[row] - 1;
62*8a729477SBarry Smith     rmax = imax[row]; nrow = ailen[row];
63*8a729477SBarry Smith     a = 0;
64*8a729477SBarry Smith     for ( l=0; l<n; l++ ) { /* loop over added columns */
65*8a729477SBarry Smith       col = idxn[l] + 1; value = *v++;
66*8a729477SBarry Smith       if (nrow) {
67*8a729477SBarry Smith         if (!sorted) a = 0; b = nrow;
68*8a729477SBarry Smith         while (b-a > 5) {
69*8a729477SBarry Smith           t = (b+a)/2;
70*8a729477SBarry Smith           if (rp[t] > col) b = t;
71*8a729477SBarry Smith           else             a = t;
72*8a729477SBarry Smith         }
73*8a729477SBarry Smith         for ( i=a; i<b; i++ ) {
74*8a729477SBarry Smith           if (rp[i] > col) break;
75*8a729477SBarry Smith           if (rp[i] == col) {ap[i] += value;  goto noinsert;}
76*8a729477SBarry Smith         }
77*8a729477SBarry Smith         if (nonew) goto noinsert;
78*8a729477SBarry Smith         if (nrow >= rmax) {
79*8a729477SBarry Smith           /* there is no extra room in row, therefore enlarge */
80*8a729477SBarry Smith           int    new_nz = ai[mat->m] + CHUNCKSIZE,len,*new_i,*new_j;
81*8a729477SBarry Smith           Scalar *new_a;
82*8a729477SBarry Smith           fprintf(stderr,"Warning, enlarging matrix storage \n");
83*8a729477SBarry Smith 
84*8a729477SBarry Smith           /* malloc new storage space */
85*8a729477SBarry Smith           len     = new_nz*(sizeof(int)+sizeof(Scalar))+(mat->m+1)*sizeof(int);
86*8a729477SBarry Smith           new_a  = (Scalar *) MALLOC( len ); CHKPTR(new_a);
87*8a729477SBarry Smith           new_j  = (int *) (new_a + new_nz);
88*8a729477SBarry Smith           new_i  = new_j + new_nz;
89*8a729477SBarry Smith 
90*8a729477SBarry Smith           /* copy over old data into new slots */
91*8a729477SBarry Smith           for ( ii=0; ii<row+1; ii++ ) {new_i[ii] = ai[ii];}
92*8a729477SBarry Smith           for ( ii=row+1; ii<mat->m+1; ii++ ) {new_i[ii] = ai[ii]+CHUNCKSIZE;}
93*8a729477SBarry Smith           MEMCPY(new_j,aj,(ai[row]+nrow-1)*sizeof(int));
94*8a729477SBarry Smith           len = (new_nz - CHUNCKSIZE - ai[row] - nrow + 1);
95*8a729477SBarry Smith           MEMCPY(new_j+ai[row]-1+nrow+CHUNCKSIZE,aj+ai[row]-1+nrow,
96*8a729477SBarry Smith                                                            len*sizeof(int));
97*8a729477SBarry Smith           MEMCPY(new_a,aa,(ai[row]+nrow-1)*sizeof(Scalar));
98*8a729477SBarry Smith           MEMCPY(new_a+ai[row]-1+nrow+CHUNCKSIZE,aa+ai[row]-1+nrow,
99*8a729477SBarry Smith                                                          len*sizeof(Scalar));
100*8a729477SBarry Smith           /* free up old matrix storage */
101*8a729477SBarry Smith           FREE(mat->a); if (!mat->singlemalloc) {FREE(mat->i);FREE(mat->j);}
102*8a729477SBarry Smith           aa = mat->a = new_a; ai = mat->i = new_i; aj = mat->j = new_j;
103*8a729477SBarry Smith           mat->singlemalloc = 1;
104*8a729477SBarry Smith 
105*8a729477SBarry Smith           rp   = aj + ai[row] - 1; ap = aa + ai[row] - 1;
106*8a729477SBarry Smith           rmax = imax[row] = imax[row] + CHUNCKSIZE;
107*8a729477SBarry Smith           mat->mem += CHUNCKSIZE*(sizeof(int) + sizeof(Scalar));
108*8a729477SBarry Smith         }
109*8a729477SBarry Smith         N = nrow++ - 1; mat->nz++;
110*8a729477SBarry Smith         /* this has too many shifts here; but alternative was slower*/
111*8a729477SBarry Smith         for ( ii=N; ii>=i; ii-- ) {/* shift values up*/
112*8a729477SBarry Smith           rp[ii+1] = rp[ii];
113*8a729477SBarry Smith           ap[ii+1] = ap[ii];
114*8a729477SBarry Smith         }
115*8a729477SBarry Smith         rp[i] = col;
116*8a729477SBarry Smith         ap[i] = value;
117*8a729477SBarry Smith         noinsert:;
118*8a729477SBarry Smith         a = i + 1;
119*8a729477SBarry Smith       }
120*8a729477SBarry Smith       else {
121*8a729477SBarry Smith         ap[0] = value; rp[0] = col; nrow++; a = 1;
122*8a729477SBarry Smith       }
123*8a729477SBarry Smith     }
124*8a729477SBarry Smith     ailen[row] = nrow;
125*8a729477SBarry Smith   }
126*8a729477SBarry Smith   return 0;
127*8a729477SBarry Smith }
128*8a729477SBarry Smith 
129*8a729477SBarry Smith static int MatiAIJview(PetscObject obj,Viewer ptr)
130*8a729477SBarry Smith {
131*8a729477SBarry Smith   Mat     aijin = (Mat) obj;
132*8a729477SBarry Smith   Matiaij *aij = (Matiaij *) aijin->data;
133*8a729477SBarry Smith   int i,j;
134*8a729477SBarry Smith   for ( i=0; i<aij->m; i++ ) {
135*8a729477SBarry Smith     printf("row %d:",i);
136*8a729477SBarry Smith     for ( j=aij->i[i]-1; j<aij->i[i+1]-1; j++ ) {
137*8a729477SBarry Smith #if defined(PETSC_COMPLEX)
138*8a729477SBarry Smith       printf(" %d %g + %g i",aij->j[j]-1,real(aij->a[j]),imag(aij->a[j]));
139*8a729477SBarry Smith #else
140*8a729477SBarry Smith       printf(" %d %g ",aij->j[j]-1,aij->a[j]);
141*8a729477SBarry Smith #endif
142*8a729477SBarry Smith     }
143*8a729477SBarry Smith     printf("\n");
144*8a729477SBarry Smith   }
145*8a729477SBarry Smith   return 0;
146*8a729477SBarry Smith }
147*8a729477SBarry Smith 
148*8a729477SBarry Smith static int MatiAIJEndAssemble(Mat aijin)
149*8a729477SBarry Smith {
150*8a729477SBarry Smith   Matiaij *aij = (Matiaij *) aijin->data;
151*8a729477SBarry Smith   int    shift = 0,i,j,*ai = aij->i, *aj = aij->j, *imax = aij->imax;
152*8a729477SBarry Smith   int    m = aij->m, *ip, N, *ailen = aij->ilen;
153*8a729477SBarry Smith   Scalar *a = aij->a, *ap;
154*8a729477SBarry Smith 
155*8a729477SBarry Smith   for ( i=1; i<m; i++ ) {
156*8a729477SBarry Smith     shift += imax[i-1] - ailen[i-1];
157*8a729477SBarry Smith     if (shift) {
158*8a729477SBarry Smith       ip = aj + ai[i] - 1; ap = a + ai[i] - 1;
159*8a729477SBarry Smith       N = ailen[i];
160*8a729477SBarry Smith       for ( j=0; j<N; j++ ) {
161*8a729477SBarry Smith         ip[j-shift] = ip[j];
162*8a729477SBarry Smith         ap[j-shift] = ap[j];
163*8a729477SBarry Smith       }
164*8a729477SBarry Smith     }
165*8a729477SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
166*8a729477SBarry Smith   }
167*8a729477SBarry Smith   shift += imax[m-1] - ailen[m-1];
168*8a729477SBarry Smith   ai[m] = ai[m-1] + ailen[m-1];
169*8a729477SBarry Smith   FREE(aij->imax);
170*8a729477SBarry Smith   FREE(aij->ilen);
171*8a729477SBarry Smith   aij->mem -= 2*(aij->m)*sizeof(int);
172*8a729477SBarry Smith   return 0;
173*8a729477SBarry Smith }
174*8a729477SBarry Smith 
175*8a729477SBarry Smith static int MatiAIJzeroentries(Mat mat)
176*8a729477SBarry Smith {
177*8a729477SBarry Smith   Matiaij *aij = (Matiaij *) mat->data;
178*8a729477SBarry Smith   Scalar  *a = aij->a;
179*8a729477SBarry Smith   int     i,n = aij->i[aij->m]-1;
180*8a729477SBarry Smith   for ( i=0; i<n; i++ ) a[i] = 0.0;
181*8a729477SBarry Smith   return 0;
182*8a729477SBarry Smith 
183*8a729477SBarry Smith }
184*8a729477SBarry Smith static int MatiAIJdestroy(PetscObject obj)
185*8a729477SBarry Smith {
186*8a729477SBarry Smith   Mat mat = (Mat) obj;
187*8a729477SBarry Smith   Matiaij *aij = (Matiaij *) mat->data;
188*8a729477SBarry Smith   FREE(aij->a);
189*8a729477SBarry Smith   if (!aij->singlemalloc) {FREE(aij->i); FREE(aij->j);}
190*8a729477SBarry Smith   FREE(aij); FREE(mat);
191*8a729477SBarry Smith   return 0;
192*8a729477SBarry Smith }
193*8a729477SBarry Smith 
194*8a729477SBarry Smith static int MatiAIJCompress(Mat aijin)
195*8a729477SBarry Smith {
196*8a729477SBarry Smith   return 0;
197*8a729477SBarry Smith }
198*8a729477SBarry Smith 
199*8a729477SBarry Smith static int MatiAIJinsopt(Mat aijin,int op)
200*8a729477SBarry Smith {
201*8a729477SBarry Smith   Matiaij *aij = (Matiaij *) aijin->data;
202*8a729477SBarry Smith   if      (op == ROW_ORIENTED)              aij->roworiented = 1;
203*8a729477SBarry Smith   else if (op == COLUMN_ORIENTED)           aij->roworiented = 0;
204*8a729477SBarry Smith   else if (op == COLUMNS_SORTED)            aij->sorted      = 1;
205*8a729477SBarry Smith   /* doesn't care about sorted rows */
206*8a729477SBarry Smith   else if (op == NO_NEW_NONZERO_LOCATIONS)  aij->nonew = 1;
207*8a729477SBarry Smith   else if (op == YES_NEW_NONZERO_LOCATIONS) aij->nonew = 0;
208*8a729477SBarry Smith 
209*8a729477SBarry Smith   if (op == COLUMN_ORIENTED) SETERR(1,"Column oriented input not supported");
210*8a729477SBarry Smith   return 0;
211*8a729477SBarry Smith }
212*8a729477SBarry Smith 
213*8a729477SBarry Smith static int MatiAIJgetdiag(Mat aijin,Vec v)
214*8a729477SBarry Smith {
215*8a729477SBarry Smith   Matiaij *aij = (Matiaij *) aijin->data;
216*8a729477SBarry Smith   int    i,j, n;
217*8a729477SBarry Smith   Scalar *x, zero = 0.0;
218*8a729477SBarry Smith   CHKTYPE(v,SEQVECTOR);
219*8a729477SBarry Smith   VecSet(&zero,v);
220*8a729477SBarry Smith   VecGetArray(v,&x); VecGetSize(v,&n);
221*8a729477SBarry Smith   if (n != aij->m) SETERR(1,"Nonconforming matrix and vector");
222*8a729477SBarry Smith   for ( i=0; i<aij->m; i++ ) {
223*8a729477SBarry Smith     for ( j=aij->i[i]-1; j<aij->i[i+1]-1; j++ ) {
224*8a729477SBarry Smith       if (aij->j[j]-1 == i) {
225*8a729477SBarry Smith         x[i] = aij->a[j];
226*8a729477SBarry Smith         break;
227*8a729477SBarry Smith       }
228*8a729477SBarry Smith     }
229*8a729477SBarry Smith   }
230*8a729477SBarry Smith   return 0;
231*8a729477SBarry Smith }
232*8a729477SBarry Smith 
233*8a729477SBarry Smith /* -------------------------------------------------------*/
234*8a729477SBarry Smith /* Should check that shapes of vectors and matrices match */
235*8a729477SBarry Smith /* -------------------------------------------------------*/
236*8a729477SBarry Smith static int MatiAIJmulttrans(Mat aijin,Vec xx,Vec yy)
237*8a729477SBarry Smith {
238*8a729477SBarry Smith   Matiaij *aij = (Matiaij *) aijin->data;
239*8a729477SBarry Smith   Scalar  *x, *y, *v, alpha;
240*8a729477SBarry Smith   int     m = aij->m, n, i, *idx;
241*8a729477SBarry Smith   CHKTYPE(xx,SEQVECTOR);CHKTYPE(yy,SEQVECTOR);
242*8a729477SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
243*8a729477SBarry Smith   MEMSET(y,0,aij->n*sizeof(Scalar));
244*8a729477SBarry Smith   y--; /* shift for Fortran start by 1 indexing */
245*8a729477SBarry Smith   for ( i=0; i<m; i++ ) {
246*8a729477SBarry Smith     idx   = aij->j + aij->i[i] - 1;
247*8a729477SBarry Smith     v     = aij->a + aij->i[i] - 1;
248*8a729477SBarry Smith     n     = aij->i[i+1] - aij->i[i];
249*8a729477SBarry Smith     alpha = x[i];
250*8a729477SBarry Smith     /* should inline */
251*8a729477SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
252*8a729477SBarry Smith   }
253*8a729477SBarry Smith   return 0;
254*8a729477SBarry Smith }
255*8a729477SBarry Smith static int MatiAIJmulttransadd(Mat aijin,Vec xx,Vec zz,Vec yy)
256*8a729477SBarry Smith {
257*8a729477SBarry Smith   Matiaij *aij = (Matiaij *) aijin->data;
258*8a729477SBarry Smith   Scalar  *x, *y, *z, *v, alpha;
259*8a729477SBarry Smith   int     m = aij->m, n, i, *idx;
260*8a729477SBarry Smith   CHKTYPE(xx,SEQVECTOR);CHKTYPE(yy,SEQVECTOR);
261*8a729477SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
262*8a729477SBarry Smith   if (zz != yy) VecCopy(zz,yy);
263*8a729477SBarry Smith   y--; /* shift for Fortran start by 1 indexing */
264*8a729477SBarry Smith   for ( i=0; i<m; i++ ) {
265*8a729477SBarry Smith     idx   = aij->j + aij->i[i] - 1;
266*8a729477SBarry Smith     v     = aij->a + aij->i[i] - 1;
267*8a729477SBarry Smith     n     = aij->i[i+1] - aij->i[i];
268*8a729477SBarry Smith     alpha = x[i];
269*8a729477SBarry Smith     /* should inline */
270*8a729477SBarry Smith     while (n-->0) {y[*idx++] += alpha * *v++;}
271*8a729477SBarry Smith   }
272*8a729477SBarry Smith   return 0;
273*8a729477SBarry Smith }
274*8a729477SBarry Smith 
275*8a729477SBarry Smith static int MatiAIJmult(Mat aijin,Vec xx,Vec yy)
276*8a729477SBarry Smith {
277*8a729477SBarry Smith   Matiaij *aij = (Matiaij *) aijin->data;
278*8a729477SBarry Smith   Scalar  *x, *y, *v, sum;
279*8a729477SBarry Smith   int     m = aij->m, n, i, *idx;
280*8a729477SBarry Smith   CHKTYPE(xx,SEQVECTOR);CHKTYPE(yy,SEQVECTOR);
281*8a729477SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
282*8a729477SBarry Smith   x--; /* shift for Fortran start by 1 indexing */
283*8a729477SBarry Smith   for ( i=0; i<m; i++ ) {
284*8a729477SBarry Smith     idx  = aij->j + aij->i[i] - 1;
285*8a729477SBarry Smith     v    = aij->a + aij->i[i] - 1;
286*8a729477SBarry Smith     n    = aij->i[i+1] - aij->i[i];
287*8a729477SBarry Smith     sum  = 0.0;
288*8a729477SBarry Smith     SPARSEDENSEDOT(sum,x,v,idx,n);
289*8a729477SBarry Smith     y[i] = sum;
290*8a729477SBarry Smith   }
291*8a729477SBarry Smith   return 0;
292*8a729477SBarry Smith }
293*8a729477SBarry Smith 
294*8a729477SBarry Smith static int MatiAIJmultadd(Mat aijin,Vec xx,Vec yy,Vec zz)
295*8a729477SBarry Smith {
296*8a729477SBarry Smith   Matiaij *aij = (Matiaij *) aijin->data;
297*8a729477SBarry Smith   Scalar  *x, *y, *z, *v, sum;
298*8a729477SBarry Smith   int     m = aij->m, n, i, *idx;
299*8a729477SBarry Smith   CHKTYPE(xx,SEQVECTOR);CHKTYPE(yy,SEQVECTOR); CHKTYPE(zz,SEQVECTOR);
300*8a729477SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z);
301*8a729477SBarry Smith   x--; /* shift for Fortran start by 1 indexing */
302*8a729477SBarry Smith   for ( i=0; i<m; i++ ) {
303*8a729477SBarry Smith     idx  = aij->j + aij->i[i] - 1;
304*8a729477SBarry Smith     v    = aij->a + aij->i[i] - 1;
305*8a729477SBarry Smith     n    = aij->i[i+1] - aij->i[i];
306*8a729477SBarry Smith     sum  = y[i];
307*8a729477SBarry Smith     SPARSEDENSEDOT(sum,x,v,idx,n);
308*8a729477SBarry Smith     y[i] = sum;
309*8a729477SBarry Smith   }
310*8a729477SBarry Smith   return 0;
311*8a729477SBarry Smith }
312*8a729477SBarry Smith 
313*8a729477SBarry Smith /*
314*8a729477SBarry Smith      Adds diagonal pointers to sparse matrix structure.
315*8a729477SBarry Smith */
316*8a729477SBarry Smith 
317*8a729477SBarry Smith static int MatiAIJmarkdiag(Matiaij  *aij)
318*8a729477SBarry Smith {
319*8a729477SBarry Smith   int    i,j, n, *diag;;
320*8a729477SBarry Smith   diag = (int *) MALLOC( aij->m*sizeof(int)); CHKPTR(diag);
321*8a729477SBarry Smith   for ( i=0; i<aij->m; i++ ) {
322*8a729477SBarry Smith     for ( j=aij->i[i]-1; j<aij->i[i+1]-1; j++ ) {
323*8a729477SBarry Smith       if (aij->j[j]-1 == i) {
324*8a729477SBarry Smith         diag[i] = j + 1;
325*8a729477SBarry Smith         break;
326*8a729477SBarry Smith       }
327*8a729477SBarry Smith     }
328*8a729477SBarry Smith   }
329*8a729477SBarry Smith   aij->diag = diag;
330*8a729477SBarry Smith   return 0;
331*8a729477SBarry Smith }
332*8a729477SBarry Smith 
333*8a729477SBarry Smith static int MatiAIJrelax(Mat matin,Vec bb,double omega,int flag,IS is,
334*8a729477SBarry Smith                         int its,Vec xx)
335*8a729477SBarry Smith {
336*8a729477SBarry Smith   Matiaij *mat = (Matiaij *) matin->data;
337*8a729477SBarry Smith   Scalar *x, *b, zero = 0.0, d, *xs, sum, *v = mat->a;
338*8a729477SBarry Smith   int    ierr,one = 1, tmp, *idx, *diag;
339*8a729477SBarry Smith   int    n = mat->n, m = mat->m, i, j;
340*8a729477SBarry Smith 
341*8a729477SBarry Smith   if (is) SETERR(1,"No support for ordering in relaxation");
342*8a729477SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
343*8a729477SBarry Smith     if (ierr = VecSet(&zero,xx)) return ierr;
344*8a729477SBarry Smith   }
345*8a729477SBarry Smith   VecGetArray(xx,&x); VecGetArray(bb,&b);
346*8a729477SBarry Smith   if (!mat->diag) {if (ierr = MatiAIJmarkdiag(mat)) return ierr;}
347*8a729477SBarry Smith   diag = mat->diag;
348*8a729477SBarry Smith   xs = x - 1; /* shifted by one for index start of a or mat->j*/
349*8a729477SBarry Smith   while (its--) {
350*8a729477SBarry Smith     if (flag & SOR_FORWARD_SWEEP){
351*8a729477SBarry Smith       for ( i=0; i<m; i++ ) {
352*8a729477SBarry Smith         d    = mat->a[diag[i]-1];
353*8a729477SBarry Smith         n    = mat->i[i+1] - mat->i[i];
354*8a729477SBarry Smith         idx  = mat->j + mat->i[i] - 1;
355*8a729477SBarry Smith         v    = mat->a + mat->i[i] - 1;
356*8a729477SBarry Smith         sum  = b[i];
357*8a729477SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
358*8a729477SBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum/d + x[i]);
359*8a729477SBarry Smith       }
360*8a729477SBarry Smith     }
361*8a729477SBarry Smith     if (flag & SOR_BACKWARD_SWEEP){
362*8a729477SBarry Smith       for ( i=m-1; i>=0; i-- ) {
363*8a729477SBarry Smith         d    = mat->a[diag[i] - 1];
364*8a729477SBarry Smith         n    = mat->i[i+1] - mat->i[i];
365*8a729477SBarry Smith         idx  = mat->j + mat->i[i] - 1;
366*8a729477SBarry Smith         v    = mat->a + mat->i[i] - 1;
367*8a729477SBarry Smith         sum  = b[i];
368*8a729477SBarry Smith         SPARSEDENSEMDOT(sum,xs,v,idx,n);
369*8a729477SBarry Smith         x[i] = (1. - omega)*x[i] + omega*(sum/d + x[i]);
370*8a729477SBarry Smith       }
371*8a729477SBarry Smith     }
372*8a729477SBarry Smith   }
373*8a729477SBarry Smith   return 0;
374*8a729477SBarry Smith }
375*8a729477SBarry Smith 
376*8a729477SBarry Smith static int MatiAIJnz(Mat matin,int *nz)
377*8a729477SBarry Smith {
378*8a729477SBarry Smith   Matiaij *mat = (Matiaij *) matin->data;
379*8a729477SBarry Smith   *nz = mat->nz;
380*8a729477SBarry Smith   return 0;
381*8a729477SBarry Smith }
382*8a729477SBarry Smith static int MatiAIJmem(Mat matin,int *nz)
383*8a729477SBarry Smith {
384*8a729477SBarry Smith   Matiaij *mat = (Matiaij *) matin->data;
385*8a729477SBarry Smith   *nz = mat->mem;
386*8a729477SBarry Smith   return 0;
387*8a729477SBarry Smith }
388*8a729477SBarry Smith 
389*8a729477SBarry Smith int MatiAIJLUFactorSymbolic(Mat,IS,IS,Mat*);
390*8a729477SBarry Smith int MatiAIJLUFactorNumeric(Mat,Mat);
391*8a729477SBarry Smith int MatiAIJSolve(Mat,Vec,Vec);
392*8a729477SBarry Smith 
393*8a729477SBarry Smith /* -------------------------------------------------------------------*/
394*8a729477SBarry Smith static struct _MatOps MatOps = {MatiAIJAddValues,MatiAIJAddValues,
395*8a729477SBarry Smith        0, 0,
396*8a729477SBarry Smith        MatiAIJmult,MatiAIJmultadd,MatiAIJmulttrans,MatiAIJmulttransadd,
397*8a729477SBarry Smith        MatiAIJSolve,0,0,0,
398*8a729477SBarry Smith        0,0,
399*8a729477SBarry Smith        MatiAIJrelax,
400*8a729477SBarry Smith        0,
401*8a729477SBarry Smith        MatiAIJnz,MatiAIJmem,0,
402*8a729477SBarry Smith        0,
403*8a729477SBarry Smith        MatiAIJgetdiag,0,0,
404*8a729477SBarry Smith        0,MatiAIJEndAssemble,
405*8a729477SBarry Smith        MatiAIJCompress,
406*8a729477SBarry Smith        MatiAIJinsopt,MatiAIJzeroentries,0,MatAIJreorder,
407*8a729477SBarry Smith        MatiAIJLUFactorSymbolic,MatiAIJLUFactorNumeric,0,0 };
408*8a729477SBarry Smith 
409*8a729477SBarry Smith 
410*8a729477SBarry Smith 
411*8a729477SBarry Smith /*@
412*8a729477SBarry Smith 
413*8a729477SBarry Smith       MatCreateSequentialAIJ - Creates a sparse matrix in AIJ format.
414*8a729477SBarry Smith 
415*8a729477SBarry Smith   Input Parameters:
416*8a729477SBarry Smith .   m,n - number of rows and columns
417*8a729477SBarry Smith .   nz - total number nonzeros in matrix
418*8a729477SBarry Smith .   nzz - number of nonzeros per row or null
419*8a729477SBarry Smith .       You must leave room for the diagonal entry even if it is zero.
420*8a729477SBarry Smith 
421*8a729477SBarry Smith   Output parameters:
422*8a729477SBarry Smith .  newmat - the matrix
423*8a729477SBarry Smith 
424*8a729477SBarry Smith   Keywords: matrix, aij, compressed row, sparse
425*8a729477SBarry Smith @*/
426*8a729477SBarry Smith int MatCreateSequentialAIJ(int m,int n,int nz,int *nnz, Mat *newmat)
427*8a729477SBarry Smith {
428*8a729477SBarry Smith   Mat       mat;
429*8a729477SBarry Smith   Matiaij   *aij;
430*8a729477SBarry Smith   int       i,rl,len;
431*8a729477SBarry Smith   *newmat      = 0;
432*8a729477SBarry Smith   CREATEHEADER(mat,_Mat);
433*8a729477SBarry Smith   mat->data    = (void *) (aij = NEW(Matiaij)); CHKPTR(aij);
434*8a729477SBarry Smith   mat->cookie  = MAT_COOKIE;
435*8a729477SBarry Smith   mat->ops     = &MatOps;
436*8a729477SBarry Smith   mat->destroy = MatiAIJdestroy;
437*8a729477SBarry Smith   mat->view    = MatiAIJview;
438*8a729477SBarry Smith   mat->type    = MATAIJSEQ;
439*8a729477SBarry Smith   mat->factor  = 0;
440*8a729477SBarry Smith   mat->row     = 0;
441*8a729477SBarry Smith   mat->col     = 0;
442*8a729477SBarry Smith   aij->m       = m;
443*8a729477SBarry Smith   aij->n       = n;
444*8a729477SBarry Smith   aij->imax    = (int *) MALLOC( m*sizeof(int) ); CHKPTR(aij->imax);
445*8a729477SBarry Smith   aij->mem     = m*sizeof(int) + sizeof(Matiaij);
446*8a729477SBarry Smith   if (!nnz) {
447*8a729477SBarry Smith     if (nz <= 0) nz = 1;
448*8a729477SBarry Smith     for ( i=0; i<m; i++ ) aij->imax[i] = nz;
449*8a729477SBarry Smith     nz = nz*m;
450*8a729477SBarry Smith   }
451*8a729477SBarry Smith   else {
452*8a729477SBarry Smith     nz = 0;
453*8a729477SBarry Smith     for ( i=0; i<m; i++ ) {aij->imax[i] = nnz[i]; nz += nnz[i];}
454*8a729477SBarry Smith   }
455*8a729477SBarry Smith 
456*8a729477SBarry Smith   /* allocate the matrix space */
457*8a729477SBarry Smith   aij->nz = nz;
458*8a729477SBarry Smith   len     = nz*(sizeof(int) + sizeof(Scalar)) + (aij->m+1)*sizeof(int);
459*8a729477SBarry Smith   aij->a  = (Scalar *) MALLOC( len ); CHKPTR(aij->a);
460*8a729477SBarry Smith   aij->j  = (int *) (aij->a + nz);
461*8a729477SBarry Smith   aij->i  = aij->j + nz;
462*8a729477SBarry Smith   aij->singlemalloc = 1;
463*8a729477SBarry Smith   aij->mem += len;
464*8a729477SBarry Smith 
465*8a729477SBarry Smith   aij->i[0] = 1;
466*8a729477SBarry Smith   for (i=1; i<m+1; i++) {
467*8a729477SBarry Smith     aij->i[i] = aij->i[i-1] + aij->imax[i-1];
468*8a729477SBarry Smith   }
469*8a729477SBarry Smith 
470*8a729477SBarry Smith   /* aij->ilen will count nonzeros in each row so far. */
471*8a729477SBarry Smith   aij->ilen = (int *) MALLOC((aij->m)*sizeof(int));
472*8a729477SBarry Smith 
473*8a729477SBarry Smith   /* stick in zeros along diagonal */
474*8a729477SBarry Smith   for ( i=0; i<aij->m; i++ ) {
475*8a729477SBarry Smith     aij->ilen[i] = 1;
476*8a729477SBarry Smith     aij->j[aij->i[i]-1] = i+1;
477*8a729477SBarry Smith     aij->a[aij->i[i]-1] = 0.0;
478*8a729477SBarry Smith   }
479*8a729477SBarry Smith   aij->nz = aij->m;
480*8a729477SBarry Smith   aij->mem += (aij->m)*sizeof(int) + len;
481*8a729477SBarry Smith 
482*8a729477SBarry Smith   aij->sorted      = 0;
483*8a729477SBarry Smith   aij->roworiented = 1;
484*8a729477SBarry Smith   aij->nonew       = 0;
485*8a729477SBarry Smith   aij->diag        = 0;
486*8a729477SBarry Smith 
487*8a729477SBarry Smith   *newmat = mat;
488*8a729477SBarry Smith   return 0;
489*8a729477SBarry Smith }
490