xref: /petsc/src/mat/impls/baij/seq/baij.c (revision 2b3076dc7d5306ac29c7a2bb400e8e4ff1ac4c63)
1b6490206SBarry Smith 
22593348eSBarry Smith #ifndef lint
3*2b3076dcSSatish Balay static char vcid[] = "$Id: baij.c,v 1.57 1996/07/09 17:06:28 balay Exp balay $";
42593348eSBarry Smith #endif
52593348eSBarry Smith 
62593348eSBarry Smith /*
7b6490206SBarry Smith     Defines the basic matrix operations for the BAIJ (compressed row)
82593348eSBarry Smith   matrix storage format.
92593348eSBarry Smith */
10b6490206SBarry Smith #include "baij.h"
111a6a6d98SBarry Smith #include "src/vec/vecimpl.h"
121a6a6d98SBarry Smith #include "src/inline/spops.h"
132593348eSBarry Smith #include "petsc.h"
143b547af2SSatish Balay 
15bcd2baecSBarry Smith extern   int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**);
162593348eSBarry Smith 
17a2ce50c7SBarry Smith static int MatGetReordering_SeqBAIJ(Mat A,MatReordering type,IS *rperm,IS *cperm)
182593348eSBarry Smith {
19b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
20bcd2baecSBarry Smith   int         ierr, *ia, *ja,n = a->mbs,*idx,i,ishift,oshift;
212593348eSBarry Smith 
222593348eSBarry Smith   /*
232593348eSBarry Smith      this is tacky: In the future when we have written special factorization
242593348eSBarry Smith      and solve routines for the identity permutation we should use a
252593348eSBarry Smith      stride index set instead of the general one.
262593348eSBarry Smith   */
272593348eSBarry Smith   if (type  == ORDER_NATURAL) {
282593348eSBarry Smith     idx = (int *) PetscMalloc( n*sizeof(int) ); CHKPTRQ(idx);
292593348eSBarry Smith     for ( i=0; i<n; i++ ) idx[i] = i;
302593348eSBarry Smith     ierr = ISCreateSeq(MPI_COMM_SELF,n,idx,rperm); CHKERRQ(ierr);
312593348eSBarry Smith     ierr = ISCreateSeq(MPI_COMM_SELF,n,idx,cperm); CHKERRQ(ierr);
322593348eSBarry Smith     PetscFree(idx);
332593348eSBarry Smith     ISSetPermutation(*rperm);
342593348eSBarry Smith     ISSetPermutation(*cperm);
352593348eSBarry Smith     ISSetIdentity(*rperm);
362593348eSBarry Smith     ISSetIdentity(*cperm);
372593348eSBarry Smith     return 0;
382593348eSBarry Smith   }
392593348eSBarry Smith 
40bcd2baecSBarry Smith   MatReorderingRegisterAll();
41a7c10996SSatish Balay   ishift = 0;
42bcd2baecSBarry Smith   oshift = -MatReorderingIndexShift[(int)type];
43bcd2baecSBarry Smith   if (MatReorderingRequiresSymmetric[(int)type]) {
441a6a6d98SBarry Smith     ierr = MatToSymmetricIJ_SeqAIJ(n,a->i,a->j,ishift,oshift,&ia,&ja);CHKERRQ(ierr);
451a6a6d98SBarry Smith     ierr = MatGetReordering_IJ(n,ia,ja,type,rperm,cperm); CHKERRQ(ierr);
462593348eSBarry Smith     PetscFree(ia); PetscFree(ja);
47bcd2baecSBarry Smith   } else {
48bcd2baecSBarry Smith     if (ishift == oshift) {
491a6a6d98SBarry Smith       ierr = MatGetReordering_IJ(n,a->i,a->j,type,rperm,cperm);CHKERRQ(ierr);
50bcd2baecSBarry Smith     }
51bcd2baecSBarry Smith     else if (ishift == -1) {
52bcd2baecSBarry Smith       /* temporarily subtract 1 from i and j indices */
531a6a6d98SBarry Smith       int nz = a->i[n] - 1;
54bcd2baecSBarry Smith       for ( i=0; i<nz; i++ ) a->j[i]--;
551a6a6d98SBarry Smith       for ( i=0; i<n+1; i++ ) a->i[i]--;
561a6a6d98SBarry Smith       ierr = MatGetReordering_IJ(n,a->i,a->j,type,rperm,cperm);CHKERRQ(ierr);
57bcd2baecSBarry Smith       for ( i=0; i<nz; i++ ) a->j[i]++;
581a6a6d98SBarry Smith       for ( i=0; i<n+1; i++ ) a->i[i]++;
59bcd2baecSBarry Smith     } else {
60bcd2baecSBarry Smith       /* temporarily add 1 to i and j indices */
611a6a6d98SBarry Smith       int nz = a->i[n] - 1;
62bcd2baecSBarry Smith       for ( i=0; i<nz; i++ ) a->j[i]++;
631a6a6d98SBarry Smith       for ( i=0; i<n+1; i++ ) a->i[i]++;
641a6a6d98SBarry Smith       ierr = MatGetReordering_IJ(n,a->i,a->j,type,rperm,cperm);CHKERRQ(ierr);
65bcd2baecSBarry Smith       for ( i=0; i<nz; i++ ) a->j[i]--;
661a6a6d98SBarry Smith       for ( i=0; i<n+1; i++ ) a->i[i]--;
67bcd2baecSBarry Smith     }
68bcd2baecSBarry Smith   }
692593348eSBarry Smith   return 0;
702593348eSBarry Smith }
712593348eSBarry Smith 
72de6a44a3SBarry Smith /*
73de6a44a3SBarry Smith      Adds diagonal pointers to sparse matrix structure.
74de6a44a3SBarry Smith */
75de6a44a3SBarry Smith 
76de6a44a3SBarry Smith int MatMarkDiag_SeqBAIJ(Mat A)
77de6a44a3SBarry Smith {
78de6a44a3SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
797fc0212eSBarry Smith   int         i,j, *diag, m = a->mbs;
80de6a44a3SBarry Smith 
81de6a44a3SBarry Smith   diag = (int *) PetscMalloc( (m+1)*sizeof(int)); CHKPTRQ(diag);
82de6a44a3SBarry Smith   PLogObjectMemory(A,(m+1)*sizeof(int));
837fc0212eSBarry Smith   for ( i=0; i<m; i++ ) {
84de6a44a3SBarry Smith     for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
85de6a44a3SBarry Smith       if (a->j[j] == i) {
86de6a44a3SBarry Smith         diag[i] = j;
87de6a44a3SBarry Smith         break;
88de6a44a3SBarry Smith       }
89de6a44a3SBarry Smith     }
90de6a44a3SBarry Smith   }
91de6a44a3SBarry Smith   a->diag = diag;
92de6a44a3SBarry Smith   return 0;
93de6a44a3SBarry Smith }
942593348eSBarry Smith 
952593348eSBarry Smith #include "draw.h"
962593348eSBarry Smith #include "pinclude/pviewer.h"
9777c4ece6SBarry Smith #include "sys.h"
982593348eSBarry Smith 
99b6490206SBarry Smith static int MatView_SeqBAIJ_Binary(Mat A,Viewer viewer)
1002593348eSBarry Smith {
101b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
1029df24120SSatish Balay   int         i, fd, *col_lens, ierr, bs = a->bs,count,*jj,j,k,l,bs2=a->bs2;
103b6490206SBarry Smith   Scalar      *aa;
1042593348eSBarry Smith 
10590ace30eSBarry Smith   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
1062593348eSBarry Smith   col_lens = (int *) PetscMalloc((4+a->m)*sizeof(int));CHKPTRQ(col_lens);
1072593348eSBarry Smith   col_lens[0] = MAT_COOKIE;
1082593348eSBarry Smith   col_lens[1] = a->m;
1092593348eSBarry Smith   col_lens[2] = a->n;
1107e67e3f9SSatish Balay   col_lens[3] = a->nz*bs2;
1112593348eSBarry Smith 
1122593348eSBarry Smith   /* store lengths of each row and write (including header) to file */
113b6490206SBarry Smith   count = 0;
114b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
115b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
116b6490206SBarry Smith       col_lens[4+count++] = bs*(a->i[i+1] - a->i[i]);
117b6490206SBarry Smith     }
1182593348eSBarry Smith   }
11977c4ece6SBarry Smith   ierr = PetscBinaryWrite(fd,col_lens,4+a->m,BINARY_INT,1); CHKERRQ(ierr);
1202593348eSBarry Smith   PetscFree(col_lens);
1212593348eSBarry Smith 
1222593348eSBarry Smith   /* store column indices (zero start index) */
1237e67e3f9SSatish Balay   jj = (int *) PetscMalloc( a->nz*bs2*sizeof(int) ); CHKPTRQ(jj);
124b6490206SBarry Smith   count = 0;
125b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
126b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
127b6490206SBarry Smith       for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
128b6490206SBarry Smith         for ( l=0; l<bs; l++ ) {
129b6490206SBarry Smith           jj[count++] = bs*a->j[k] + l;
1302593348eSBarry Smith         }
1312593348eSBarry Smith       }
132b6490206SBarry Smith     }
133b6490206SBarry Smith   }
1347e67e3f9SSatish Balay   ierr = PetscBinaryWrite(fd,jj,bs2*a->nz,BINARY_INT,0); CHKERRQ(ierr);
135b6490206SBarry Smith   PetscFree(jj);
1362593348eSBarry Smith 
1372593348eSBarry Smith   /* store nonzero values */
1387e67e3f9SSatish Balay   aa = (Scalar *) PetscMalloc(a->nz*bs2*sizeof(Scalar)); CHKPTRQ(aa);
139b6490206SBarry Smith   count = 0;
140b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
141b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
142b6490206SBarry Smith       for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
143b6490206SBarry Smith         for ( l=0; l<bs; l++ ) {
1447e67e3f9SSatish Balay           aa[count++] = a->a[bs2*k + l*bs + j];
145b6490206SBarry Smith         }
146b6490206SBarry Smith       }
147b6490206SBarry Smith     }
148b6490206SBarry Smith   }
1497e67e3f9SSatish Balay   ierr = PetscBinaryWrite(fd,aa,bs2*a->nz,BINARY_SCALAR,0); CHKERRQ(ierr);
150b6490206SBarry Smith   PetscFree(aa);
1512593348eSBarry Smith   return 0;
1522593348eSBarry Smith }
1532593348eSBarry Smith 
154b6490206SBarry Smith static int MatView_SeqBAIJ_ASCII(Mat A,Viewer viewer)
1552593348eSBarry Smith {
156b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
1579df24120SSatish Balay   int         ierr, i,j,format,bs = a->bs,k,l,bs2=a->bs2;
1582593348eSBarry Smith   FILE        *fd;
1592593348eSBarry Smith   char        *outputname;
1602593348eSBarry Smith 
16190ace30eSBarry Smith   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
1622593348eSBarry Smith   ierr = ViewerFileGetOutputname_Private(viewer,&outputname);CHKERRQ(ierr);
16390ace30eSBarry Smith   ierr = ViewerGetFormat(viewer,&format);
1647ddc982cSLois Curfman McInnes   if (format == ASCII_FORMAT_INFO || format == ASCII_FORMAT_INFO_DETAILED) {
1657ddc982cSLois Curfman McInnes     fprintf(fd,"  block size is %d\n",bs);
1662593348eSBarry Smith   }
16790ace30eSBarry Smith   else if (format == ASCII_FORMAT_MATLAB) {
168b6490206SBarry Smith     SETERRQ(1,"MatView_SeqBAIJ_ASCII:Matlab format not supported");
1692593348eSBarry Smith   }
17044cd7ae7SLois Curfman McInnes   else if (format == ASCII_FORMAT_COMMON) {
17144cd7ae7SLois Curfman McInnes     for ( i=0; i<a->mbs; i++ ) {
17244cd7ae7SLois Curfman McInnes       for ( j=0; j<bs; j++ ) {
17344cd7ae7SLois Curfman McInnes         fprintf(fd,"row %d:",i*bs+j);
17444cd7ae7SLois Curfman McInnes         for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
17544cd7ae7SLois Curfman McInnes           for ( l=0; l<bs; l++ ) {
17644cd7ae7SLois Curfman McInnes #if defined(PETSC_COMPLEX)
17744cd7ae7SLois Curfman McInnes           if (imag(a->a[bs2*k + l*bs + j]) != 0.0 && real(a->a[bs2*k + l*bs + j]) != 0.0)
17844cd7ae7SLois Curfman McInnes             fprintf(fd," %d %g + %g i",bs*a->j[k]+l,
17944cd7ae7SLois Curfman McInnes               real(a->a[bs2*k + l*bs + j]),imag(a->a[bs2*k + l*bs + j]));
18044cd7ae7SLois Curfman McInnes           else if (real(a->a[bs2*k + l*bs + j]) != 0.0)
18144cd7ae7SLois Curfman McInnes             fprintf(fd," %d %g ",bs*a->j[k]+l,real(a->a[bs2*k + l*bs + j]));
18244cd7ae7SLois Curfman McInnes #else
18344cd7ae7SLois Curfman McInnes           if (a->a[bs2*k + l*bs + j] != 0.0)
18444cd7ae7SLois Curfman McInnes             fprintf(fd," %d %g ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);
18544cd7ae7SLois Curfman McInnes #endif
18644cd7ae7SLois Curfman McInnes           }
18744cd7ae7SLois Curfman McInnes         }
18844cd7ae7SLois Curfman McInnes         fprintf(fd,"\n");
18944cd7ae7SLois Curfman McInnes       }
19044cd7ae7SLois Curfman McInnes     }
19144cd7ae7SLois Curfman McInnes   }
1922593348eSBarry Smith   else {
193b6490206SBarry Smith     for ( i=0; i<a->mbs; i++ ) {
194b6490206SBarry Smith       for ( j=0; j<bs; j++ ) {
195b6490206SBarry Smith         fprintf(fd,"row %d:",i*bs+j);
196b6490206SBarry Smith         for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
197b6490206SBarry Smith           for ( l=0; l<bs; l++ ) {
19888685aaeSLois Curfman McInnes #if defined(PETSC_COMPLEX)
1997e67e3f9SSatish Balay           if (imag(a->a[bs2*k + l*bs + j]) != 0.0) {
20088685aaeSLois Curfman McInnes             fprintf(fd," %d %g + %g i",bs*a->j[k]+l,
2017e67e3f9SSatish Balay               real(a->a[bs2*k + l*bs + j]),imag(a->a[bs2*k + l*bs + j]));
20288685aaeSLois Curfman McInnes           }
20388685aaeSLois Curfman McInnes           else {
2047e67e3f9SSatish Balay             fprintf(fd," %d %g ",bs*a->j[k]+l,real(a->a[bs2*k + l*bs + j]));
20588685aaeSLois Curfman McInnes           }
20688685aaeSLois Curfman McInnes #else
2077e67e3f9SSatish Balay             fprintf(fd," %d %g ",bs*a->j[k]+l,a->a[bs2*k + l*bs + j]);
20888685aaeSLois Curfman McInnes #endif
2092593348eSBarry Smith           }
2102593348eSBarry Smith         }
2112593348eSBarry Smith         fprintf(fd,"\n");
2122593348eSBarry Smith       }
2132593348eSBarry Smith     }
214b6490206SBarry Smith   }
2152593348eSBarry Smith   fflush(fd);
2162593348eSBarry Smith   return 0;
2172593348eSBarry Smith }
2182593348eSBarry Smith 
219b6490206SBarry Smith static int MatView_SeqBAIJ(PetscObject obj,Viewer viewer)
2202593348eSBarry Smith {
2212593348eSBarry Smith   Mat         A = (Mat) obj;
22219bcc07fSBarry Smith   ViewerType  vtype;
22319bcc07fSBarry Smith   int         ierr;
2242593348eSBarry Smith 
22519bcc07fSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
22619bcc07fSBarry Smith   if (vtype == MATLAB_VIEWER) {
227b6490206SBarry Smith     SETERRQ(1,"MatView_SeqBAIJ:Matlab viewer not supported");
2282593348eSBarry Smith   }
22919bcc07fSBarry Smith   else if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER){
230b6490206SBarry Smith     return MatView_SeqBAIJ_ASCII(A,viewer);
2312593348eSBarry Smith   }
23219bcc07fSBarry Smith   else if (vtype == BINARY_FILE_VIEWER) {
233b6490206SBarry Smith     return MatView_SeqBAIJ_Binary(A,viewer);
2342593348eSBarry Smith   }
23519bcc07fSBarry Smith   else if (vtype == DRAW_VIEWER) {
236b6490206SBarry Smith     SETERRQ(1,"MatView_SeqBAIJ:Draw viewer not supported");
2372593348eSBarry Smith   }
2382593348eSBarry Smith   return 0;
2392593348eSBarry Smith }
240b6490206SBarry Smith 
241119a934aSSatish Balay #define CHUNKSIZE  10
242cd0e1443SSatish Balay 
243cd0e1443SSatish Balay /* This version has row oriented v  */
244cd0e1443SSatish Balay static int MatSetValues_SeqBAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is)
245cd0e1443SSatish Balay {
246cd0e1443SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
247cd0e1443SSatish Balay   int         *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,sorted=a->sorted;
248cd0e1443SSatish Balay   int         *imax=a->imax,*ai=a->i,*ailen=a->ilen,roworiented=a->roworiented;
249a7c10996SSatish Balay   int         *aj=a->j,nonew=a->nonew,bs=a->bs,brow,bcol;
2509df24120SSatish Balay   int          ridx,cidx,bs2=a->bs2;
251cd0e1443SSatish Balay   Scalar      *ap,value,*aa=a->a,*bap;
252cd0e1443SSatish Balay 
253cd0e1443SSatish Balay   for ( k=0; k<m; k++ ) { /* loop over added rows */
254cd0e1443SSatish Balay     row  = im[k]; brow = row/bs;
255cd0e1443SSatish Balay     if (row < 0) SETERRQ(1,"MatSetValues_SeqBAIJ:Negative row");
256cd0e1443SSatish Balay     if (row >= a->m) SETERRQ(1,"MatSetValues_SeqBAIJ:Row too large");
257a7c10996SSatish Balay     rp   = aj + ai[brow]; ap = aa + bs2*ai[brow];
258cd0e1443SSatish Balay     rmax = imax[brow]; nrow = ailen[brow];
259cd0e1443SSatish Balay     low = 0;
260cd0e1443SSatish Balay     for ( l=0; l<n; l++ ) { /* loop over added columns */
261cd0e1443SSatish Balay       if (in[l] < 0) SETERRQ(1,"MatSetValues_SeqBAIJ:Negative column");
262cd0e1443SSatish Balay       if (in[l] >= a->n) SETERRQ(1,"MatSetValues_SeqBAIJ:Column too large");
263a7c10996SSatish Balay       col = in[l]; bcol = col/bs;
264cd0e1443SSatish Balay       ridx = row % bs; cidx = col % bs;
265cd0e1443SSatish Balay       if (roworiented) {
266cd0e1443SSatish Balay         value = *v++;
267cd0e1443SSatish Balay       }
268cd0e1443SSatish Balay       else {
269cd0e1443SSatish Balay         value = v[k + l*m];
270cd0e1443SSatish Balay       }
271cd0e1443SSatish Balay       if (!sorted) low = 0; high = nrow;
272cd0e1443SSatish Balay       while (high-low > 5) {
273cd0e1443SSatish Balay         t = (low+high)/2;
274cd0e1443SSatish Balay         if (rp[t] > bcol) high = t;
275cd0e1443SSatish Balay         else             low  = t;
276cd0e1443SSatish Balay       }
277cd0e1443SSatish Balay       for ( i=low; i<high; i++ ) {
278cd0e1443SSatish Balay         if (rp[i] > bcol) break;
279cd0e1443SSatish Balay         if (rp[i] == bcol) {
2807e67e3f9SSatish Balay           bap  = ap +  bs2*i + bs*cidx + ridx;
281cd0e1443SSatish Balay           if (is == ADD_VALUES) *bap += value;
282cd0e1443SSatish Balay           else                  *bap  = value;
283cd0e1443SSatish Balay           goto noinsert;
284cd0e1443SSatish Balay         }
285cd0e1443SSatish Balay       }
286cd0e1443SSatish Balay       if (nonew) goto noinsert;
287cd0e1443SSatish Balay       if (nrow >= rmax) {
288cd0e1443SSatish Balay         /* there is no extra room in row, therefore enlarge */
289cd0e1443SSatish Balay         int    new_nz = ai[a->mbs] + CHUNKSIZE,len,*new_i,*new_j;
290cd0e1443SSatish Balay         Scalar *new_a;
291cd0e1443SSatish Balay 
292cd0e1443SSatish Balay         /* malloc new storage space */
2937e67e3f9SSatish Balay         len     = new_nz*(sizeof(int)+bs2*sizeof(Scalar))+(a->mbs+1)*sizeof(int);
294cd0e1443SSatish Balay         new_a   = (Scalar *) PetscMalloc( len ); CHKPTRQ(new_a);
2957e67e3f9SSatish Balay         new_j   = (int *) (new_a + bs2*new_nz);
296cd0e1443SSatish Balay         new_i   = new_j + new_nz;
297cd0e1443SSatish Balay 
298cd0e1443SSatish Balay         /* copy over old data into new slots */
299cd0e1443SSatish Balay         for ( ii=0; ii<brow+1; ii++ ) {new_i[ii] = ai[ii];}
3007e67e3f9SSatish Balay         for ( ii=brow+1; ii<a->mbs+1; ii++ ) {new_i[ii] = ai[ii]+CHUNKSIZE;}
301a7c10996SSatish Balay         PetscMemcpy(new_j,aj,(ai[brow]+nrow)*sizeof(int));
302a7c10996SSatish Balay         len = (new_nz - CHUNKSIZE - ai[brow] - nrow);
303a7c10996SSatish Balay         PetscMemcpy(new_j+ai[brow]+nrow+CHUNKSIZE,aj+ai[brow]+nrow,
304cd0e1443SSatish Balay                                                            len*sizeof(int));
305a7c10996SSatish Balay         PetscMemcpy(new_a,aa,(ai[brow]+nrow)*bs2*sizeof(Scalar));
306a7c10996SSatish Balay         PetscMemzero(new_a+bs2*(ai[brow]+nrow),bs2*CHUNKSIZE*sizeof(Scalar));
307a7c10996SSatish Balay         PetscMemcpy(new_a+bs2*(ai[brow]+nrow+CHUNKSIZE),
308a7c10996SSatish Balay                     aa+bs2*(ai[brow]+nrow),bs2*len*sizeof(Scalar));
309cd0e1443SSatish Balay         /* free up old matrix storage */
310cd0e1443SSatish Balay         PetscFree(a->a);
311cd0e1443SSatish Balay         if (!a->singlemalloc) {PetscFree(a->i);PetscFree(a->j);}
312cd0e1443SSatish Balay         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
313cd0e1443SSatish Balay         a->singlemalloc = 1;
314cd0e1443SSatish Balay 
315a7c10996SSatish Balay         rp   = aj + ai[brow]; ap = aa + bs2*ai[brow];
316cd0e1443SSatish Balay         rmax = imax[brow] = imax[brow] + CHUNKSIZE;
3177e67e3f9SSatish Balay         PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + bs2*sizeof(Scalar)));
31818e7b8e4SLois Curfman McInnes         a->maxnz += bs2*CHUNKSIZE;
319cd0e1443SSatish Balay         a->reallocs++;
320119a934aSSatish Balay         a->nz++;
321cd0e1443SSatish Balay       }
3227e67e3f9SSatish Balay       N = nrow++ - 1;
323cd0e1443SSatish Balay       /* shift up all the later entries in this row */
324cd0e1443SSatish Balay       for ( ii=N; ii>=i; ii-- ) {
325cd0e1443SSatish Balay         rp[ii+1] = rp[ii];
3267e67e3f9SSatish Balay          PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(Scalar));
327cd0e1443SSatish Balay       }
3287e67e3f9SSatish Balay       if (N>=i) PetscMemzero(ap+bs2*i,bs2*sizeof(Scalar));
329cd0e1443SSatish Balay       rp[i] = bcol;
3307e67e3f9SSatish Balay       ap[bs2*i + bs*cidx + ridx] = value;
331cd0e1443SSatish Balay       noinsert:;
332cd0e1443SSatish Balay       low = i;
333cd0e1443SSatish Balay     }
334cd0e1443SSatish Balay     ailen[brow] = nrow;
335cd0e1443SSatish Balay   }
336cd0e1443SSatish Balay   return 0;
337cd0e1443SSatish Balay }
338cd0e1443SSatish Balay 
3390b824a48SSatish Balay static int MatGetSize_SeqBAIJ(Mat A,int *m,int *n)
3400b824a48SSatish Balay {
3410b824a48SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
3420b824a48SSatish Balay   *m = a->m; *n = a->n;
3430b824a48SSatish Balay   return 0;
3440b824a48SSatish Balay }
3450b824a48SSatish Balay 
3460b824a48SSatish Balay static int MatGetOwnershipRange_SeqBAIJ(Mat A,int *m,int *n)
3470b824a48SSatish Balay {
3480b824a48SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
3490b824a48SSatish Balay   *m = 0; *n = a->m;
3500b824a48SSatish Balay   return 0;
3510b824a48SSatish Balay }
3520b824a48SSatish Balay 
3539867e207SSatish Balay int MatGetRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
3549867e207SSatish Balay {
3559867e207SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
3567e67e3f9SSatish Balay   int          itmp,i,j,k,M,*ai,*aj,bs,bn,bp,*idx_i,bs2;
3579867e207SSatish Balay   Scalar      *aa,*v_i,*aa_i;
3589867e207SSatish Balay 
3599867e207SSatish Balay   bs  = a->bs;
3609867e207SSatish Balay   ai  = a->i;
3619867e207SSatish Balay   aj  = a->j;
3629867e207SSatish Balay   aa  = a->a;
3639df24120SSatish Balay   bs2 = a->bs2;
3649867e207SSatish Balay 
3659867e207SSatish Balay   if (row < 0 || row >= a->m) SETERRQ(1,"MatGetRow_SeqBAIJ:Row out of range");
3669867e207SSatish Balay 
3679867e207SSatish Balay   bn  = row/bs;   /* Block number */
3689867e207SSatish Balay   bp  = row % bs; /* Block Position */
3699867e207SSatish Balay   M   = ai[bn+1] - ai[bn];
3709867e207SSatish Balay   *nz = bs*M;
3719867e207SSatish Balay 
3729867e207SSatish Balay   if (v) {
3739867e207SSatish Balay     *v = 0;
3749867e207SSatish Balay     if (*nz) {
3759867e207SSatish Balay       *v = (Scalar *) PetscMalloc( (*nz)*sizeof(Scalar) ); CHKPTRQ(*v);
3769867e207SSatish Balay       for ( i=0; i<M; i++ ) { /* for each block in the block row */
3779867e207SSatish Balay         v_i  = *v + i*bs;
3787e67e3f9SSatish Balay         aa_i = aa + bs2*(ai[bn] + i);
3797e67e3f9SSatish Balay         for ( j=bp,k=0; j<bs2; j+=bs,k++ ) {v_i[k] = aa_i[j];}
3809867e207SSatish Balay       }
3819867e207SSatish Balay     }
3829867e207SSatish Balay   }
3839867e207SSatish Balay 
3849867e207SSatish Balay   if (idx) {
3859867e207SSatish Balay     *idx = 0;
3869867e207SSatish Balay     if (*nz) {
3879867e207SSatish Balay       *idx = (int *) PetscMalloc( (*nz)*sizeof(int) ); CHKPTRQ(*idx);
3889867e207SSatish Balay       for ( i=0; i<M; i++ ) { /* for each block in the block row */
3899867e207SSatish Balay         idx_i = *idx + i*bs;
3909867e207SSatish Balay         itmp  = bs*aj[ai[bn] + i];
3919867e207SSatish Balay         for ( j=0; j<bs; j++ ) {idx_i[j] = itmp++;}
3929867e207SSatish Balay       }
3939867e207SSatish Balay     }
3949867e207SSatish Balay   }
3959867e207SSatish Balay   return 0;
3969867e207SSatish Balay }
3979867e207SSatish Balay 
3989867e207SSatish Balay int MatRestoreRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
3999867e207SSatish Balay {
4009867e207SSatish Balay   if (idx) {if (*idx) PetscFree(*idx);}
4019867e207SSatish Balay   if (v)   {if (*v)   PetscFree(*v);}
4029867e207SSatish Balay   return 0;
4039867e207SSatish Balay }
404b6490206SBarry Smith 
405f2501298SSatish Balay static int MatTranspose_SeqBAIJ(Mat A,Mat *B)
406f2501298SSatish Balay {
407f2501298SSatish Balay   Mat_SeqBAIJ *a=(Mat_SeqBAIJ *)A->data;
408f2501298SSatish Balay   Mat         C;
409f2501298SSatish Balay   int         i,j,k,ierr,*aj=a->j,*ai=a->i,bs=a->bs,mbs=a->mbs,nbs=a->nbs,len,*col;
4109df24120SSatish Balay   int         *rows,*cols,bs2=a->bs2;
411f2501298SSatish Balay   Scalar      *array=a->a;
412f2501298SSatish Balay 
413f2501298SSatish Balay   if (B==PETSC_NULL && mbs!=nbs)
414f2501298SSatish Balay     SETERRQ(1,"MatTranspose_SeqBAIJ:Square matrix only for in-place");
415f2501298SSatish Balay   col = (int *) PetscMalloc((1+nbs)*sizeof(int)); CHKPTRQ(col);
416f2501298SSatish Balay   PetscMemzero(col,(1+nbs)*sizeof(int));
417a7c10996SSatish Balay 
418a7c10996SSatish Balay   for ( i=0; i<ai[mbs]; i++ ) col[aj[i]] += 1;
419f2501298SSatish Balay   ierr = MatCreateSeqBAIJ(A->comm,bs,a->n,a->m,PETSC_NULL,col,&C); CHKERRQ(ierr);
420f2501298SSatish Balay   PetscFree(col);
421f2501298SSatish Balay   rows = (int *) PetscMalloc(2*bs*sizeof(int)); CHKPTRQ(rows);
422f2501298SSatish Balay   cols = rows + bs;
423f2501298SSatish Balay   for ( i=0; i<mbs; i++ ) {
424f2501298SSatish Balay     cols[0] = i*bs;
425f2501298SSatish Balay     for (k=1; k<bs; k++ ) cols[k] = cols[k-1] + 1;
426f2501298SSatish Balay     len = ai[i+1] - ai[i];
427f2501298SSatish Balay     for ( j=0; j<len; j++ ) {
428f2501298SSatish Balay       rows[0] = (*aj++)*bs;
429f2501298SSatish Balay       for (k=1; k<bs; k++ ) rows[k] = rows[k-1] + 1;
430f2501298SSatish Balay       ierr = MatSetValues(C,bs,rows,bs,cols,array,INSERT_VALUES); CHKERRQ(ierr);
431f2501298SSatish Balay       array += bs2;
432f2501298SSatish Balay     }
433f2501298SSatish Balay   }
4341073c447SSatish Balay   PetscFree(rows);
435f2501298SSatish Balay 
4366d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4376d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
438f2501298SSatish Balay 
439f2501298SSatish Balay   if (B != PETSC_NULL) {
440f2501298SSatish Balay     *B = C;
441f2501298SSatish Balay   } else {
442f2501298SSatish Balay     /* This isn't really an in-place transpose */
443f2501298SSatish Balay     PetscFree(a->a);
444f2501298SSatish Balay     if (!a->singlemalloc) {PetscFree(a->i); PetscFree(a->j);}
445f2501298SSatish Balay     if (a->diag) PetscFree(a->diag);
446f2501298SSatish Balay     if (a->ilen) PetscFree(a->ilen);
447f2501298SSatish Balay     if (a->imax) PetscFree(a->imax);
448f2501298SSatish Balay     if (a->solve_work) PetscFree(a->solve_work);
449f2501298SSatish Balay     PetscFree(a);
450f2501298SSatish Balay     PetscMemcpy(A,C,sizeof(struct _Mat));
451f2501298SSatish Balay     PetscHeaderDestroy(C);
452f2501298SSatish Balay   }
453f2501298SSatish Balay   return 0;
454f2501298SSatish Balay }
455f2501298SSatish Balay 
456f2501298SSatish Balay 
457584200bdSSatish Balay static int MatAssemblyEnd_SeqBAIJ(Mat A,MatAssemblyType mode)
458584200bdSSatish Balay {
459584200bdSSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
460584200bdSSatish Balay   int        fshift = 0,i,j,*ai = a->i, *aj = a->j, *imax = a->imax;
461a7c10996SSatish Balay   int        m = a->m,*ip, N, *ailen = a->ilen;
4629df24120SSatish Balay   int        mbs = a->mbs, bs2 = a->bs2;
463584200bdSSatish Balay   Scalar     *aa = a->a, *ap;
464584200bdSSatish Balay 
4656d4a8577SBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) return 0;
466584200bdSSatish Balay 
467584200bdSSatish Balay   for ( i=1; i<mbs; i++ ) {
468584200bdSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
469584200bdSSatish Balay     fshift += imax[i-1] - ailen[i-1];
470584200bdSSatish Balay     if (fshift) {
471a7c10996SSatish Balay       ip = aj + ai[i]; ap = aa + bs2*ai[i];
472584200bdSSatish Balay       N = ailen[i];
473584200bdSSatish Balay       for ( j=0; j<N; j++ ) {
474584200bdSSatish Balay         ip[j-fshift] = ip[j];
4757e67e3f9SSatish Balay         PetscMemcpy(ap+(j-fshift)*bs2,ap+j*bs2,bs2*sizeof(Scalar));
476584200bdSSatish Balay       }
477584200bdSSatish Balay     }
478584200bdSSatish Balay     ai[i] = ai[i-1] + ailen[i-1];
479584200bdSSatish Balay   }
480584200bdSSatish Balay   if (mbs) {
481584200bdSSatish Balay     fshift += imax[mbs-1] - ailen[mbs-1];
482584200bdSSatish Balay     ai[mbs] = ai[mbs-1] + ailen[mbs-1];
483584200bdSSatish Balay   }
484584200bdSSatish Balay   /* reset ilen and imax for each row */
485584200bdSSatish Balay   for ( i=0; i<mbs; i++ ) {
486584200bdSSatish Balay     ailen[i] = imax[i] = ai[i+1] - ai[i];
487584200bdSSatish Balay   }
488a7c10996SSatish Balay   a->nz = ai[mbs];
489584200bdSSatish Balay 
490584200bdSSatish Balay   /* diagonals may have moved, so kill the diagonal pointers */
491584200bdSSatish Balay   if (fshift && a->diag) {
492584200bdSSatish Balay     PetscFree(a->diag);
493584200bdSSatish Balay     PLogObjectMemory(A,-(m+1)*sizeof(int));
494584200bdSSatish Balay     a->diag = 0;
495584200bdSSatish Balay   }
49667790700SSatish Balay   PLogInfo(A,"MatAssemblyEnd_SeqBAIJ: Unneed storage space (blocks) %d used %d, rows %d, block size %d\n", fshift*bs2,a->nz*bs2,m,a->bs);
497584200bdSSatish Balay   PLogInfo(A,"MatAssemblyEnd_SeqBAIJ: Number of mallocs during MatSetValues %d\n",
498584200bdSSatish Balay            a->reallocs);
499584200bdSSatish Balay   return 0;
500584200bdSSatish Balay }
501584200bdSSatish Balay 
502b6490206SBarry Smith static int MatZeroEntries_SeqBAIJ(Mat A)
5032593348eSBarry Smith {
504b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
5059df24120SSatish Balay   PetscMemzero(a->a,a->bs2*a->i[a->mbs]*sizeof(Scalar));
5062593348eSBarry Smith   return 0;
5072593348eSBarry Smith }
5082593348eSBarry Smith 
509b6490206SBarry Smith int MatDestroy_SeqBAIJ(PetscObject obj)
5102593348eSBarry Smith {
5112593348eSBarry Smith   Mat         A  = (Mat) obj;
512b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
5132593348eSBarry Smith 
5142593348eSBarry Smith #if defined(PETSC_LOG)
5152593348eSBarry Smith   PLogObjectState(obj,"Rows=%d, Cols=%d, NZ=%d",a->m,a->n,a->nz);
5162593348eSBarry Smith #endif
5172593348eSBarry Smith   PetscFree(a->a);
5182593348eSBarry Smith   if (!a->singlemalloc) { PetscFree(a->i); PetscFree(a->j);}
5192593348eSBarry Smith   if (a->diag) PetscFree(a->diag);
5202593348eSBarry Smith   if (a->ilen) PetscFree(a->ilen);
5212593348eSBarry Smith   if (a->imax) PetscFree(a->imax);
5222593348eSBarry Smith   if (a->solve_work) PetscFree(a->solve_work);
523de6a44a3SBarry Smith   if (a->mult_work) PetscFree(a->mult_work);
5242593348eSBarry Smith   PetscFree(a);
525f2655603SLois Curfman McInnes   PLogObjectDestroy(A);
526f2655603SLois Curfman McInnes   PetscHeaderDestroy(A);
5272593348eSBarry Smith   return 0;
5282593348eSBarry Smith }
5292593348eSBarry Smith 
530b6490206SBarry Smith static int MatSetOption_SeqBAIJ(Mat A,MatOption op)
5312593348eSBarry Smith {
532b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
5336d4a8577SBarry Smith   if      (op == MAT_ROW_ORIENTED)              a->roworiented = 1;
5346d4a8577SBarry Smith   else if (op == MAT_COLUMN_ORIENTED)           a->roworiented = 0;
5356d4a8577SBarry Smith   else if (op == MAT_COLUMNS_SORTED)            a->sorted      = 1;
5366d4a8577SBarry Smith   else if (op == MAT_NO_NEW_NONZERO_LOCATIONS)  a->nonew       = 1;
5376d4a8577SBarry Smith   else if (op == MAT_YES_NEW_NONZERO_LOCATIONS) a->nonew       = 0;
5386d4a8577SBarry Smith   else if (op == MAT_ROWS_SORTED ||
5396d4a8577SBarry Smith            op == MAT_SYMMETRIC ||
5406d4a8577SBarry Smith            op == MAT_STRUCTURALLY_SYMMETRIC ||
5416d4a8577SBarry Smith            op == MAT_YES_NEW_DIAGONALS)
54294a424c1SBarry Smith     PLogInfo(A,"Info:MatSetOption_SeqBAIJ:Option ignored\n");
5436d4a8577SBarry Smith   else if (op == MAT_NO_NEW_DIAGONALS)
5446d4a8577SBarry Smith     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqBAIJ:MAT_NO_NEW_DIAGONALS");}
5452593348eSBarry Smith   else
546b6490206SBarry Smith     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqBAIJ:unknown option");}
5472593348eSBarry Smith   return 0;
5482593348eSBarry Smith }
5492593348eSBarry Smith 
5502593348eSBarry Smith 
5512593348eSBarry Smith /* -------------------------------------------------------*/
5522593348eSBarry Smith /* Should check that shapes of vectors and matrices match */
5532593348eSBarry Smith /* -------------------------------------------------------*/
554b6490206SBarry Smith #include "pinclude/plapack.h"
555b6490206SBarry Smith 
55639b95ed1SBarry Smith static int MatMult_SeqBAIJ_1(Mat A,Vec xx,Vec zz)
5572593348eSBarry Smith {
558b6490206SBarry Smith   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
5591a6a6d98SBarry Smith   Scalar          *xg,*zg;
56039b95ed1SBarry Smith   register Scalar *x,*z,*v,sum;
56139b95ed1SBarry Smith   int             mbs=a->mbs,i,*idx,*ii,n,ierr;
5622593348eSBarry Smith 
563bb42667fSSatish Balay   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
564bb42667fSSatish Balay   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
565b6490206SBarry Smith 
566119a934aSSatish Balay   idx   = a->j;
567119a934aSSatish Balay   v     = a->a;
568119a934aSSatish Balay   ii    = a->i;
569119a934aSSatish Balay 
570119a934aSSatish Balay   for ( i=0; i<mbs; i++ ) {
571119a934aSSatish Balay     n    = ii[1] - ii[0]; ii++;
572119a934aSSatish Balay     sum  = 0.0;
573119a934aSSatish Balay     while (n--) sum += *v++ * x[*idx++];
5741a6a6d98SBarry Smith     z[i] = sum;
575119a934aSSatish Balay   }
57639b95ed1SBarry Smith   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
57739b95ed1SBarry Smith   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
57839b95ed1SBarry Smith   PLogFlops(2*a->nz - a->m);
57939b95ed1SBarry Smith   return 0;
58039b95ed1SBarry Smith }
58139b95ed1SBarry Smith 
58239b95ed1SBarry Smith static int MatMult_SeqBAIJ_2(Mat A,Vec xx,Vec zz)
58339b95ed1SBarry Smith {
58439b95ed1SBarry Smith   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
58539b95ed1SBarry Smith   Scalar          *xg,*zg;
58639b95ed1SBarry Smith   register Scalar *x,*z,*v,*xb,sum1,sum2;
58739b95ed1SBarry Smith   register Scalar x1,x2;
58839b95ed1SBarry Smith   int             mbs=a->mbs,i,*idx,*ii;
58939b95ed1SBarry Smith   int             j,n,ierr;
59039b95ed1SBarry Smith 
59139b95ed1SBarry Smith   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
59239b95ed1SBarry Smith   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
59339b95ed1SBarry Smith 
59439b95ed1SBarry Smith   idx   = a->j;
59539b95ed1SBarry Smith   v     = a->a;
59639b95ed1SBarry Smith   ii    = a->i;
59739b95ed1SBarry Smith 
598119a934aSSatish Balay   for ( i=0; i<mbs; i++ ) {
599119a934aSSatish Balay     n  = ii[1] - ii[0]; ii++;
600119a934aSSatish Balay     sum1 = 0.0; sum2 = 0.0;
601119a934aSSatish Balay     for ( j=0; j<n; j++ ) {
602119a934aSSatish Balay       xb = x + 2*(*idx++); x1 = xb[0]; x2 = xb[1];
603119a934aSSatish Balay       sum1 += v[0]*x1 + v[2]*x2;
604119a934aSSatish Balay       sum2 += v[1]*x1 + v[3]*x2;
605119a934aSSatish Balay       v += 4;
606119a934aSSatish Balay     }
6071a6a6d98SBarry Smith     z[0] = sum1; z[1] = sum2;
608119a934aSSatish Balay     z += 2;
609119a934aSSatish Balay   }
61039b95ed1SBarry Smith   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
61139b95ed1SBarry Smith   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
61239b95ed1SBarry Smith   PLogFlops(4*a->nz - a->m);
61339b95ed1SBarry Smith   return 0;
61439b95ed1SBarry Smith }
61539b95ed1SBarry Smith 
61639b95ed1SBarry Smith static int MatMult_SeqBAIJ_3(Mat A,Vec xx,Vec zz)
61739b95ed1SBarry Smith {
61839b95ed1SBarry Smith   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
61939b95ed1SBarry Smith   Scalar          *xg,*zg;
62039b95ed1SBarry Smith   register Scalar *x,*z,*v,*xb,sum1,sum2,sum3,x1,x2,x3;
62139b95ed1SBarry Smith   int             mbs=a->mbs,i,*idx,*ii,j,n,ierr;
62239b95ed1SBarry Smith 
62339b95ed1SBarry Smith   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
62439b95ed1SBarry Smith   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
62539b95ed1SBarry Smith 
62639b95ed1SBarry Smith   idx   = a->j;
62739b95ed1SBarry Smith   v     = a->a;
62839b95ed1SBarry Smith   ii    = a->i;
62939b95ed1SBarry Smith 
630119a934aSSatish Balay   for ( i=0; i<mbs; i++ ) {
631119a934aSSatish Balay     n  = ii[1] - ii[0]; ii++;
632119a934aSSatish Balay     sum1 = 0.0; sum2 = 0.0; sum3 = 0.0;
633119a934aSSatish Balay     for ( j=0; j<n; j++ ) {
634119a934aSSatish Balay       xb = x + 3*(*idx++); x1 = xb[0]; x2 = xb[1]; x3 = xb[2];
635119a934aSSatish Balay       sum1 += v[0]*x1 + v[3]*x2 + v[6]*x3;
636119a934aSSatish Balay       sum2 += v[1]*x1 + v[4]*x2 + v[7]*x3;
637119a934aSSatish Balay       sum3 += v[2]*x1 + v[5]*x2 + v[8]*x3;
638119a934aSSatish Balay       v += 9;
639119a934aSSatish Balay     }
6401a6a6d98SBarry Smith     z[0] = sum1; z[1] = sum2; z[2] = sum3;
641119a934aSSatish Balay     z += 3;
642119a934aSSatish Balay   }
64339b95ed1SBarry Smith   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
64439b95ed1SBarry Smith   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
64539b95ed1SBarry Smith   PLogFlops(18*a->nz - a->m);
64639b95ed1SBarry Smith   return 0;
64739b95ed1SBarry Smith }
64839b95ed1SBarry Smith 
64939b95ed1SBarry Smith static int MatMult_SeqBAIJ_4(Mat A,Vec xx,Vec zz)
65039b95ed1SBarry Smith {
65139b95ed1SBarry Smith   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
65239b95ed1SBarry Smith   Scalar          *xg,*zg;
65339b95ed1SBarry Smith   register Scalar *x,*z,*v,*xb,sum1,sum2,sum3,sum4;
65439b95ed1SBarry Smith   register Scalar x1,x2,x3,x4;
65539b95ed1SBarry Smith   int             mbs=a->mbs,i,*idx,*ii;
65639b95ed1SBarry Smith   int             j,n,ierr;
65739b95ed1SBarry Smith 
65839b95ed1SBarry Smith   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
65939b95ed1SBarry Smith   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
66039b95ed1SBarry Smith 
66139b95ed1SBarry Smith   idx   = a->j;
66239b95ed1SBarry Smith   v     = a->a;
66339b95ed1SBarry Smith   ii    = a->i;
66439b95ed1SBarry Smith 
665119a934aSSatish Balay   for ( i=0; i<mbs; i++ ) {
666119a934aSSatish Balay     n  = ii[1] - ii[0]; ii++;
667119a934aSSatish Balay     sum1 = 0.0; sum2 = 0.0; sum3 = 0.0; sum4 = 0.0;
668119a934aSSatish Balay     for ( j=0; j<n; j++ ) {
669119a934aSSatish Balay       xb = x + 4*(*idx++);
670119a934aSSatish Balay       x1 = xb[0]; x2 = xb[1]; x3 = xb[2]; x4 = xb[3];
671119a934aSSatish Balay       sum1 += v[0]*x1 + v[4]*x2 + v[8]*x3   + v[12]*x4;
672119a934aSSatish Balay       sum2 += v[1]*x1 + v[5]*x2 + v[9]*x3   + v[13]*x4;
673119a934aSSatish Balay       sum3 += v[2]*x1 + v[6]*x2 + v[10]*x3  + v[14]*x4;
674119a934aSSatish Balay       sum4 += v[3]*x1 + v[7]*x2 + v[11]*x3  + v[15]*x4;
675119a934aSSatish Balay       v += 16;
676119a934aSSatish Balay     }
6771a6a6d98SBarry Smith     z[0] = sum1; z[1] = sum2; z[2] = sum3; z[3] = sum4;
678119a934aSSatish Balay     z += 4;
679119a934aSSatish Balay   }
68039b95ed1SBarry Smith   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
68139b95ed1SBarry Smith   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
68239b95ed1SBarry Smith   PLogFlops(32*a->nz - a->m);
68339b95ed1SBarry Smith   return 0;
68439b95ed1SBarry Smith }
68539b95ed1SBarry Smith 
68639b95ed1SBarry Smith static int MatMult_SeqBAIJ_5(Mat A,Vec xx,Vec zz)
68739b95ed1SBarry Smith {
68839b95ed1SBarry Smith   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
68939b95ed1SBarry Smith   Scalar          *xg,*zg;
69039b95ed1SBarry Smith   register Scalar *x,*z,*v,*xb,sum1,sum2,sum3,sum4,sum5;
69139b95ed1SBarry Smith   register Scalar x1,x2,x3,x4,x5;
69239b95ed1SBarry Smith   int             mbs=a->mbs,i,*idx,*ii,j,n,ierr;
69339b95ed1SBarry Smith 
69439b95ed1SBarry Smith   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
69539b95ed1SBarry Smith   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
69639b95ed1SBarry Smith 
69739b95ed1SBarry Smith   idx   = a->j;
69839b95ed1SBarry Smith   v     = a->a;
69939b95ed1SBarry Smith   ii    = a->i;
70039b95ed1SBarry Smith 
701119a934aSSatish Balay   for ( i=0; i<mbs; i++ ) {
702119a934aSSatish Balay     n  = ii[1] - ii[0]; ii++;
703119a934aSSatish Balay     sum1 = 0.0; sum2 = 0.0; sum3 = 0.0; sum4 = 0.0; sum5 = 0.0;
704119a934aSSatish Balay     for ( j=0; j<n; j++ ) {
705119a934aSSatish Balay       xb = x + 5*(*idx++);
706119a934aSSatish Balay       x1 = xb[0]; x2 = xb[1]; x3 = xb[2]; x4 = xb[3]; x5 = xb[4];
707119a934aSSatish Balay       sum1 += v[0]*x1 + v[5]*x2 + v[10]*x3  + v[15]*x4 + v[20]*x5;
708119a934aSSatish Balay       sum2 += v[1]*x1 + v[6]*x2 + v[11]*x3  + v[16]*x4 + v[21]*x5;
709119a934aSSatish Balay       sum3 += v[2]*x1 + v[7]*x2 + v[12]*x3  + v[17]*x4 + v[22]*x5;
710119a934aSSatish Balay       sum4 += v[3]*x1 + v[8]*x2 + v[13]*x3  + v[18]*x4 + v[23]*x5;
711119a934aSSatish Balay       sum5 += v[4]*x1 + v[9]*x2 + v[14]*x3  + v[19]*x4 + v[24]*x5;
712119a934aSSatish Balay       v += 25;
713119a934aSSatish Balay     }
7141a6a6d98SBarry Smith     z[0] = sum1; z[1] = sum2; z[2] = sum3; z[3] = sum4; z[4] = sum5;
715119a934aSSatish Balay     z += 5;
716119a934aSSatish Balay   }
71739b95ed1SBarry Smith   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
71839b95ed1SBarry Smith   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
71939b95ed1SBarry Smith   PLogFlops(50*a->nz - a->m);
72039b95ed1SBarry Smith   return 0;
72139b95ed1SBarry Smith }
72239b95ed1SBarry Smith 
72339b95ed1SBarry Smith static int MatMult_SeqBAIJ_N(Mat A,Vec xx,Vec zz)
72439b95ed1SBarry Smith {
72539b95ed1SBarry Smith   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
72639b95ed1SBarry Smith   Scalar          *xg,*zg;
72739b95ed1SBarry Smith   register Scalar *x,*z,*v,*xb;
72839b95ed1SBarry Smith   int             mbs=a->mbs,i,*idx,*ii,bs=a->bs,j,n,bs2=a->bs2,ierr;
7291a6a6d98SBarry Smith   int             _One = 1,ncols,k; Scalar _DOne = 1.0, *work,*workt, _DZero = 0.0;
73039b95ed1SBarry Smith 
73139b95ed1SBarry Smith   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
73239b95ed1SBarry Smith   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
73339b95ed1SBarry Smith 
73439b95ed1SBarry Smith   idx   = a->j;
73539b95ed1SBarry Smith   v     = a->a;
73639b95ed1SBarry Smith   ii    = a->i;
73739b95ed1SBarry Smith 
73839b95ed1SBarry Smith 
739119a934aSSatish Balay   if (!a->mult_work) {
7403b547af2SSatish Balay     k = PetscMax(a->m,a->n);
741*2b3076dcSSatish Balay     a->mult_work = (Scalar *) PetscMalloc((k+1)*sizeof(Scalar));CHKPTRQ(a->mult_work);
742119a934aSSatish Balay   }
743119a934aSSatish Balay   work = a->mult_work;
744119a934aSSatish Balay   for ( i=0; i<mbs; i++ ) {
745119a934aSSatish Balay     n     = ii[1] - ii[0]; ii++;
746119a934aSSatish Balay     ncols = n*bs;
747119a934aSSatish Balay     workt = work;
748119a934aSSatish Balay     for ( j=0; j<n; j++ ) {
749119a934aSSatish Balay       xb = x + bs*(*idx++);
750119a934aSSatish Balay       for ( k=0; k<bs; k++ ) workt[k] = xb[k];
751119a934aSSatish Balay       workt += bs;
752119a934aSSatish Balay     }
7531a6a6d98SBarry Smith     LAgemv_("N",&bs,&ncols,&_DOne,v,&bs,work,&_One,&_DZero,z,&_One);
754119a934aSSatish Balay     v += n*bs2;
755119a934aSSatish Balay     z += bs;
756119a934aSSatish Balay   }
7570419e6cdSSatish Balay    ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
7580419e6cdSSatish Balay   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
7591a6a6d98SBarry Smith   PLogFlops(2*a->nz*bs2 - a->m);
760bb42667fSSatish Balay   return 0;
761bb42667fSSatish Balay }
762bb42667fSSatish Balay 
763f44d3a6dSSatish Balay static int MatMultAdd_SeqBAIJ_1(Mat A,Vec xx,Vec yy,Vec zz)
764f44d3a6dSSatish Balay {
765f44d3a6dSSatish Balay   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
766f44d3a6dSSatish Balay   Scalar          *xg,*yg,*zg;
767f44d3a6dSSatish Balay   register Scalar *x,*y,*z,*v,sum;
768f44d3a6dSSatish Balay   int             mbs=a->mbs,i,*idx,*ii,n,ierr;
769f44d3a6dSSatish Balay 
770f44d3a6dSSatish Balay   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
771f44d3a6dSSatish Balay   ierr = VecGetArray(yy,&yg); CHKERRQ(ierr); y = yg;
772f44d3a6dSSatish Balay   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
773f44d3a6dSSatish Balay 
774f44d3a6dSSatish Balay   idx   = a->j;
775f44d3a6dSSatish Balay   v     = a->a;
776f44d3a6dSSatish Balay   ii    = a->i;
777f44d3a6dSSatish Balay 
778f44d3a6dSSatish Balay   for ( i=0; i<mbs; i++ ) {
779f44d3a6dSSatish Balay     n    = ii[1] - ii[0]; ii++;
780f44d3a6dSSatish Balay     sum  = y[i];
781f44d3a6dSSatish Balay     while (n--) sum += *v++ * x[*idx++];
782f44d3a6dSSatish Balay     z[i] = sum;
783f44d3a6dSSatish Balay   }
784f44d3a6dSSatish Balay   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
785f44d3a6dSSatish Balay   ierr = VecRestoreArray(yy,&yg); CHKERRQ(ierr);
786f44d3a6dSSatish Balay   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
787f44d3a6dSSatish Balay   PLogFlops(2*a->nz);
788f44d3a6dSSatish Balay   return 0;
789f44d3a6dSSatish Balay }
790f44d3a6dSSatish Balay 
791f44d3a6dSSatish Balay static int MatMultAdd_SeqBAIJ_2(Mat A,Vec xx,Vec yy,Vec zz)
792f44d3a6dSSatish Balay {
793f44d3a6dSSatish Balay   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
794f44d3a6dSSatish Balay   Scalar          *xg,*yg,*zg;
795f44d3a6dSSatish Balay   register Scalar *x,*y,*z,*v,*xb,sum1,sum2;
796f44d3a6dSSatish Balay   register Scalar x1,x2;
797f44d3a6dSSatish Balay   int             mbs=a->mbs,i,*idx,*ii;
798f44d3a6dSSatish Balay   int             j,n,ierr;
799f44d3a6dSSatish Balay 
800f44d3a6dSSatish Balay   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
801f44d3a6dSSatish Balay   ierr = VecGetArray(yy,&yg); CHKERRQ(ierr); y = yg;
802f44d3a6dSSatish Balay   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
803f44d3a6dSSatish Balay 
804f44d3a6dSSatish Balay   idx   = a->j;
805f44d3a6dSSatish Balay   v     = a->a;
806f44d3a6dSSatish Balay   ii    = a->i;
807f44d3a6dSSatish Balay 
808f44d3a6dSSatish Balay   for ( i=0; i<mbs; i++ ) {
809f44d3a6dSSatish Balay     n  = ii[1] - ii[0]; ii++;
810f44d3a6dSSatish Balay     sum1 = y[0]; sum2 = y[1];
811f44d3a6dSSatish Balay     for ( j=0; j<n; j++ ) {
812f44d3a6dSSatish Balay       xb = x + 2*(*idx++); x1 = xb[0]; x2 = xb[1];
813f44d3a6dSSatish Balay       sum1 += v[0]*x1 + v[2]*x2;
814f44d3a6dSSatish Balay       sum2 += v[1]*x1 + v[3]*x2;
815f44d3a6dSSatish Balay       v += 4;
816f44d3a6dSSatish Balay     }
817f44d3a6dSSatish Balay     z[0] = sum1; z[1] = sum2;
818f44d3a6dSSatish Balay     z += 2; y += 2;
819f44d3a6dSSatish Balay   }
820f44d3a6dSSatish Balay   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
821f44d3a6dSSatish Balay   ierr = VecRestoreArray(yy,&yg); CHKERRQ(ierr);
822f44d3a6dSSatish Balay   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
823f44d3a6dSSatish Balay   PLogFlops(4*a->nz);
824f44d3a6dSSatish Balay   return 0;
825f44d3a6dSSatish Balay }
826f44d3a6dSSatish Balay 
827f44d3a6dSSatish Balay static int MatMultAdd_SeqBAIJ_3(Mat A,Vec xx,Vec yy,Vec zz)
828f44d3a6dSSatish Balay {
829f44d3a6dSSatish Balay   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
830f44d3a6dSSatish Balay   Scalar          *xg,*yg,*zg;
831f44d3a6dSSatish Balay   register Scalar *x,*y,*z,*v,*xb,sum1,sum2,sum3,x1,x2,x3;
832f44d3a6dSSatish Balay   int             mbs=a->mbs,i,*idx,*ii,j,n,ierr;
833f44d3a6dSSatish Balay 
834f44d3a6dSSatish Balay   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
835f44d3a6dSSatish Balay   ierr = VecGetArray(yy,&yg); CHKERRQ(ierr); y = yg;
836f44d3a6dSSatish Balay   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
837f44d3a6dSSatish Balay 
838f44d3a6dSSatish Balay   idx   = a->j;
839f44d3a6dSSatish Balay   v     = a->a;
840f44d3a6dSSatish Balay   ii    = a->i;
841f44d3a6dSSatish Balay 
842f44d3a6dSSatish Balay   for ( i=0; i<mbs; i++ ) {
843f44d3a6dSSatish Balay     n  = ii[1] - ii[0]; ii++;
844f44d3a6dSSatish Balay     sum1 = y[0]; sum2 = y[1]; sum3 = y[2];
845f44d3a6dSSatish Balay     for ( j=0; j<n; j++ ) {
846f44d3a6dSSatish Balay       xb = x + 3*(*idx++); x1 = xb[0]; x2 = xb[1]; x3 = xb[2];
847f44d3a6dSSatish Balay       sum1 += v[0]*x1 + v[3]*x2 + v[6]*x3;
848f44d3a6dSSatish Balay       sum2 += v[1]*x1 + v[4]*x2 + v[7]*x3;
849f44d3a6dSSatish Balay       sum3 += v[2]*x1 + v[5]*x2 + v[8]*x3;
850f44d3a6dSSatish Balay       v += 9;
851f44d3a6dSSatish Balay     }
852f44d3a6dSSatish Balay     z[0] = sum1; z[1] = sum2; z[2] = sum3;
853f44d3a6dSSatish Balay     z += 3; y += 3;
854f44d3a6dSSatish Balay   }
855f44d3a6dSSatish Balay   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
856f44d3a6dSSatish Balay   ierr = VecRestoreArray(yy,&yg); CHKERRQ(ierr);
857f44d3a6dSSatish Balay   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
858f44d3a6dSSatish Balay   PLogFlops(18*a->nz);
859f44d3a6dSSatish Balay   return 0;
860f44d3a6dSSatish Balay }
861f44d3a6dSSatish Balay 
862f44d3a6dSSatish Balay static int MatMultAdd_SeqBAIJ_4(Mat A,Vec xx,Vec yy,Vec zz)
863f44d3a6dSSatish Balay {
864f44d3a6dSSatish Balay   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
865f44d3a6dSSatish Balay   Scalar          *xg,*yg,*zg;
866f44d3a6dSSatish Balay   register Scalar *x,*y,*z,*v,*xb,sum1,sum2,sum3,sum4;
867f44d3a6dSSatish Balay   register Scalar x1,x2,x3,x4;
868f44d3a6dSSatish Balay   int             mbs=a->mbs,i,*idx,*ii;
869f44d3a6dSSatish Balay   int             j,n,ierr;
870f44d3a6dSSatish Balay 
871f44d3a6dSSatish Balay   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
872f44d3a6dSSatish Balay   ierr = VecGetArray(yy,&yg); CHKERRQ(ierr); y = yg;
873f44d3a6dSSatish Balay   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
874f44d3a6dSSatish Balay 
875f44d3a6dSSatish Balay   idx   = a->j;
876f44d3a6dSSatish Balay   v     = a->a;
877f44d3a6dSSatish Balay   ii    = a->i;
878f44d3a6dSSatish Balay 
879f44d3a6dSSatish Balay   for ( i=0; i<mbs; i++ ) {
880f44d3a6dSSatish Balay     n  = ii[1] - ii[0]; ii++;
881f44d3a6dSSatish Balay     sum1 = y[0]; sum2 = y[1]; sum3 = y[2]; sum4 = y[3];
882f44d3a6dSSatish Balay     for ( j=0; j<n; j++ ) {
883f44d3a6dSSatish Balay       xb = x + 4*(*idx++);
884f44d3a6dSSatish Balay       x1 = xb[0]; x2 = xb[1]; x3 = xb[2]; x4 = xb[3];
885f44d3a6dSSatish Balay       sum1 += v[0]*x1 + v[4]*x2 + v[8]*x3   + v[12]*x4;
886f44d3a6dSSatish Balay       sum2 += v[1]*x1 + v[5]*x2 + v[9]*x3   + v[13]*x4;
887f44d3a6dSSatish Balay       sum3 += v[2]*x1 + v[6]*x2 + v[10]*x3  + v[14]*x4;
888f44d3a6dSSatish Balay       sum4 += v[3]*x1 + v[7]*x2 + v[11]*x3  + v[15]*x4;
889f44d3a6dSSatish Balay       v += 16;
890f44d3a6dSSatish Balay     }
891f44d3a6dSSatish Balay     z[0] = sum1; z[1] = sum2; z[2] = sum3; z[3] = sum4;
892f44d3a6dSSatish Balay     z += 4; y += 4;
893f44d3a6dSSatish Balay   }
894f44d3a6dSSatish Balay   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
895f44d3a6dSSatish Balay   ierr = VecRestoreArray(yy,&yg); CHKERRQ(ierr);
896f44d3a6dSSatish Balay   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
897f44d3a6dSSatish Balay   PLogFlops(32*a->nz);
898f44d3a6dSSatish Balay   return 0;
899f44d3a6dSSatish Balay }
900f44d3a6dSSatish Balay 
901f44d3a6dSSatish Balay static int MatMultAdd_SeqBAIJ_5(Mat A,Vec xx,Vec yy,Vec zz)
902f44d3a6dSSatish Balay {
903f44d3a6dSSatish Balay   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
904f44d3a6dSSatish Balay   Scalar          *xg,*yg,*zg;
905f44d3a6dSSatish Balay   register Scalar *x,*y,*z,*v,*xb,sum1,sum2,sum3,sum4,sum5;
906f44d3a6dSSatish Balay   register Scalar x1,x2,x3,x4,x5;
907f44d3a6dSSatish Balay   int             mbs=a->mbs,i,*idx,*ii,j,n,ierr;
908f44d3a6dSSatish Balay 
909f44d3a6dSSatish Balay   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
910f44d3a6dSSatish Balay   ierr = VecGetArray(yy,&yg); CHKERRQ(ierr); y = yg;
911f44d3a6dSSatish Balay   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
912f44d3a6dSSatish Balay 
913f44d3a6dSSatish Balay   idx   = a->j;
914f44d3a6dSSatish Balay   v     = a->a;
915f44d3a6dSSatish Balay   ii    = a->i;
916f44d3a6dSSatish Balay 
917f44d3a6dSSatish Balay   for ( i=0; i<mbs; i++ ) {
918f44d3a6dSSatish Balay     n  = ii[1] - ii[0]; ii++;
919f44d3a6dSSatish Balay     sum1 = y[0]; sum2 = y[1]; sum3 = y[2]; sum4 = y[3]; sum5 = y[4];
920f44d3a6dSSatish Balay     for ( j=0; j<n; j++ ) {
921f44d3a6dSSatish Balay       xb = x + 5*(*idx++);
922f44d3a6dSSatish Balay       x1 = xb[0]; x2 = xb[1]; x3 = xb[2]; x4 = xb[3]; x5 = xb[4];
923f44d3a6dSSatish Balay       sum1 += v[0]*x1 + v[5]*x2 + v[10]*x3  + v[15]*x4 + v[20]*x5;
924f44d3a6dSSatish Balay       sum2 += v[1]*x1 + v[6]*x2 + v[11]*x3  + v[16]*x4 + v[21]*x5;
925f44d3a6dSSatish Balay       sum3 += v[2]*x1 + v[7]*x2 + v[12]*x3  + v[17]*x4 + v[22]*x5;
926f44d3a6dSSatish Balay       sum4 += v[3]*x1 + v[8]*x2 + v[13]*x3  + v[18]*x4 + v[23]*x5;
927f44d3a6dSSatish Balay       sum5 += v[4]*x1 + v[9]*x2 + v[14]*x3  + v[19]*x4 + v[24]*x5;
928f44d3a6dSSatish Balay       v += 25;
929f44d3a6dSSatish Balay     }
930f44d3a6dSSatish Balay     z[0] = sum1; z[1] = sum2; z[2] = sum3; z[3] = sum4; z[4] = sum5;
931f44d3a6dSSatish Balay     z += 5; y += 5;
932f44d3a6dSSatish Balay   }
933f44d3a6dSSatish Balay   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
934f44d3a6dSSatish Balay   ierr = VecRestoreArray(yy,&yg); CHKERRQ(ierr);
935f44d3a6dSSatish Balay   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
936f44d3a6dSSatish Balay   PLogFlops(50*a->nz);
937f44d3a6dSSatish Balay   return 0;
938f44d3a6dSSatish Balay }
939f44d3a6dSSatish Balay 
940f44d3a6dSSatish Balay static int MatMultAdd_SeqBAIJ_N(Mat A,Vec xx,Vec yy,Vec zz)
941f44d3a6dSSatish Balay {
942f44d3a6dSSatish Balay   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
943f44d3a6dSSatish Balay   Scalar          *xg,*zg;
944f44d3a6dSSatish Balay   register Scalar *x,*z,*v,*xb;
945f44d3a6dSSatish Balay   int             mbs=a->mbs,i,*idx,*ii,bs=a->bs,j,n,bs2=a->bs2,ierr;
946f44d3a6dSSatish Balay   int             _One = 1,ncols,k; Scalar _DOne = 1.0, *work,*workt;
947f44d3a6dSSatish Balay 
948f44d3a6dSSatish Balay   if ( xx != yy) { ierr = VecCopy(yy,zz); CHKERRQ(ierr); }
949f44d3a6dSSatish Balay 
950f44d3a6dSSatish Balay   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
951f44d3a6dSSatish Balay   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
952f44d3a6dSSatish Balay 
953f44d3a6dSSatish Balay   idx   = a->j;
954f44d3a6dSSatish Balay   v     = a->a;
955f44d3a6dSSatish Balay   ii    = a->i;
956f44d3a6dSSatish Balay 
957f44d3a6dSSatish Balay 
958f44d3a6dSSatish Balay   if (!a->mult_work) {
959f44d3a6dSSatish Balay     k = PetscMax(a->m,a->n);
960f44d3a6dSSatish Balay     a->mult_work = (Scalar *) PetscMalloc(k*sizeof(Scalar));CHKPTRQ(a->mult_work);
961f44d3a6dSSatish Balay   }
962f44d3a6dSSatish Balay   work = a->mult_work;
963f44d3a6dSSatish Balay   for ( i=0; i<mbs; i++ ) {
964f44d3a6dSSatish Balay     n     = ii[1] - ii[0]; ii++;
965f44d3a6dSSatish Balay     ncols = n*bs;
966f44d3a6dSSatish Balay     workt = work;
967f44d3a6dSSatish Balay     for ( j=0; j<n; j++ ) {
968f44d3a6dSSatish Balay       xb = x + bs*(*idx++);
969f44d3a6dSSatish Balay       for ( k=0; k<bs; k++ ) workt[k] = xb[k];
970f44d3a6dSSatish Balay       workt += bs;
971f44d3a6dSSatish Balay     }
972f44d3a6dSSatish Balay     LAgemv_("N",&bs,&ncols,&_DOne,v,&bs,work,&_One,&_DOne,z,&_One);
973f44d3a6dSSatish Balay     v += n*bs2;
974f44d3a6dSSatish Balay     z += bs;
975f44d3a6dSSatish Balay   }
976f44d3a6dSSatish Balay   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
977f44d3a6dSSatish Balay   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
978f44d3a6dSSatish Balay   PLogFlops(2*a->nz*bs2 );
979f44d3a6dSSatish Balay   return 0;
980f44d3a6dSSatish Balay }
981f44d3a6dSSatish Balay 
9821a6a6d98SBarry Smith static int MatMultTrans_SeqBAIJ(Mat A,Vec xx,Vec zz)
983bb42667fSSatish Balay {
984bb42667fSSatish Balay   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
9851a6a6d98SBarry Smith   Scalar          *xg,*zg,*zb;
986bb42667fSSatish Balay   register Scalar *x,*z,*v,*xb,x1,x2,x3,x4,x5;
987bb1453f0SSatish Balay   int             mbs=a->mbs,i,*idx,*ii,*ai=a->i,rval,N=a->n;
9889df24120SSatish Balay   int             bs=a->bs,j,n,bs2=a->bs2,*ib,ierr;
989119a934aSSatish Balay 
990119a934aSSatish Balay 
991bb42667fSSatish Balay   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
992bb42667fSSatish Balay   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
993bb1453f0SSatish Balay   PetscMemzero(z,N*sizeof(Scalar));
994bb42667fSSatish Balay 
995119a934aSSatish Balay   idx   = a->j;
996119a934aSSatish Balay   v     = a->a;
997119a934aSSatish Balay   ii    = a->i;
998119a934aSSatish Balay 
999119a934aSSatish Balay   switch (bs) {
1000119a934aSSatish Balay   case 1:
1001119a934aSSatish Balay     for ( i=0; i<mbs; i++ ) {
1002119a934aSSatish Balay       n  = ii[1] - ii[0]; ii++;
1003119a934aSSatish Balay       xb = x + i; x1 = xb[0];
1004119a934aSSatish Balay       ib = idx + ai[i];
1005119a934aSSatish Balay       for ( j=0; j<n; j++ ) {
1006bb1453f0SSatish Balay         rval    = ib[j];
1007bb1453f0SSatish Balay         z[rval] += *v++ * x1;
1008119a934aSSatish Balay       }
1009119a934aSSatish Balay     }
1010119a934aSSatish Balay     break;
1011119a934aSSatish Balay   case 2:
1012119a934aSSatish Balay     for ( i=0; i<mbs; i++ ) {
1013119a934aSSatish Balay       n  = ii[1] - ii[0]; ii++;
1014119a934aSSatish Balay       xb = x + 2*i; x1 = xb[0]; x2 = xb[1];
1015119a934aSSatish Balay       ib = idx + ai[i];
1016119a934aSSatish Balay       for ( j=0; j<n; j++ ) {
1017119a934aSSatish Balay         rval      = ib[j]*2;
1018bb1453f0SSatish Balay         z[rval++] += v[0]*x1 + v[1]*x2;
1019bb1453f0SSatish Balay         z[rval++] += v[2]*x1 + v[3]*x2;
1020119a934aSSatish Balay         v += 4;
1021119a934aSSatish Balay       }
1022119a934aSSatish Balay     }
1023119a934aSSatish Balay     break;
1024119a934aSSatish Balay   case 3:
1025119a934aSSatish Balay     for ( i=0; i<mbs; i++ ) {
1026119a934aSSatish Balay       n  = ii[1] - ii[0]; ii++;
1027119a934aSSatish Balay       xb = x + 3*i; x1 = xb[0]; x2 = xb[1]; x3 = xb[2];
1028119a934aSSatish Balay       ib = idx + ai[i];
1029119a934aSSatish Balay       for ( j=0; j<n; j++ ) {
1030119a934aSSatish Balay         rval      = ib[j]*3;
1031bb1453f0SSatish Balay         z[rval++] += v[0]*x1 + v[1]*x2 + v[2]*x3;
1032bb1453f0SSatish Balay         z[rval++] += v[3]*x1 + v[4]*x2 + v[5]*x3;
1033bb1453f0SSatish Balay         z[rval++] += v[6]*x1 + v[7]*x2 + v[8]*x3;
1034119a934aSSatish Balay         v += 9;
1035119a934aSSatish Balay       }
1036119a934aSSatish Balay     }
1037119a934aSSatish Balay     break;
1038119a934aSSatish Balay   case 4:
1039119a934aSSatish Balay     for ( i=0; i<mbs; i++ ) {
1040119a934aSSatish Balay       n  = ii[1] - ii[0]; ii++;
1041119a934aSSatish Balay       xb = x + 4*i; x1 = xb[0]; x2 = xb[1]; x3 = xb[2]; x4 = xb[3];
1042119a934aSSatish Balay       ib = idx + ai[i];
1043119a934aSSatish Balay       for ( j=0; j<n; j++ ) {
1044119a934aSSatish Balay         rval      = ib[j]*4;
1045bb1453f0SSatish Balay         z[rval++] +=  v[0]*x1 +  v[1]*x2 +  v[2]*x3 +  v[3]*x4;
1046bb1453f0SSatish Balay         z[rval++] +=  v[4]*x1 +  v[5]*x2 +  v[6]*x3 +  v[7]*x4;
1047bb1453f0SSatish Balay         z[rval++] +=  v[8]*x1 +  v[9]*x2 + v[10]*x3 + v[11]*x4;
1048bb1453f0SSatish Balay         z[rval++] += v[12]*x1 + v[13]*x2 + v[14]*x3 + v[15]*x4;
1049119a934aSSatish Balay         v += 16;
1050119a934aSSatish Balay       }
1051119a934aSSatish Balay     }
1052119a934aSSatish Balay     break;
1053119a934aSSatish Balay   case 5:
1054119a934aSSatish Balay     for ( i=0; i<mbs; i++ ) {
1055119a934aSSatish Balay       n  = ii[1] - ii[0]; ii++;
1056119a934aSSatish Balay       xb = x + 5*i; x1 = xb[0]; x2 = xb[1]; x3 = xb[2];
1057119a934aSSatish Balay       x4 = xb[3];   x5 = xb[4];
1058119a934aSSatish Balay       ib = idx + ai[i];
1059119a934aSSatish Balay       for ( j=0; j<n; j++ ) {
1060119a934aSSatish Balay         rval      = ib[j]*5;
1061bb1453f0SSatish Balay         z[rval++] +=  v[0]*x1 +  v[1]*x2 +  v[2]*x3 +  v[3]*x4 +  v[4]*x5;
1062bb1453f0SSatish Balay         z[rval++] +=  v[5]*x1 +  v[6]*x2 +  v[7]*x3 +  v[8]*x4 +  v[9]*x5;
1063bb1453f0SSatish Balay         z[rval++] += v[10]*x1 + v[11]*x2 + v[12]*x3 + v[13]*x4 + v[14]*x5;
1064bb1453f0SSatish Balay         z[rval++] += v[15]*x1 + v[16]*x2 + v[17]*x3 + v[18]*x4 + v[19]*x5;
1065bb1453f0SSatish Balay         z[rval++] += v[20]*x1 + v[21]*x2 + v[22]*x3 + v[23]*x4 + v[24]*x5;
1066119a934aSSatish Balay         v += 25;
1067119a934aSSatish Balay       }
1068119a934aSSatish Balay     }
1069119a934aSSatish Balay     break;
1070119a934aSSatish Balay       /* block sizes larger then 5 by 5 are handled by BLAS */
1071119a934aSSatish Balay     default: {
1072119a934aSSatish Balay       int  _One = 1,ncols,k; Scalar _DOne = 1.0, *work,*workt;
1073119a934aSSatish Balay       if (!a->mult_work) {
10743b547af2SSatish Balay         k = PetscMax(a->m,a->n);
1075bb42667fSSatish Balay         a->mult_work = (Scalar *) PetscMalloc(k*sizeof(Scalar));
1076119a934aSSatish Balay         CHKPTRQ(a->mult_work);
1077119a934aSSatish Balay       }
1078119a934aSSatish Balay       work = a->mult_work;
1079119a934aSSatish Balay       for ( i=0; i<mbs; i++ ) {
1080119a934aSSatish Balay         n     = ii[1] - ii[0]; ii++;
1081119a934aSSatish Balay         ncols = n*bs;
1082119a934aSSatish Balay         PetscMemzero(work,ncols*sizeof(Scalar));
1083119a934aSSatish Balay         LAgemv_("T",&bs,&ncols,&_DOne,v,&bs,x,&_One,&_DOne,work,&_One);
1084119a934aSSatish Balay         v += n*bs2;
1085119a934aSSatish Balay         x += bs;
1086119a934aSSatish Balay         workt = work;
1087119a934aSSatish Balay         for ( j=0; j<n; j++ ) {
1088119a934aSSatish Balay           zb = z + bs*(*idx++);
1089bb1453f0SSatish Balay           for ( k=0; k<bs; k++ ) zb[k] += workt[k] ;
1090119a934aSSatish Balay           workt += bs;
1091119a934aSSatish Balay         }
1092119a934aSSatish Balay       }
1093119a934aSSatish Balay     }
1094119a934aSSatish Balay   }
10950419e6cdSSatish Balay   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
10960419e6cdSSatish Balay   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
1097faf6580fSSatish Balay   PLogFlops(2*a->nz*a->bs2 - a->n);
1098faf6580fSSatish Balay   return 0;
1099faf6580fSSatish Balay }
1100faf6580fSSatish Balay static int MatMultTransAdd_SeqBAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1101faf6580fSSatish Balay {
1102faf6580fSSatish Balay   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
1103faf6580fSSatish Balay   Scalar          *xg,*zg,*zb;
1104faf6580fSSatish Balay   register Scalar *x,*z,*v,*xb,x1,x2,x3,x4,x5;
1105faf6580fSSatish Balay   int             mbs=a->mbs,i,*idx,*ii,*ai=a->i,rval,N=a->n;
1106faf6580fSSatish Balay   int             bs=a->bs,j,n,bs2=a->bs2,*ib,ierr;
1107faf6580fSSatish Balay 
1108faf6580fSSatish Balay 
1109faf6580fSSatish Balay 
1110faf6580fSSatish Balay   ierr = VecGetArray(xx,&xg); CHKERRQ(ierr); x = xg;
1111faf6580fSSatish Balay   ierr = VecGetArray(zz,&zg); CHKERRQ(ierr); z = zg;
1112faf6580fSSatish Balay 
1113648c1d95SSatish Balay   if ( yy != zz ) { ierr = VecCopy(yy,zz); CHKERRQ(ierr); }
1114648c1d95SSatish Balay   else PetscMemzero(z,N*sizeof(Scalar));
1115648c1d95SSatish Balay 
1116faf6580fSSatish Balay 
1117faf6580fSSatish Balay   idx   = a->j;
1118faf6580fSSatish Balay   v     = a->a;
1119faf6580fSSatish Balay   ii    = a->i;
1120faf6580fSSatish Balay 
1121faf6580fSSatish Balay   switch (bs) {
1122faf6580fSSatish Balay   case 1:
1123faf6580fSSatish Balay     for ( i=0; i<mbs; i++ ) {
1124faf6580fSSatish Balay       n  = ii[1] - ii[0]; ii++;
1125faf6580fSSatish Balay       xb = x + i; x1 = xb[0];
1126faf6580fSSatish Balay       ib = idx + ai[i];
1127faf6580fSSatish Balay       for ( j=0; j<n; j++ ) {
1128faf6580fSSatish Balay         rval    = ib[j];
1129faf6580fSSatish Balay         z[rval] += *v++ * x1;
1130faf6580fSSatish Balay       }
1131faf6580fSSatish Balay     }
1132faf6580fSSatish Balay     break;
1133faf6580fSSatish Balay   case 2:
1134faf6580fSSatish Balay     for ( i=0; i<mbs; i++ ) {
1135faf6580fSSatish Balay       n  = ii[1] - ii[0]; ii++;
1136faf6580fSSatish Balay       xb = x + 2*i; x1 = xb[0]; x2 = xb[1];
1137faf6580fSSatish Balay       ib = idx + ai[i];
1138faf6580fSSatish Balay       for ( j=0; j<n; j++ ) {
1139faf6580fSSatish Balay         rval      = ib[j]*2;
1140faf6580fSSatish Balay         z[rval++] += v[0]*x1 + v[1]*x2;
1141faf6580fSSatish Balay         z[rval++] += v[2]*x1 + v[3]*x2;
1142faf6580fSSatish Balay         v += 4;
1143faf6580fSSatish Balay       }
1144faf6580fSSatish Balay     }
1145faf6580fSSatish Balay     break;
1146faf6580fSSatish Balay   case 3:
1147faf6580fSSatish Balay     for ( i=0; i<mbs; i++ ) {
1148faf6580fSSatish Balay       n  = ii[1] - ii[0]; ii++;
1149faf6580fSSatish Balay       xb = x + 3*i; x1 = xb[0]; x2 = xb[1]; x3 = xb[2];
1150faf6580fSSatish Balay       ib = idx + ai[i];
1151faf6580fSSatish Balay       for ( j=0; j<n; j++ ) {
1152faf6580fSSatish Balay         rval      = ib[j]*3;
1153faf6580fSSatish Balay         z[rval++] += v[0]*x1 + v[1]*x2 + v[2]*x3;
1154faf6580fSSatish Balay         z[rval++] += v[3]*x1 + v[4]*x2 + v[5]*x3;
1155faf6580fSSatish Balay         z[rval++] += v[6]*x1 + v[7]*x2 + v[8]*x3;
1156faf6580fSSatish Balay         v += 9;
1157faf6580fSSatish Balay       }
1158faf6580fSSatish Balay     }
1159faf6580fSSatish Balay     break;
1160faf6580fSSatish Balay   case 4:
1161faf6580fSSatish Balay     for ( i=0; i<mbs; i++ ) {
1162faf6580fSSatish Balay       n  = ii[1] - ii[0]; ii++;
1163faf6580fSSatish Balay       xb = x + 4*i; x1 = xb[0]; x2 = xb[1]; x3 = xb[2]; x4 = xb[3];
1164faf6580fSSatish Balay       ib = idx + ai[i];
1165faf6580fSSatish Balay       for ( j=0; j<n; j++ ) {
1166faf6580fSSatish Balay         rval      = ib[j]*4;
1167faf6580fSSatish Balay         z[rval++] +=  v[0]*x1 +  v[1]*x2 +  v[2]*x3 +  v[3]*x4;
1168faf6580fSSatish Balay         z[rval++] +=  v[4]*x1 +  v[5]*x2 +  v[6]*x3 +  v[7]*x4;
1169faf6580fSSatish Balay         z[rval++] +=  v[8]*x1 +  v[9]*x2 + v[10]*x3 + v[11]*x4;
1170faf6580fSSatish Balay         z[rval++] += v[12]*x1 + v[13]*x2 + v[14]*x3 + v[15]*x4;
1171faf6580fSSatish Balay         v += 16;
1172faf6580fSSatish Balay       }
1173faf6580fSSatish Balay     }
1174faf6580fSSatish Balay     break;
1175faf6580fSSatish Balay   case 5:
1176faf6580fSSatish Balay     for ( i=0; i<mbs; i++ ) {
1177faf6580fSSatish Balay       n  = ii[1] - ii[0]; ii++;
1178faf6580fSSatish Balay       xb = x + 5*i; x1 = xb[0]; x2 = xb[1]; x3 = xb[2];
1179faf6580fSSatish Balay       x4 = xb[3];   x5 = xb[4];
1180faf6580fSSatish Balay       ib = idx + ai[i];
1181faf6580fSSatish Balay       for ( j=0; j<n; j++ ) {
1182faf6580fSSatish Balay         rval      = ib[j]*5;
1183faf6580fSSatish Balay         z[rval++] +=  v[0]*x1 +  v[1]*x2 +  v[2]*x3 +  v[3]*x4 +  v[4]*x5;
1184faf6580fSSatish Balay         z[rval++] +=  v[5]*x1 +  v[6]*x2 +  v[7]*x3 +  v[8]*x4 +  v[9]*x5;
1185faf6580fSSatish Balay         z[rval++] += v[10]*x1 + v[11]*x2 + v[12]*x3 + v[13]*x4 + v[14]*x5;
1186faf6580fSSatish Balay         z[rval++] += v[15]*x1 + v[16]*x2 + v[17]*x3 + v[18]*x4 + v[19]*x5;
1187faf6580fSSatish Balay         z[rval++] += v[20]*x1 + v[21]*x2 + v[22]*x3 + v[23]*x4 + v[24]*x5;
1188faf6580fSSatish Balay         v += 25;
1189faf6580fSSatish Balay       }
1190faf6580fSSatish Balay     }
1191faf6580fSSatish Balay     break;
1192faf6580fSSatish Balay       /* block sizes larger then 5 by 5 are handled by BLAS */
1193faf6580fSSatish Balay     default: {
1194faf6580fSSatish Balay       int  _One = 1,ncols,k; Scalar _DOne = 1.0, *work,*workt;
1195faf6580fSSatish Balay       if (!a->mult_work) {
1196faf6580fSSatish Balay         k = PetscMax(a->m,a->n);
1197faf6580fSSatish Balay         a->mult_work = (Scalar *) PetscMalloc(k*sizeof(Scalar));
1198faf6580fSSatish Balay         CHKPTRQ(a->mult_work);
1199faf6580fSSatish Balay       }
1200faf6580fSSatish Balay       work = a->mult_work;
1201faf6580fSSatish Balay       for ( i=0; i<mbs; i++ ) {
1202faf6580fSSatish Balay         n     = ii[1] - ii[0]; ii++;
1203faf6580fSSatish Balay         ncols = n*bs;
1204faf6580fSSatish Balay         PetscMemzero(work,ncols*sizeof(Scalar));
1205faf6580fSSatish Balay         LAgemv_("T",&bs,&ncols,&_DOne,v,&bs,x,&_One,&_DOne,work,&_One);
1206faf6580fSSatish Balay         v += n*bs2;
1207faf6580fSSatish Balay         x += bs;
1208faf6580fSSatish Balay         workt = work;
1209faf6580fSSatish Balay         for ( j=0; j<n; j++ ) {
1210faf6580fSSatish Balay           zb = z + bs*(*idx++);
1211faf6580fSSatish Balay           for ( k=0; k<bs; k++ ) zb[k] += workt[k] ;
1212faf6580fSSatish Balay           workt += bs;
1213faf6580fSSatish Balay         }
1214faf6580fSSatish Balay       }
1215faf6580fSSatish Balay     }
1216faf6580fSSatish Balay   }
1217faf6580fSSatish Balay   ierr = VecRestoreArray(xx,&xg); CHKERRQ(ierr);
1218faf6580fSSatish Balay   ierr = VecRestoreArray(zz,&zg); CHKERRQ(ierr);
1219faf6580fSSatish Balay   PLogFlops(2*a->nz*a->bs2);
12202593348eSBarry Smith   return 0;
12212593348eSBarry Smith }
12222593348eSBarry Smith 
1223de6a44a3SBarry Smith static int MatGetInfo_SeqBAIJ(Mat A,MatInfoType flag,int *nz,int *nza,int *mem)
12242593348eSBarry Smith {
1225b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
12269df24120SSatish Balay   if (nz)  *nz  = a->bs2*a->nz;
1227bcd2baecSBarry Smith   if (nza) *nza = a->maxnz;
1228bcd2baecSBarry Smith   if (mem) *mem = (int)A->mem;
12292593348eSBarry Smith   return 0;
12302593348eSBarry Smith }
12312593348eSBarry Smith 
123291d316f6SSatish Balay static int MatEqual_SeqBAIJ(Mat A,Mat B, PetscTruth* flg)
123391d316f6SSatish Balay {
123491d316f6SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *)A->data, *b = (Mat_SeqBAIJ *)B->data;
123591d316f6SSatish Balay 
123691d316f6SSatish Balay   if (B->type !=MATSEQBAIJ)SETERRQ(1,"MatEqual_SeqBAIJ:Matrices must be same type");
123791d316f6SSatish Balay 
123891d316f6SSatish Balay   /* If the  matrix/block dimensions are not equal, or no of nonzeros or shift */
123991d316f6SSatish Balay   if ((a->m != b->m) || (a->n !=b->n) || (a->bs != b->bs)||
1240a7c10996SSatish Balay       (a->nz != b->nz)) {
124191d316f6SSatish Balay     *flg = PETSC_FALSE; return 0;
124291d316f6SSatish Balay   }
124391d316f6SSatish Balay 
124491d316f6SSatish Balay   /* if the a->i are the same */
124591d316f6SSatish Balay   if (PetscMemcmp(a->i,b->i, (a->mbs+1)*sizeof(int))) {
124691d316f6SSatish Balay     *flg = PETSC_FALSE; return 0;
124791d316f6SSatish Balay   }
124891d316f6SSatish Balay 
124991d316f6SSatish Balay   /* if a->j are the same */
125091d316f6SSatish Balay   if (PetscMemcmp(a->j,b->j,(a->nz)*sizeof(int))) {
125191d316f6SSatish Balay     *flg = PETSC_FALSE; return 0;
125291d316f6SSatish Balay   }
125391d316f6SSatish Balay 
125491d316f6SSatish Balay   /* if a->a are the same */
125591d316f6SSatish Balay   if (PetscMemcmp(a->a, b->a,(a->nz)*(a->bs)*(a->bs)*sizeof(Scalar))) {
125691d316f6SSatish Balay     *flg = PETSC_FALSE; return 0;
125791d316f6SSatish Balay   }
125891d316f6SSatish Balay   *flg = PETSC_TRUE;
125991d316f6SSatish Balay   return 0;
126091d316f6SSatish Balay 
126191d316f6SSatish Balay }
126291d316f6SSatish Balay 
126391d316f6SSatish Balay static int MatGetDiagonal_SeqBAIJ(Mat A,Vec v)
126491d316f6SSatish Balay {
126591d316f6SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
12667e67e3f9SSatish Balay   int         i,j,k,n,row,bs,*ai,*aj,ambs,bs2;
126717e48fc4SSatish Balay   Scalar      *x, zero = 0.0,*aa,*aa_j;
126817e48fc4SSatish Balay 
126917e48fc4SSatish Balay   bs   = a->bs;
127017e48fc4SSatish Balay   aa   = a->a;
127117e48fc4SSatish Balay   ai   = a->i;
127217e48fc4SSatish Balay   aj   = a->j;
127317e48fc4SSatish Balay   ambs = a->mbs;
12749df24120SSatish Balay   bs2  = a->bs2;
127591d316f6SSatish Balay 
127691d316f6SSatish Balay   VecSet(&zero,v);
127791d316f6SSatish Balay   VecGetArray(v,&x); VecGetLocalSize(v,&n);
12789867e207SSatish Balay   if (n != a->m) SETERRQ(1,"MatGetDiagonal_SeqBAIJ:Nonconforming matrix and vector");
127917e48fc4SSatish Balay   for ( i=0; i<ambs; i++ ) {
128017e48fc4SSatish Balay     for ( j=ai[i]; j<ai[i+1]; j++ ) {
128117e48fc4SSatish Balay       if (aj[j] == i) {
128217e48fc4SSatish Balay         row  = i*bs;
12837e67e3f9SSatish Balay         aa_j = aa+j*bs2;
12847e67e3f9SSatish Balay         for (k=0; k<bs2; k+=(bs+1),row++) x[row] = aa_j[k];
128591d316f6SSatish Balay         break;
128691d316f6SSatish Balay       }
128791d316f6SSatish Balay     }
128891d316f6SSatish Balay   }
128991d316f6SSatish Balay   return 0;
129091d316f6SSatish Balay }
129191d316f6SSatish Balay 
12929867e207SSatish Balay static int MatDiagonalScale_SeqBAIJ(Mat A,Vec ll,Vec rr)
12939867e207SSatish Balay {
12949867e207SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
12959867e207SSatish Balay   Scalar      *l,*r,x,*v,*aa,*li,*ri;
12967e67e3f9SSatish Balay   int         i,j,k,lm,rn,M,m,n,*ai,*aj,mbs,tmp,bs,bs2;
12979867e207SSatish Balay 
12989867e207SSatish Balay   ai  = a->i;
12999867e207SSatish Balay   aj  = a->j;
13009867e207SSatish Balay   aa  = a->a;
13019867e207SSatish Balay   m   = a->m;
13029867e207SSatish Balay   n   = a->n;
13039867e207SSatish Balay   bs  = a->bs;
13049867e207SSatish Balay   mbs = a->mbs;
13059df24120SSatish Balay   bs2 = a->bs2;
13069867e207SSatish Balay   if (ll) {
13079867e207SSatish Balay     VecGetArray(ll,&l); VecGetSize(ll,&lm);
13089867e207SSatish Balay     if (lm != m) SETERRQ(1,"MatDiagonalScale_SeqBAIJ:Left scaling vector wrong length");
13099867e207SSatish Balay     for ( i=0; i<mbs; i++ ) { /* for each block row */
13109867e207SSatish Balay       M  = ai[i+1] - ai[i];
13119867e207SSatish Balay       li = l + i*bs;
13127e67e3f9SSatish Balay       v  = aa + bs2*ai[i];
13139867e207SSatish Balay       for ( j=0; j<M; j++ ) { /* for each block */
13147e67e3f9SSatish Balay         for ( k=0; k<bs2; k++ ) {
13159867e207SSatish Balay           (*v++) *= li[k%bs];
13169867e207SSatish Balay         }
13179867e207SSatish Balay       }
13189867e207SSatish Balay     }
13199867e207SSatish Balay   }
13209867e207SSatish Balay 
13219867e207SSatish Balay   if (rr) {
13229867e207SSatish Balay     VecGetArray(rr,&r); VecGetSize(rr,&rn);
13239867e207SSatish Balay     if (rn != n) SETERRQ(1,"MatDiagonalScale_SeqBAIJ:Right scaling vector wrong length");
13249867e207SSatish Balay     for ( i=0; i<mbs; i++ ) { /* for each block row */
13259867e207SSatish Balay       M  = ai[i+1] - ai[i];
13267e67e3f9SSatish Balay       v  = aa + bs2*ai[i];
13279867e207SSatish Balay       for ( j=0; j<M; j++ ) { /* for each block */
13289867e207SSatish Balay         ri = r + bs*aj[ai[i]+j];
13299867e207SSatish Balay         for ( k=0; k<bs; k++ ) {
13309867e207SSatish Balay           x = ri[k];
13319867e207SSatish Balay           for ( tmp=0; tmp<bs; tmp++ ) (*v++) *= x;
13329867e207SSatish Balay         }
13339867e207SSatish Balay       }
13349867e207SSatish Balay     }
13359867e207SSatish Balay   }
13369867e207SSatish Balay   return 0;
13379867e207SSatish Balay }
13389867e207SSatish Balay 
13399867e207SSatish Balay 
1340b6490206SBarry Smith extern int MatLUFactorSymbolic_SeqBAIJ(Mat,IS,IS,double,Mat*);
1341b6490206SBarry Smith extern int MatLUFactor_SeqBAIJ(Mat,IS,IS,double);
13422a38ea04SSatish Balay extern int MatIncreaseOverlap_SeqBAIJ(Mat,int,IS*,int);
1343736121d4SSatish Balay extern int MatGetSubMatrix_SeqBAIJ(Mat,IS,IS,MatGetSubMatrixCall,Mat*);
1344736121d4SSatish Balay extern int MatGetSubMatrices_SeqBAIJ(Mat,int,IS*,IS*,MatGetSubMatrixCall,Mat**);
13451a6a6d98SBarry Smith 
13461a6a6d98SBarry Smith extern int MatSolve_SeqBAIJ_N(Mat,Vec,Vec);
13471a6a6d98SBarry Smith extern int MatSolve_SeqBAIJ_1(Mat,Vec,Vec);
13481a6a6d98SBarry Smith extern int MatSolve_SeqBAIJ_2(Mat,Vec,Vec);
13491a6a6d98SBarry Smith extern int MatSolve_SeqBAIJ_3(Mat,Vec,Vec);
13501a6a6d98SBarry Smith extern int MatSolve_SeqBAIJ_4(Mat,Vec,Vec);
13511a6a6d98SBarry Smith extern int MatSolve_SeqBAIJ_5(Mat,Vec,Vec);
13521a6a6d98SBarry Smith 
13537fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_N(Mat,Mat*);
13547fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_1(Mat,Mat*);
13557fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_2(Mat,Mat*);
13567fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_3(Mat,Mat*);
13577fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_4(Mat,Mat*);
13587fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_5(Mat,Mat*);
13592593348eSBarry Smith 
1360b6490206SBarry Smith static int MatNorm_SeqBAIJ(Mat A,NormType type,double *norm)
13612593348eSBarry Smith {
1362b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
13632593348eSBarry Smith   Scalar      *v = a->a;
13642593348eSBarry Smith   double      sum = 0.0;
13659df24120SSatish Balay   int         i,nz=a->nz,bs2=a->bs2;
13662593348eSBarry Smith 
13672593348eSBarry Smith   if (type == NORM_FROBENIUS) {
13680419e6cdSSatish Balay     for (i=0; i< bs2*nz; i++ ) {
13692593348eSBarry Smith #if defined(PETSC_COMPLEX)
13702593348eSBarry Smith       sum += real(conj(*v)*(*v)); v++;
13712593348eSBarry Smith #else
13722593348eSBarry Smith       sum += (*v)*(*v); v++;
13732593348eSBarry Smith #endif
13742593348eSBarry Smith     }
13752593348eSBarry Smith     *norm = sqrt(sum);
13762593348eSBarry Smith   }
13772593348eSBarry Smith   else {
1378b6490206SBarry Smith     SETERRQ(1,"MatNorm_SeqBAIJ:No support for this norm yet");
13792593348eSBarry Smith   }
13802593348eSBarry Smith   return 0;
13812593348eSBarry Smith }
13822593348eSBarry Smith 
13832593348eSBarry Smith /*
13842593348eSBarry Smith      note: This can only work for identity for row and col. It would
13852593348eSBarry Smith    be good to check this and otherwise generate an error.
13862593348eSBarry Smith */
1387b6490206SBarry Smith static int MatILUFactor_SeqBAIJ(Mat inA,IS row,IS col,double efill,int fill)
13882593348eSBarry Smith {
1389b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) inA->data;
13902593348eSBarry Smith   Mat         outA;
1391de6a44a3SBarry Smith   int         ierr;
13922593348eSBarry Smith 
1393b6490206SBarry Smith   if (fill != 0) SETERRQ(1,"MatILUFactor_SeqBAIJ:Only fill=0 supported");
13942593348eSBarry Smith 
13952593348eSBarry Smith   outA          = inA;
13962593348eSBarry Smith   inA->factor   = FACTOR_LU;
13972593348eSBarry Smith   a->row        = row;
13982593348eSBarry Smith   a->col        = col;
13992593348eSBarry Smith 
1400de6a44a3SBarry Smith   a->solve_work = (Scalar *) PetscMalloc((a->m+a->bs)*sizeof(Scalar));CHKPTRQ(a->solve_work);
14012593348eSBarry Smith 
14022593348eSBarry Smith   if (!a->diag) {
1403b6490206SBarry Smith     ierr = MatMarkDiag_SeqBAIJ(inA); CHKERRQ(ierr);
14042593348eSBarry Smith   }
14057fc0212eSBarry Smith   ierr = MatLUFactorNumeric(inA,&outA); CHKERRQ(ierr);
14062593348eSBarry Smith   return 0;
14072593348eSBarry Smith }
14082593348eSBarry Smith 
1409b6490206SBarry Smith static int MatScale_SeqBAIJ(Scalar *alpha,Mat inA)
14102593348eSBarry Smith {
1411b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) inA->data;
14129df24120SSatish Balay   int         one = 1, totalnz = a->bs2*a->nz;
1413b6490206SBarry Smith   BLscal_( &totalnz, alpha, a->a, &one );
1414b6490206SBarry Smith   PLogFlops(totalnz);
14152593348eSBarry Smith   return 0;
14162593348eSBarry Smith }
14172593348eSBarry Smith 
14187e67e3f9SSatish Balay static int MatGetValues_SeqBAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v)
14197e67e3f9SSatish Balay {
14207e67e3f9SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
14217e67e3f9SSatish Balay   int        *rp, k, low, high, t, row, nrow, i, col, l, *aj = a->j;
1422a7c10996SSatish Balay   int        *ai = a->i, *ailen = a->ilen;
14239df24120SSatish Balay   int        brow,bcol,ridx,cidx,bs=a->bs,bs2=a->bs2;
14247e67e3f9SSatish Balay   Scalar     *ap, *aa = a->a, zero = 0.0;
14257e67e3f9SSatish Balay 
14267e67e3f9SSatish Balay   for ( k=0; k<m; k++ ) { /* loop over rows */
14277e67e3f9SSatish Balay     row  = im[k]; brow = row/bs;
14287e67e3f9SSatish Balay     if (row < 0) SETERRQ(1,"MatGetValues_SeqBAIJ:Negative row");
14297e67e3f9SSatish Balay     if (row >= a->m) SETERRQ(1,"MatGetValues_SeqBAIJ:Row too large");
1430a7c10996SSatish Balay     rp   = aj + ai[brow] ; ap = aa + bs2*ai[brow] ;
14317e67e3f9SSatish Balay     nrow = ailen[brow];
14327e67e3f9SSatish Balay     for ( l=0; l<n; l++ ) { /* loop over columns */
14337e67e3f9SSatish Balay       if (in[l] < 0) SETERRQ(1,"MatGetValues_SeqBAIJ:Negative column");
14347e67e3f9SSatish Balay       if (in[l] >= a->n) SETERRQ(1,"MatGetValues_SeqBAIJ:Column too large");
1435a7c10996SSatish Balay       col  = in[l] ;
14367e67e3f9SSatish Balay       bcol = col/bs;
14377e67e3f9SSatish Balay       cidx = col%bs;
14387e67e3f9SSatish Balay       ridx = row%bs;
14397e67e3f9SSatish Balay       high = nrow;
14407e67e3f9SSatish Balay       low  = 0; /* assume unsorted */
14417e67e3f9SSatish Balay       while (high-low > 5) {
14427e67e3f9SSatish Balay         t = (low+high)/2;
14437e67e3f9SSatish Balay         if (rp[t] > bcol) high = t;
14447e67e3f9SSatish Balay         else             low  = t;
14457e67e3f9SSatish Balay       }
14467e67e3f9SSatish Balay       for ( i=low; i<high; i++ ) {
14477e67e3f9SSatish Balay         if (rp[i] > bcol) break;
14487e67e3f9SSatish Balay         if (rp[i] == bcol) {
14497e67e3f9SSatish Balay           *v++ = ap[bs2*i+bs*cidx+ridx];
14507e67e3f9SSatish Balay           goto finished;
14517e67e3f9SSatish Balay         }
14527e67e3f9SSatish Balay       }
14537e67e3f9SSatish Balay       *v++ = zero;
14547e67e3f9SSatish Balay       finished:;
14557e67e3f9SSatish Balay     }
14567e67e3f9SSatish Balay   }
14577e67e3f9SSatish Balay   return 0;
14587e67e3f9SSatish Balay }
14597e67e3f9SSatish Balay 
14602593348eSBarry Smith /* -------------------------------------------------------------------*/
1461cd0e1443SSatish Balay static struct _MatOps MatOps = {MatSetValues_SeqBAIJ,
14629867e207SSatish Balay        MatGetRow_SeqBAIJ,MatRestoreRow_SeqBAIJ,
1463f44d3a6dSSatish Balay        MatMult_SeqBAIJ_N,MatMultAdd_SeqBAIJ_N,
1464faf6580fSSatish Balay        MatMultTrans_SeqBAIJ,MatMultTransAdd_SeqBAIJ,
14651a6a6d98SBarry Smith        MatSolve_SeqBAIJ_N,0,
1466b6490206SBarry Smith        0,0,
1467de6a44a3SBarry Smith        MatLUFactor_SeqBAIJ,0,
1468b6490206SBarry Smith        0,
1469f2501298SSatish Balay        MatTranspose_SeqBAIJ,
147017e48fc4SSatish Balay        MatGetInfo_SeqBAIJ,MatEqual_SeqBAIJ,
14719867e207SSatish Balay        MatGetDiagonal_SeqBAIJ,MatDiagonalScale_SeqBAIJ,MatNorm_SeqBAIJ,
1472584200bdSSatish Balay        0,MatAssemblyEnd_SeqBAIJ,
1473b6490206SBarry Smith        0,
1474b6490206SBarry Smith        MatSetOption_SeqBAIJ,MatZeroEntries_SeqBAIJ,0,
1475b6490206SBarry Smith        MatGetReordering_SeqBAIJ,
14767fc0212eSBarry Smith        MatLUFactorSymbolic_SeqBAIJ,MatLUFactorNumeric_SeqBAIJ_N,0,0,
1477b6490206SBarry Smith        MatGetSize_SeqBAIJ,MatGetSize_SeqBAIJ,MatGetOwnershipRange_SeqBAIJ,
1478de6a44a3SBarry Smith        MatILUFactorSymbolic_SeqBAIJ,0,
1479b6490206SBarry Smith        0,0,/*  MatConvert_SeqBAIJ  */ 0,
1480736121d4SSatish Balay        MatGetSubMatrix_SeqBAIJ,0,
1481b6490206SBarry Smith        MatConvertSameType_SeqBAIJ,0,0,
1482b6490206SBarry Smith        MatILUFactor_SeqBAIJ,0,0,
1483af015674SSatish Balay        MatGetSubMatrices_SeqBAIJ,MatIncreaseOverlap_SeqBAIJ,
14847e67e3f9SSatish Balay        MatGetValues_SeqBAIJ,0,
14851a6a6d98SBarry Smith        0,MatScale_SeqBAIJ,
1486b6490206SBarry Smith        0};
14872593348eSBarry Smith 
14882593348eSBarry Smith /*@C
148944cd7ae7SLois Curfman McInnes    MatCreateSeqBAIJ - Creates a sparse matrix in block AIJ (block
149044cd7ae7SLois Curfman McInnes    compressed row) format.  For good matrix assembly performance the
149144cd7ae7SLois Curfman McInnes    user should preallocate the matrix storage by setting the parameter nz
14922bd5e0b2SLois Curfman McInnes    (or the array nzz).  By setting these parameters accurately, performance
14932bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
14942593348eSBarry Smith 
14952593348eSBarry Smith    Input Parameters:
14962593348eSBarry Smith .  comm - MPI communicator, set to MPI_COMM_SELF
1497b6490206SBarry Smith .  bs - size of block
14982593348eSBarry Smith .  m - number of rows
14992593348eSBarry Smith .  n - number of columns
1500b6490206SBarry Smith .  nz - number of block nonzeros per block row (same for all rows)
15012bd5e0b2SLois Curfman McInnes .  nzz - array containing the number of block nonzeros in the various block rows
15022bd5e0b2SLois Curfman McInnes          (possibly different for each block row) or PETSC_NULL
15032593348eSBarry Smith 
15042593348eSBarry Smith    Output Parameter:
15052593348eSBarry Smith .  A - the matrix
15062593348eSBarry Smith 
15072593348eSBarry Smith    Notes:
150844cd7ae7SLois Curfman McInnes    The block AIJ format is fully compatible with standard Fortran 77
15092593348eSBarry Smith    storage.  That is, the stored row and column indices can begin at
151044cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
15112593348eSBarry Smith 
15122593348eSBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
15132593348eSBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
15142593348eSBarry Smith    allocation.  For additional details, see the users manual chapter on
15152593348eSBarry Smith    matrices and the file $(PETSC_DIR)/Performance.
15162593348eSBarry Smith 
151744cd7ae7SLois Curfman McInnes .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues()
15182593348eSBarry Smith @*/
1519b6490206SBarry Smith int MatCreateSeqBAIJ(MPI_Comm comm,int bs,int m,int n,int nz,int *nnz, Mat *A)
15202593348eSBarry Smith {
15212593348eSBarry Smith   Mat         B;
1522b6490206SBarry Smith   Mat_SeqBAIJ *b;
1523f2501298SSatish Balay   int         i,len,ierr,flg,mbs=m/bs,nbs=n/bs,bs2=bs*bs;
1524b6490206SBarry Smith 
1525f2501298SSatish Balay   if (mbs*bs!=m || nbs*bs!=n)
1526f2501298SSatish Balay     SETERRQ(1,"MatCreateSeqBAIJ:Number rows, cols must be divisible by blocksize");
15272593348eSBarry Smith 
15282593348eSBarry Smith   *A = 0;
1529b6490206SBarry Smith   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSEQBAIJ,comm);
15302593348eSBarry Smith   PLogObjectCreate(B);
1531b6490206SBarry Smith   B->data = (void *) (b = PetscNew(Mat_SeqBAIJ)); CHKPTRQ(b);
153244cd7ae7SLois Curfman McInnes   PetscMemzero(b,sizeof(Mat_SeqBAIJ));
15332593348eSBarry Smith   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
15341a6a6d98SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_no_unroll",&flg); CHKERRQ(ierr);
15351a6a6d98SBarry Smith   if (!flg) {
15367fc0212eSBarry Smith     switch (bs) {
15377fc0212eSBarry Smith       case 1:
15387fc0212eSBarry Smith         B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_1;
15391a6a6d98SBarry Smith         B->ops.solve           = MatSolve_SeqBAIJ_1;
154039b95ed1SBarry Smith         B->ops.mult            = MatMult_SeqBAIJ_1;
1541f44d3a6dSSatish Balay         B->ops.multadd         = MatMultAdd_SeqBAIJ_1;
15427fc0212eSBarry Smith        break;
15434eeb42bcSBarry Smith       case 2:
15444eeb42bcSBarry Smith         B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_2;
15451a6a6d98SBarry Smith         B->ops.solve           = MatSolve_SeqBAIJ_2;
154639b95ed1SBarry Smith         B->ops.mult            = MatMult_SeqBAIJ_2;
1547f44d3a6dSSatish Balay         B->ops.multadd         = MatMultAdd_SeqBAIJ_2;
15486d84be18SBarry Smith         break;
1549f327dd97SBarry Smith       case 3:
1550f327dd97SBarry Smith         B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_3;
15511a6a6d98SBarry Smith         B->ops.solve           = MatSolve_SeqBAIJ_3;
155239b95ed1SBarry Smith         B->ops.mult            = MatMult_SeqBAIJ_3;
1553f44d3a6dSSatish Balay         B->ops.multadd         = MatMultAdd_SeqBAIJ_3;
15544eeb42bcSBarry Smith         break;
15556d84be18SBarry Smith       case 4:
15566d84be18SBarry Smith         B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_4;
15571a6a6d98SBarry Smith         B->ops.solve           = MatSolve_SeqBAIJ_4;
155839b95ed1SBarry Smith         B->ops.mult            = MatMult_SeqBAIJ_4;
1559f44d3a6dSSatish Balay         B->ops.multadd         = MatMultAdd_SeqBAIJ_4;
15606d84be18SBarry Smith         break;
15616d84be18SBarry Smith       case 5:
15626d84be18SBarry Smith         B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_5;
15631a6a6d98SBarry Smith         B->ops.solve           = MatSolve_SeqBAIJ_5;
156439b95ed1SBarry Smith         B->ops.mult            = MatMult_SeqBAIJ_5;
1565f44d3a6dSSatish Balay         B->ops.multadd         = MatMultAdd_SeqBAIJ_5;
15666d84be18SBarry Smith         break;
15677fc0212eSBarry Smith     }
15681a6a6d98SBarry Smith   }
1569b6490206SBarry Smith   B->destroy          = MatDestroy_SeqBAIJ;
1570b6490206SBarry Smith   B->view             = MatView_SeqBAIJ;
15712593348eSBarry Smith   B->factor           = 0;
15722593348eSBarry Smith   B->lupivotthreshold = 1.0;
15732593348eSBarry Smith   b->row              = 0;
15742593348eSBarry Smith   b->col              = 0;
15752593348eSBarry Smith   b->reallocs         = 0;
15762593348eSBarry Smith 
157744cd7ae7SLois Curfman McInnes   b->m       = m; B->m = m; B->M = m;
157844cd7ae7SLois Curfman McInnes   b->n       = n; B->n = n; B->N = n;
1579b6490206SBarry Smith   b->mbs     = mbs;
1580f2501298SSatish Balay   b->nbs     = nbs;
1581b6490206SBarry Smith   b->imax    = (int *) PetscMalloc( (mbs+1)*sizeof(int) ); CHKPTRQ(b->imax);
15822593348eSBarry Smith   if (nnz == PETSC_NULL) {
1583119a934aSSatish Balay     if (nz == PETSC_DEFAULT) nz = 5;
15842593348eSBarry Smith     else if (nz <= 0)        nz = 1;
1585b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) b->imax[i] = nz;
1586b6490206SBarry Smith     nz = nz*mbs;
15872593348eSBarry Smith   }
15882593348eSBarry Smith   else {
15892593348eSBarry Smith     nz = 0;
1590b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) {b->imax[i] = nnz[i]; nz += nnz[i];}
15912593348eSBarry Smith   }
15922593348eSBarry Smith 
15932593348eSBarry Smith   /* allocate the matrix space */
15947e67e3f9SSatish Balay   len   = nz*sizeof(int) + nz*bs2*sizeof(Scalar) + (b->m+1)*sizeof(int);
15952593348eSBarry Smith   b->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(b->a);
15967e67e3f9SSatish Balay   PetscMemzero(b->a,nz*bs2*sizeof(Scalar));
15977e67e3f9SSatish Balay   b->j  = (int *) (b->a + nz*bs2);
15982593348eSBarry Smith   PetscMemzero(b->j,nz*sizeof(int));
15992593348eSBarry Smith   b->i  = b->j + nz;
16002593348eSBarry Smith   b->singlemalloc = 1;
16012593348eSBarry Smith 
1602de6a44a3SBarry Smith   b->i[0] = 0;
1603b6490206SBarry Smith   for (i=1; i<mbs+1; i++) {
16042593348eSBarry Smith     b->i[i] = b->i[i-1] + b->imax[i-1];
16052593348eSBarry Smith   }
16062593348eSBarry Smith 
1607b6490206SBarry Smith   /* b->ilen will count nonzeros in each block row so far. */
1608b6490206SBarry Smith   b->ilen = (int *) PetscMalloc((mbs+1)*sizeof(int));
1609b6490206SBarry Smith   PLogObjectMemory(B,len+2*(mbs+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqBAIJ));
1610b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) { b->ilen[i] = 0;}
16112593348eSBarry Smith 
1612b6490206SBarry Smith   b->bs               = bs;
16139df24120SSatish Balay   b->bs2              = bs2;
1614b6490206SBarry Smith   b->mbs              = mbs;
16152593348eSBarry Smith   b->nz               = 0;
161618e7b8e4SLois Curfman McInnes   b->maxnz            = nz*bs2;
16172593348eSBarry Smith   b->sorted           = 0;
16182593348eSBarry Smith   b->roworiented      = 1;
16192593348eSBarry Smith   b->nonew            = 0;
16202593348eSBarry Smith   b->diag             = 0;
16212593348eSBarry Smith   b->solve_work       = 0;
1622de6a44a3SBarry Smith   b->mult_work        = 0;
16232593348eSBarry Smith   b->spptr            = 0;
16242593348eSBarry Smith   *A = B;
16252593348eSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-help", &flg); CHKERRQ(ierr);
16262593348eSBarry Smith   if (flg) {ierr = MatPrintHelp(B); CHKERRQ(ierr); }
16272593348eSBarry Smith   return 0;
16282593348eSBarry Smith }
16292593348eSBarry Smith 
1630b6490206SBarry Smith int MatConvertSameType_SeqBAIJ(Mat A,Mat *B,int cpvalues)
16312593348eSBarry Smith {
16322593348eSBarry Smith   Mat         C;
1633b6490206SBarry Smith   Mat_SeqBAIJ *c,*a = (Mat_SeqBAIJ *) A->data;
16349df24120SSatish Balay   int         i,len, mbs = a->mbs,nz = a->nz,bs2 =a->bs2;
1635de6a44a3SBarry Smith 
1636de6a44a3SBarry Smith   if (a->i[mbs] != nz) SETERRQ(1,"MatConvertSameType_SeqBAIJ:Corrupt matrix");
16372593348eSBarry Smith 
16382593348eSBarry Smith   *B = 0;
1639b6490206SBarry Smith   PetscHeaderCreate(C,_Mat,MAT_COOKIE,MATSEQBAIJ,A->comm);
16402593348eSBarry Smith   PLogObjectCreate(C);
1641b6490206SBarry Smith   C->data       = (void *) (c = PetscNew(Mat_SeqBAIJ)); CHKPTRQ(c);
16422593348eSBarry Smith   PetscMemcpy(&C->ops,&A->ops,sizeof(struct _MatOps));
1643b6490206SBarry Smith   C->destroy    = MatDestroy_SeqBAIJ;
1644b6490206SBarry Smith   C->view       = MatView_SeqBAIJ;
16452593348eSBarry Smith   C->factor     = A->factor;
16462593348eSBarry Smith   c->row        = 0;
16472593348eSBarry Smith   c->col        = 0;
16482593348eSBarry Smith   C->assembled  = PETSC_TRUE;
16492593348eSBarry Smith 
165044cd7ae7SLois Curfman McInnes   c->m = C->m   = a->m;
165144cd7ae7SLois Curfman McInnes   c->n = C->n   = a->n;
165244cd7ae7SLois Curfman McInnes   C->M          = a->m;
165344cd7ae7SLois Curfman McInnes   C->N          = a->n;
165444cd7ae7SLois Curfman McInnes 
1655b6490206SBarry Smith   c->bs         = a->bs;
16569df24120SSatish Balay   c->bs2        = a->bs2;
1657b6490206SBarry Smith   c->mbs        = a->mbs;
1658b6490206SBarry Smith   c->nbs        = a->nbs;
16592593348eSBarry Smith 
1660b6490206SBarry Smith   c->imax       = (int *) PetscMalloc((mbs+1)*sizeof(int)); CHKPTRQ(c->imax);
1661b6490206SBarry Smith   c->ilen       = (int *) PetscMalloc((mbs+1)*sizeof(int)); CHKPTRQ(c->ilen);
1662b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
16632593348eSBarry Smith     c->imax[i] = a->imax[i];
16642593348eSBarry Smith     c->ilen[i] = a->ilen[i];
16652593348eSBarry Smith   }
16662593348eSBarry Smith 
16672593348eSBarry Smith   /* allocate the matrix space */
16682593348eSBarry Smith   c->singlemalloc = 1;
16697e67e3f9SSatish Balay   len   = (mbs+1)*sizeof(int) + nz*(bs2*sizeof(Scalar) + sizeof(int));
16702593348eSBarry Smith   c->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(c->a);
16717e67e3f9SSatish Balay   c->j  = (int *) (c->a + nz*bs2);
1672de6a44a3SBarry Smith   c->i  = c->j + nz;
1673b6490206SBarry Smith   PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(int));
1674b6490206SBarry Smith   if (mbs > 0) {
1675de6a44a3SBarry Smith     PetscMemcpy(c->j,a->j,nz*sizeof(int));
16762593348eSBarry Smith     if (cpvalues == COPY_VALUES) {
16777e67e3f9SSatish Balay       PetscMemcpy(c->a,a->a,bs2*nz*sizeof(Scalar));
16782593348eSBarry Smith     }
16792593348eSBarry Smith   }
16802593348eSBarry Smith 
1681b6490206SBarry Smith   PLogObjectMemory(C,len+2*(mbs+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqBAIJ));
16822593348eSBarry Smith   c->sorted      = a->sorted;
16832593348eSBarry Smith   c->roworiented = a->roworiented;
16842593348eSBarry Smith   c->nonew       = a->nonew;
16852593348eSBarry Smith 
16862593348eSBarry Smith   if (a->diag) {
1687b6490206SBarry Smith     c->diag = (int *) PetscMalloc( (mbs+1)*sizeof(int) ); CHKPTRQ(c->diag);
1688b6490206SBarry Smith     PLogObjectMemory(C,(mbs+1)*sizeof(int));
1689b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) {
16902593348eSBarry Smith       c->diag[i] = a->diag[i];
16912593348eSBarry Smith     }
16922593348eSBarry Smith   }
16932593348eSBarry Smith   else c->diag          = 0;
16942593348eSBarry Smith   c->nz                 = a->nz;
16952593348eSBarry Smith   c->maxnz              = a->maxnz;
16962593348eSBarry Smith   c->solve_work         = 0;
16972593348eSBarry Smith   c->spptr              = 0;      /* Dangerous -I'm throwing away a->spptr */
16987fc0212eSBarry Smith   c->mult_work          = 0;
16992593348eSBarry Smith   *B = C;
17002593348eSBarry Smith   return 0;
17012593348eSBarry Smith }
17022593348eSBarry Smith 
170319bcc07fSBarry Smith int MatLoad_SeqBAIJ(Viewer viewer,MatType type,Mat *A)
17042593348eSBarry Smith {
1705b6490206SBarry Smith   Mat_SeqBAIJ  *a;
17062593348eSBarry Smith   Mat          B;
1707de6a44a3SBarry Smith   int          i,nz,ierr,fd,header[4],size,*rowlengths=0,M,N,bs=1,flg;
1708b6490206SBarry Smith   int          *mask,mbs,*jj,j,rowcount,nzcount,k,*browlengths,maskcount;
170935aab85fSBarry Smith   int          kmax,jcount,block,idx,point,nzcountb,extra_rows;
1710a7c10996SSatish Balay   int          *masked, nmask,tmp,bs2,ishift;
1711b6490206SBarry Smith   Scalar       *aa;
171219bcc07fSBarry Smith   MPI_Comm     comm = ((PetscObject) viewer)->comm;
17132593348eSBarry Smith 
17141a6a6d98SBarry Smith   ierr = OptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,&flg);CHKERRQ(ierr);
1715de6a44a3SBarry Smith   bs2  = bs*bs;
1716b6490206SBarry Smith 
17172593348eSBarry Smith   MPI_Comm_size(comm,&size);
1718b6490206SBarry Smith   if (size > 1) SETERRQ(1,"MatLoad_SeqBAIJ:view must have one processor");
171990ace30eSBarry Smith   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
172077c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,header,4,BINARY_INT); CHKERRQ(ierr);
1721de6a44a3SBarry Smith   if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_SeqBAIJ:not Mat object");
17222593348eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
17232593348eSBarry Smith 
1724b6490206SBarry Smith   if (M != N) SETERRQ(1,"MatLoad_SeqBAIJ:Can only do square matrices");
172535aab85fSBarry Smith 
172635aab85fSBarry Smith   /*
172735aab85fSBarry Smith      This code adds extra rows to make sure the number of rows is
172835aab85fSBarry Smith     divisible by the blocksize
172935aab85fSBarry Smith   */
1730b6490206SBarry Smith   mbs        = M/bs;
173135aab85fSBarry Smith   extra_rows = bs - M + bs*(mbs);
173235aab85fSBarry Smith   if (extra_rows == bs) extra_rows = 0;
173335aab85fSBarry Smith   else                  mbs++;
173435aab85fSBarry Smith   if (extra_rows) {
17351a6a6d98SBarry Smith     PLogInfo(0,"MatLoad_SeqBAIJ:Padding loaded matrix to match blocksize");
173635aab85fSBarry Smith   }
1737b6490206SBarry Smith 
17382593348eSBarry Smith   /* read in row lengths */
173935aab85fSBarry Smith   rowlengths = (int*) PetscMalloc((M+extra_rows)*sizeof(int));CHKPTRQ(rowlengths);
174077c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,rowlengths,M,BINARY_INT); CHKERRQ(ierr);
174135aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) rowlengths[M+i] = 1;
17422593348eSBarry Smith 
1743b6490206SBarry Smith   /* read in column indices */
174435aab85fSBarry Smith   jj = (int*) PetscMalloc( (nz+extra_rows)*sizeof(int) ); CHKPTRQ(jj);
174577c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,jj,nz,BINARY_INT); CHKERRQ(ierr);
174635aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) jj[nz+i] = M+i;
1747b6490206SBarry Smith 
1748b6490206SBarry Smith   /* loop over row lengths determining block row lengths */
1749b6490206SBarry Smith   browlengths = (int *) PetscMalloc(mbs*sizeof(int));CHKPTRQ(browlengths);
1750b6490206SBarry Smith   PetscMemzero(browlengths,mbs*sizeof(int));
175135aab85fSBarry Smith   mask   = (int *) PetscMalloc( 2*mbs*sizeof(int) ); CHKPTRQ(mask);
175235aab85fSBarry Smith   PetscMemzero(mask,mbs*sizeof(int));
175335aab85fSBarry Smith   masked = mask + mbs;
1754b6490206SBarry Smith   rowcount = 0; nzcount = 0;
1755b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
175635aab85fSBarry Smith     nmask = 0;
1757b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
1758b6490206SBarry Smith       kmax = rowlengths[rowcount];
1759b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
176035aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
176135aab85fSBarry Smith         if (!mask[tmp]) {masked[nmask++] = tmp; mask[tmp] = 1;}
1762b6490206SBarry Smith       }
1763b6490206SBarry Smith       rowcount++;
1764b6490206SBarry Smith     }
176535aab85fSBarry Smith     browlengths[i] += nmask;
176635aab85fSBarry Smith     /* zero out the mask elements we set */
176735aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) mask[masked[j]] = 0;
1768b6490206SBarry Smith   }
1769b6490206SBarry Smith 
17702593348eSBarry Smith   /* create our matrix */
177135aab85fSBarry Smith   ierr = MatCreateSeqBAIJ(comm,bs,M+extra_rows,N+extra_rows,0,browlengths,A);
177235aab85fSBarry Smith          CHKERRQ(ierr);
17732593348eSBarry Smith   B = *A;
1774b6490206SBarry Smith   a = (Mat_SeqBAIJ *) B->data;
17752593348eSBarry Smith 
17762593348eSBarry Smith   /* set matrix "i" values */
1777de6a44a3SBarry Smith   a->i[0] = 0;
1778b6490206SBarry Smith   for ( i=1; i<= mbs; i++ ) {
1779b6490206SBarry Smith     a->i[i]      = a->i[i-1] + browlengths[i-1];
1780b6490206SBarry Smith     a->ilen[i-1] = browlengths[i-1];
17812593348eSBarry Smith   }
1782b6490206SBarry Smith   a->nz         = 0;
1783b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) a->nz += browlengths[i];
17842593348eSBarry Smith 
1785b6490206SBarry Smith   /* read in nonzero values */
178635aab85fSBarry Smith   aa = (Scalar *) PetscMalloc((nz+extra_rows)*sizeof(Scalar));CHKPTRQ(aa);
178777c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,aa,nz,BINARY_SCALAR); CHKERRQ(ierr);
178835aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) aa[nz+i] = 1.0;
1789b6490206SBarry Smith 
1790b6490206SBarry Smith   /* set "a" and "j" values into matrix */
1791b6490206SBarry Smith   nzcount = 0; jcount = 0;
1792b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
1793b6490206SBarry Smith     nzcountb = nzcount;
179435aab85fSBarry Smith     nmask    = 0;
1795b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
1796b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
1797b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
179835aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
179935aab85fSBarry Smith 	if (!mask[tmp]) { masked[nmask++] = tmp; mask[tmp] = 1;}
1800b6490206SBarry Smith       }
1801b6490206SBarry Smith       rowcount++;
1802b6490206SBarry Smith     }
1803de6a44a3SBarry Smith     /* sort the masked values */
180477c4ece6SBarry Smith     PetscSortInt(nmask,masked);
1805de6a44a3SBarry Smith 
1806b6490206SBarry Smith     /* set "j" values into matrix */
1807b6490206SBarry Smith     maskcount = 1;
180835aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) {
180935aab85fSBarry Smith       a->j[jcount++]  = masked[j];
1810de6a44a3SBarry Smith       mask[masked[j]] = maskcount++;
1811b6490206SBarry Smith     }
1812b6490206SBarry Smith     /* set "a" values into matrix */
1813de6a44a3SBarry Smith     ishift = bs2*a->i[i];
1814b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
1815b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
1816b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
1817de6a44a3SBarry Smith         tmp    = jj[nzcountb]/bs ;
1818de6a44a3SBarry Smith         block  = mask[tmp] - 1;
1819de6a44a3SBarry Smith         point  = jj[nzcountb] - bs*tmp;
1820de6a44a3SBarry Smith         idx    = ishift + bs2*block + j + bs*point;
1821b6490206SBarry Smith         a->a[idx] = aa[nzcountb++];
1822b6490206SBarry Smith       }
1823b6490206SBarry Smith     }
182435aab85fSBarry Smith     /* zero out the mask elements we set */
182535aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) mask[masked[j]] = 0;
1826b6490206SBarry Smith   }
182735aab85fSBarry Smith   if (jcount != a->nz) SETERRQ(1,"MatLoad_SeqBAIJ:Error bad binary matrix");
1828b6490206SBarry Smith 
1829b6490206SBarry Smith   PetscFree(rowlengths);
1830b6490206SBarry Smith   PetscFree(browlengths);
1831b6490206SBarry Smith   PetscFree(aa);
1832b6490206SBarry Smith   PetscFree(jj);
1833b6490206SBarry Smith   PetscFree(mask);
1834b6490206SBarry Smith 
1835b6490206SBarry Smith   B->assembled = PETSC_TRUE;
1836de6a44a3SBarry Smith 
1837de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_info",&flg); CHKERRQ(ierr);
1838de6a44a3SBarry Smith   if (flg) {
183919bcc07fSBarry Smith     Viewer tviewer;
184019bcc07fSBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&tviewer);CHKERRQ(ierr);
184190ace30eSBarry Smith     ierr = ViewerSetFormat(tviewer,ASCII_FORMAT_INFO,0);CHKERRQ(ierr);
184219bcc07fSBarry Smith     ierr = MatView(B,tviewer); CHKERRQ(ierr);
184319bcc07fSBarry Smith     ierr = ViewerDestroy(tviewer); CHKERRQ(ierr);
1844de6a44a3SBarry Smith   }
1845de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_info_detailed",&flg);CHKERRQ(ierr);
1846de6a44a3SBarry Smith   if (flg) {
184719bcc07fSBarry Smith     Viewer tviewer;
184819bcc07fSBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&tviewer);CHKERRQ(ierr);
184990ace30eSBarry Smith     ierr = ViewerSetFormat(tviewer,ASCII_FORMAT_INFO_DETAILED,0);CHKERRQ(ierr);
185019bcc07fSBarry Smith     ierr = MatView(B,tviewer); CHKERRQ(ierr);
185119bcc07fSBarry Smith     ierr = ViewerDestroy(tviewer); CHKERRQ(ierr);
1852de6a44a3SBarry Smith   }
1853de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view",&flg); CHKERRQ(ierr);
1854de6a44a3SBarry Smith   if (flg) {
185519bcc07fSBarry Smith     Viewer tviewer;
185619bcc07fSBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&tviewer);CHKERRQ(ierr);
185719bcc07fSBarry Smith     ierr = MatView(B,tviewer); CHKERRQ(ierr);
185819bcc07fSBarry Smith     ierr = ViewerDestroy(tviewer); CHKERRQ(ierr);
1859de6a44a3SBarry Smith   }
1860de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_matlab",&flg); CHKERRQ(ierr);
1861de6a44a3SBarry Smith   if (flg) {
186219bcc07fSBarry Smith     Viewer tviewer;
186319bcc07fSBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&tviewer);CHKERRQ(ierr);
186490ace30eSBarry Smith     ierr = ViewerSetFormat(tviewer,ASCII_FORMAT_MATLAB,"M");CHKERRQ(ierr);
186519bcc07fSBarry Smith     ierr = MatView(B,tviewer); CHKERRQ(ierr);
186619bcc07fSBarry Smith     ierr = ViewerDestroy(tviewer); CHKERRQ(ierr);
1867de6a44a3SBarry Smith   }
1868de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_draw",&flg); CHKERRQ(ierr);
1869de6a44a3SBarry Smith   if (flg) {
187019bcc07fSBarry Smith     Viewer tviewer;
187119bcc07fSBarry Smith     ierr = ViewerDrawOpenX(B->comm,0,0,0,0,300,300,&tviewer); CHKERRQ(ierr);
187219bcc07fSBarry Smith     ierr = MatView(B,(Viewer)tviewer); CHKERRQ(ierr);
187319bcc07fSBarry Smith     ierr = ViewerFlush(tviewer); CHKERRQ(ierr);
187419bcc07fSBarry Smith     ierr = ViewerDestroy(tviewer); CHKERRQ(ierr);
1875de6a44a3SBarry Smith   }
18762593348eSBarry Smith   return 0;
18772593348eSBarry Smith }
18782593348eSBarry Smith 
18792593348eSBarry Smith 
18802593348eSBarry Smith 
1881