xref: /petsc/src/mat/impls/baij/seq/baij.c (revision 584200bd60b19aa872b60562eaa98d23aa621582)
1b6490206SBarry Smith 
22593348eSBarry Smith #ifndef lint
3*584200bdSSatish Balay static char vcid[] = "$Id: baij.c,v 1.25 1996/04/04 00:27:51 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"
112593348eSBarry Smith #include "vec/vecimpl.h"
122593348eSBarry Smith #include "inline/spops.h"
132593348eSBarry Smith #include "petsc.h"
142593348eSBarry Smith 
15bcd2baecSBarry Smith extern int MatToSymmetricIJ_SeqAIJ(int,int*,int*,int,int,int**,int**);
162593348eSBarry Smith 
17b6490206SBarry Smith static int MatGetReordering_SeqBAIJ(Mat A,MatOrdering 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();
41bcd2baecSBarry Smith   ishift = a->indexshift;
42bcd2baecSBarry Smith   oshift = -MatReorderingIndexShift[(int)type];
43bcd2baecSBarry Smith   if (MatReorderingRequiresSymmetric[(int)type]) {
44bcd2baecSBarry Smith     ierr = MatToSymmetricIJ_SeqAIJ(a->n,a->i,a->j,ishift,oshift,&ia,&ja);
45bcd2baecSBarry Smith     CHKERRQ(ierr);
46bcd2baecSBarry Smith     ierr = MatGetReordering_IJ(a->n,ia,ja,type,rperm,cperm); CHKERRQ(ierr);
472593348eSBarry Smith     PetscFree(ia); PetscFree(ja);
48bcd2baecSBarry Smith   } else {
49bcd2baecSBarry Smith     if (ishift == oshift) {
50bcd2baecSBarry Smith       ierr = MatGetReordering_IJ(a->n,a->i,a->j,type,rperm,cperm);CHKERRQ(ierr);
51bcd2baecSBarry Smith     }
52bcd2baecSBarry Smith     else if (ishift == -1) {
53bcd2baecSBarry Smith       /* temporarily subtract 1 from i and j indices */
54bcd2baecSBarry Smith       int nz = a->i[a->n] - 1;
55bcd2baecSBarry Smith       for ( i=0; i<nz; i++ ) a->j[i]--;
56bcd2baecSBarry Smith       for ( i=0; i<a->n+1; i++ ) a->i[i]--;
57bcd2baecSBarry Smith       ierr = MatGetReordering_IJ(a->n,a->i,a->j,type,rperm,cperm);CHKERRQ(ierr);
58bcd2baecSBarry Smith       for ( i=0; i<nz; i++ ) a->j[i]++;
59bcd2baecSBarry Smith       for ( i=0; i<a->n+1; i++ ) a->i[i]++;
60bcd2baecSBarry Smith     } else {
61bcd2baecSBarry Smith       /* temporarily add 1 to i and j indices */
62bcd2baecSBarry Smith       int nz = a->i[a->n] - 1;
63bcd2baecSBarry Smith       for ( i=0; i<nz; i++ ) a->j[i]++;
64bcd2baecSBarry Smith       for ( i=0; i<a->n+1; i++ ) a->i[i]++;
65bcd2baecSBarry Smith       ierr = MatGetReordering_IJ(a->n,a->i,a->j,type,rperm,cperm);CHKERRQ(ierr);
66bcd2baecSBarry Smith       for ( i=0; i<nz; i++ ) a->j[i]--;
67bcd2baecSBarry Smith       for ( i=0; i<a->n+1; i++ ) a->i[i]--;
68bcd2baecSBarry Smith     }
69bcd2baecSBarry Smith   }
702593348eSBarry Smith   return 0;
712593348eSBarry Smith }
722593348eSBarry Smith 
73de6a44a3SBarry Smith /*
74de6a44a3SBarry Smith      Adds diagonal pointers to sparse matrix structure.
75de6a44a3SBarry Smith */
76de6a44a3SBarry Smith 
77de6a44a3SBarry Smith int MatMarkDiag_SeqBAIJ(Mat A)
78de6a44a3SBarry Smith {
79de6a44a3SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
807fc0212eSBarry Smith   int         i,j, *diag, m = a->mbs;
81de6a44a3SBarry Smith 
82de6a44a3SBarry Smith   diag = (int *) PetscMalloc( (m+1)*sizeof(int)); CHKPTRQ(diag);
83de6a44a3SBarry Smith   PLogObjectMemory(A,(m+1)*sizeof(int));
847fc0212eSBarry Smith   for ( i=0; i<m; i++ ) {
85de6a44a3SBarry Smith     for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
86de6a44a3SBarry Smith       if (a->j[j] == i) {
87de6a44a3SBarry Smith         diag[i] = j;
88de6a44a3SBarry Smith         break;
89de6a44a3SBarry Smith       }
90de6a44a3SBarry Smith     }
91de6a44a3SBarry Smith   }
92de6a44a3SBarry Smith   a->diag = diag;
93de6a44a3SBarry Smith   return 0;
94de6a44a3SBarry Smith }
952593348eSBarry Smith 
962593348eSBarry Smith #include "draw.h"
972593348eSBarry Smith #include "pinclude/pviewer.h"
9877c4ece6SBarry Smith #include "sys.h"
992593348eSBarry Smith 
100b6490206SBarry Smith static int MatView_SeqBAIJ_Binary(Mat A,Viewer viewer)
1012593348eSBarry Smith {
102b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
103b6490206SBarry Smith   int         i, fd, *col_lens, ierr, bs = a->bs,count,*jj,j,k,l;
104b6490206SBarry Smith   Scalar      *aa;
1052593348eSBarry Smith 
10690ace30eSBarry Smith   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
1072593348eSBarry Smith   col_lens = (int *) PetscMalloc((4+a->m)*sizeof(int));CHKPTRQ(col_lens);
1082593348eSBarry Smith   col_lens[0] = MAT_COOKIE;
1092593348eSBarry Smith   col_lens[1] = a->m;
1102593348eSBarry Smith   col_lens[2] = a->n;
111b6490206SBarry Smith   col_lens[3] = a->nz*bs*bs;
1122593348eSBarry Smith 
1132593348eSBarry Smith   /* store lengths of each row and write (including header) to file */
114b6490206SBarry Smith   count = 0;
115b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
116b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
117b6490206SBarry Smith       col_lens[4+count++] = bs*(a->i[i+1] - a->i[i]);
118b6490206SBarry Smith     }
1192593348eSBarry Smith   }
12077c4ece6SBarry Smith   ierr = PetscBinaryWrite(fd,col_lens,4+a->m,BINARY_INT,1); CHKERRQ(ierr);
1212593348eSBarry Smith   PetscFree(col_lens);
1222593348eSBarry Smith 
1232593348eSBarry Smith   /* store column indices (zero start index) */
124b6490206SBarry Smith   jj = (int *) PetscMalloc( a->nz*bs*bs*sizeof(int) ); CHKPTRQ(jj);
125b6490206SBarry Smith   count = 0;
126b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
127b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
128b6490206SBarry Smith       for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
129b6490206SBarry Smith         for ( l=0; l<bs; l++ ) {
130b6490206SBarry Smith           jj[count++] = bs*a->j[k] + l;
1312593348eSBarry Smith         }
1322593348eSBarry Smith       }
133b6490206SBarry Smith     }
134b6490206SBarry Smith   }
13577c4ece6SBarry Smith   ierr = PetscBinaryWrite(fd,jj,bs*bs*a->nz,BINARY_INT,0); CHKERRQ(ierr);
136b6490206SBarry Smith   PetscFree(jj);
1372593348eSBarry Smith 
1382593348eSBarry Smith   /* store nonzero values */
139b6490206SBarry Smith   aa = (Scalar *) PetscMalloc(a->nz*bs*bs*sizeof(Scalar)); CHKPTRQ(aa);
140b6490206SBarry Smith   count = 0;
141b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
142b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
143b6490206SBarry Smith       for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
144b6490206SBarry Smith         for ( l=0; l<bs; l++ ) {
145b6490206SBarry Smith           aa[count++] = a->a[bs*bs*k + l*bs + j];
146b6490206SBarry Smith         }
147b6490206SBarry Smith       }
148b6490206SBarry Smith     }
149b6490206SBarry Smith   }
15077c4ece6SBarry Smith   ierr = PetscBinaryWrite(fd,aa,bs*bs*a->nz,BINARY_SCALAR,0); CHKERRQ(ierr);
151b6490206SBarry Smith   PetscFree(aa);
1522593348eSBarry Smith   return 0;
1532593348eSBarry Smith }
1542593348eSBarry Smith 
155b6490206SBarry Smith static int MatView_SeqBAIJ_ASCII(Mat A,Viewer viewer)
1562593348eSBarry Smith {
157b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
158de6a44a3SBarry Smith   int         ierr, i,j,format,bs = a->bs,k,l;
1592593348eSBarry Smith   FILE        *fd;
1602593348eSBarry Smith   char        *outputname;
1612593348eSBarry Smith 
16290ace30eSBarry Smith   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
1632593348eSBarry Smith   ierr = ViewerFileGetOutputname_Private(viewer,&outputname);CHKERRQ(ierr);
16490ace30eSBarry Smith   ierr = ViewerGetFormat(viewer,&format);
16590ace30eSBarry Smith   if (format == ASCII_FORMAT_INFO) {
1662593348eSBarry Smith     /* no need to print additional information */ ;
1672593348eSBarry Smith   }
16890ace30eSBarry Smith   else if (format == ASCII_FORMAT_MATLAB) {
169b6490206SBarry Smith     SETERRQ(1,"MatView_SeqBAIJ_ASCII:Matlab format not supported");
1702593348eSBarry Smith   }
1712593348eSBarry Smith   else {
172b6490206SBarry Smith     for ( i=0; i<a->mbs; i++ ) {
173b6490206SBarry Smith       for ( j=0; j<bs; j++ ) {
174b6490206SBarry Smith         fprintf(fd,"row %d:",i*bs+j);
175b6490206SBarry Smith         for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
176b6490206SBarry Smith           for ( l=0; l<bs; l++ ) {
17788685aaeSLois Curfman McInnes #if defined(PETSC_COMPLEX)
17888685aaeSLois Curfman McInnes           if (imag(a->a[bs*bs*k + l*bs + j]) != 0.0) {
17988685aaeSLois Curfman McInnes             fprintf(fd," %d %g + %g i",bs*a->j[k]+l,
18088685aaeSLois Curfman McInnes               real(a->a[bs*bs*k + l*bs + j]),imag(a->a[bs*bs*k + l*bs + j]));
18188685aaeSLois Curfman McInnes           }
18288685aaeSLois Curfman McInnes           else {
18388685aaeSLois Curfman McInnes             fprintf(fd," %d %g",bs*a->j[k]+l,real(a->a[bs*bs*k + l*bs + j]));
18488685aaeSLois Curfman McInnes           }
18588685aaeSLois Curfman McInnes #else
186de6a44a3SBarry Smith             fprintf(fd," %d %g",bs*a->j[k]+l,a->a[bs*bs*k + l*bs + j]);
18788685aaeSLois Curfman McInnes #endif
1882593348eSBarry Smith           }
1892593348eSBarry Smith         }
1902593348eSBarry Smith         fprintf(fd,"\n");
1912593348eSBarry Smith       }
1922593348eSBarry Smith     }
193b6490206SBarry Smith   }
1942593348eSBarry Smith   fflush(fd);
1952593348eSBarry Smith   return 0;
1962593348eSBarry Smith }
1972593348eSBarry Smith 
198b6490206SBarry Smith static int MatView_SeqBAIJ(PetscObject obj,Viewer viewer)
1992593348eSBarry Smith {
2002593348eSBarry Smith   Mat         A = (Mat) obj;
20119bcc07fSBarry Smith   ViewerType  vtype;
20219bcc07fSBarry Smith   int         ierr;
2032593348eSBarry Smith 
2042593348eSBarry Smith   if (!viewer) {
20519bcc07fSBarry Smith     viewer = STDOUT_VIEWER_SELF;
2062593348eSBarry Smith   }
20719bcc07fSBarry Smith 
20819bcc07fSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
20919bcc07fSBarry Smith   if (vtype == MATLAB_VIEWER) {
210b6490206SBarry Smith     SETERRQ(1,"MatView_SeqBAIJ:Matlab viewer not supported");
2112593348eSBarry Smith   }
21219bcc07fSBarry Smith   else if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER){
213b6490206SBarry Smith     return MatView_SeqBAIJ_ASCII(A,viewer);
2142593348eSBarry Smith   }
21519bcc07fSBarry Smith   else if (vtype == BINARY_FILE_VIEWER) {
216b6490206SBarry Smith     return MatView_SeqBAIJ_Binary(A,viewer);
2172593348eSBarry Smith   }
21819bcc07fSBarry Smith   else if (vtype == DRAW_VIEWER) {
219b6490206SBarry Smith     SETERRQ(1,"MatView_SeqBAIJ:Draw viewer not supported");
2202593348eSBarry Smith   }
2212593348eSBarry Smith   return 0;
2222593348eSBarry Smith }
223b6490206SBarry Smith 
224*584200bdSSatish Balay #define CHUNKSIZE  2
225cd0e1443SSatish Balay 
226cd0e1443SSatish Balay /* This version has row oriented v  */
227cd0e1443SSatish Balay static int MatSetValues_SeqBAIJ(Mat A,int m,int *im,int n,int *in,Scalar *v,InsertMode is)
228cd0e1443SSatish Balay {
229cd0e1443SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
230cd0e1443SSatish Balay   int         *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N,sorted=a->sorted;
231cd0e1443SSatish Balay   int         *imax=a->imax,*ai=a->i,*ailen=a->ilen,roworiented=a->roworiented;
232cd0e1443SSatish Balay   int         *aj=a->j,nonew=a->nonew,shift=a->indexshift,bs=a->bs,brow,bcol;
233cd0e1443SSatish Balay   int          ridx,cidx;
234cd0e1443SSatish Balay   Scalar      *ap,value,*aa=a->a,*bap;
235cd0e1443SSatish Balay 
236cd0e1443SSatish Balay   for ( k=0; k<m; k++ ) { /* loop over added rows */
237cd0e1443SSatish Balay     row  = im[k]; brow = row/bs;
238cd0e1443SSatish Balay     if (row < 0) SETERRQ(1,"MatSetValues_SeqBAIJ:Negative row");
239cd0e1443SSatish Balay     if (row >= a->m) SETERRQ(1,"MatSetValues_SeqBAIJ:Row too large");
240cd0e1443SSatish Balay     rp   = aj + ai[brow] + shift; ap = aa + bs*bs*ai[brow] + shift;
241cd0e1443SSatish Balay     rmax = imax[brow]; nrow = ailen[brow];
242cd0e1443SSatish Balay     low = 0;
243cd0e1443SSatish Balay     for ( l=0; l<n; l++ ) { /* loop over added columns */
244cd0e1443SSatish Balay       if (in[l] < 0) SETERRQ(1,"MatSetValues_SeqBAIJ:Negative column");
245cd0e1443SSatish Balay       if (in[l] >= a->n) SETERRQ(1,"MatSetValues_SeqBAIJ:Column too large");
246cd0e1443SSatish Balay       col = in[l] - shift; bcol = col/bs;
247cd0e1443SSatish Balay       ridx = row % bs; cidx = col % bs;
248cd0e1443SSatish Balay       if (roworiented) {
249cd0e1443SSatish Balay         value = *v++;
250cd0e1443SSatish Balay       }
251cd0e1443SSatish Balay       else {
252cd0e1443SSatish Balay         value = v[k + l*m];
253cd0e1443SSatish Balay       }
254cd0e1443SSatish Balay       if (!sorted) low = 0; high = nrow;
255cd0e1443SSatish Balay       while (high-low > 5) {
256cd0e1443SSatish Balay         t = (low+high)/2;
257cd0e1443SSatish Balay         if (rp[t] > bcol) high = t;
258cd0e1443SSatish Balay         else             low  = t;
259cd0e1443SSatish Balay       }
260cd0e1443SSatish Balay       for ( i=low; i<high; i++ ) {
261cd0e1443SSatish Balay         if (rp[i] > bcol) break;
262cd0e1443SSatish Balay         if (rp[i] == bcol) {
263cd0e1443SSatish Balay           bap  = ap +  bs*bs*i + bs*ridx + cidx;
264cd0e1443SSatish Balay           if (is == ADD_VALUES) *bap += value;
265cd0e1443SSatish Balay           else                  *bap  = value;
266cd0e1443SSatish Balay           goto noinsert;
267cd0e1443SSatish Balay         }
268cd0e1443SSatish Balay       }
269cd0e1443SSatish Balay       if (nonew) goto noinsert;
270cd0e1443SSatish Balay       if (nrow >= rmax) {
271cd0e1443SSatish Balay         /* there is no extra room in row, therefore enlarge */
272cd0e1443SSatish Balay         int    new_nz = ai[a->mbs] + CHUNKSIZE,len,*new_i,*new_j;
273cd0e1443SSatish Balay         Scalar *new_a;
274cd0e1443SSatish Balay 
275cd0e1443SSatish Balay         /* malloc new storage space */
276cd0e1443SSatish Balay         len     = new_nz*(sizeof(int)+bs*bs*sizeof(Scalar))+(a->mbs+1)*sizeof(int);
277cd0e1443SSatish Balay         new_a   = (Scalar *) PetscMalloc( len ); CHKPTRQ(new_a);
278cd0e1443SSatish Balay         new_j   = (int *) (new_a + bs*bs*new_nz);
279cd0e1443SSatish Balay         new_i   = new_j + new_nz;
280cd0e1443SSatish Balay 
281cd0e1443SSatish Balay         /* copy over old data into new slots */
282cd0e1443SSatish Balay         for ( ii=0; ii<brow+1; ii++ ) {new_i[ii] = ai[ii];}
283cd0e1443SSatish Balay         for ( ii=row+1; ii<a->mbs+1; ii++ ) {new_i[ii] = ai[ii]+CHUNKSIZE;}
284cd0e1443SSatish Balay         PetscMemcpy(new_j,aj,(ai[row]+nrow+shift)*sizeof(int));
285cd0e1443SSatish Balay         len = (new_nz - CHUNKSIZE - ai[brow] - nrow - shift);
286cd0e1443SSatish Balay         PetscMemcpy(new_j+ai[brow]+shift+nrow+CHUNKSIZE,aj+ai[brow]+shift+nrow,
287cd0e1443SSatish Balay                                                            len*sizeof(int));
288cd0e1443SSatish Balay         PetscMemcpy(new_a,aa,(ai[brow]+nrow+shift)*bs*bs*sizeof(Scalar));
289cd0e1443SSatish Balay         PetscMemzero(new_a+bs*bs*(ai[brow]+shift+nrow),bs*bs*CHUNKSIZE);
290cd0e1443SSatish Balay         PetscMemcpy(new_a+bs*bs*(ai[brow]+shift+nrow+CHUNKSIZE),
291cd0e1443SSatish Balay                     aa+bs*bs*(ai[brow]+shift+nrow),bs*bs*len*sizeof(Scalar));
292cd0e1443SSatish Balay         /* free up old matrix storage */
293cd0e1443SSatish Balay         PetscFree(a->a);
294cd0e1443SSatish Balay         if (!a->singlemalloc) {PetscFree(a->i);PetscFree(a->j);}
295cd0e1443SSatish Balay         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;
296cd0e1443SSatish Balay         a->singlemalloc = 1;
297cd0e1443SSatish Balay 
298cd0e1443SSatish Balay         rp   = aj + ai[brow] + shift; ap = aa + ai[brow] + shift;
299cd0e1443SSatish Balay         rmax = imax[brow] = imax[brow] + CHUNKSIZE;
300cd0e1443SSatish Balay         PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + bs*bs*sizeof(Scalar)));
301cd0e1443SSatish Balay         a->maxnz += bs*bs*CHUNKSIZE;
302cd0e1443SSatish Balay         a->reallocs++;
303cd0e1443SSatish Balay       }
304cd0e1443SSatish Balay       N = nrow++ - 1; a->nz++;
305cd0e1443SSatish Balay       /* shift up all the later entries in this row */
306cd0e1443SSatish Balay       for ( ii=N; ii>=i; ii-- ) {
307cd0e1443SSatish Balay         rp[ii+1] = rp[ii];
308cd0e1443SSatish Balay         PetscMemcpy(ap+bs*bs*(ii+1),ap+bs*bs*(ii),bs*bs);
309cd0e1443SSatish Balay       }
310cd0e1443SSatish Balay       rp[i] = bcol;
311cd0e1443SSatish Balay       ap[bs*bs*i + bs*ridx + cidx] = value;
312cd0e1443SSatish Balay       noinsert:;
313cd0e1443SSatish Balay       low = i;
314cd0e1443SSatish Balay     }
315cd0e1443SSatish Balay     ailen[brow] = nrow;
316cd0e1443SSatish Balay   }
317cd0e1443SSatish Balay   return 0;
318cd0e1443SSatish Balay }
319cd0e1443SSatish Balay 
3200b824a48SSatish Balay static int MatGetSize_SeqBAIJ(Mat A,int *m,int *n)
3210b824a48SSatish Balay {
3220b824a48SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
3230b824a48SSatish Balay   *m = a->m; *n = a->n;
3240b824a48SSatish Balay   return 0;
3250b824a48SSatish Balay }
3260b824a48SSatish Balay 
3270b824a48SSatish Balay static int MatGetOwnershipRange_SeqBAIJ(Mat A,int *m,int *n)
3280b824a48SSatish Balay {
3290b824a48SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
3300b824a48SSatish Balay   *m = 0; *n = a->m;
3310b824a48SSatish Balay   return 0;
3320b824a48SSatish Balay }
3330b824a48SSatish Balay 
3349867e207SSatish Balay int MatGetRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
3359867e207SSatish Balay {
3369867e207SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
3379867e207SSatish Balay   int          itmp,i,j,k,M,*ai,*aj,bs,bn,bp,*idx_i;
3389867e207SSatish Balay   Scalar      *aa,*v_i,*aa_i;
3399867e207SSatish Balay 
3409867e207SSatish Balay   bs = a->bs;
3419867e207SSatish Balay   ai = a->i;
3429867e207SSatish Balay   aj = a->j;
3439867e207SSatish Balay   aa = a->a;
3449867e207SSatish Balay 
3459867e207SSatish Balay   if (row < 0 || row >= a->m) SETERRQ(1,"MatGetRow_SeqBAIJ:Row out of range");
3469867e207SSatish Balay 
3479867e207SSatish Balay   bn  = row/bs;   /* Block number */
3489867e207SSatish Balay   bp  = row % bs; /* Block Position */
3499867e207SSatish Balay   M   = ai[bn+1] - ai[bn];
3509867e207SSatish Balay   *nz = bs*M;
3519867e207SSatish Balay 
3529867e207SSatish Balay   if (v) {
3539867e207SSatish Balay     *v = 0;
3549867e207SSatish Balay     if (*nz) {
3559867e207SSatish Balay       *v = (Scalar *) PetscMalloc( (*nz)*sizeof(Scalar) ); CHKPTRQ(*v);
3569867e207SSatish Balay       for ( i=0; i<M; i++ ) { /* for each block in the block row */
3579867e207SSatish Balay         v_i  = *v + i*bs;
3589867e207SSatish Balay         aa_i = aa + bs*bs*(ai[bn] + i);
3599867e207SSatish Balay         for ( j=bp,k=0; j<bs*bs; j+=bs,k++ ) {v_i[k] = aa_i[j];}
3609867e207SSatish Balay       }
3619867e207SSatish Balay     }
3629867e207SSatish Balay   }
3639867e207SSatish Balay 
3649867e207SSatish Balay   if (idx) {
3659867e207SSatish Balay     *idx = 0;
3669867e207SSatish Balay     if (*nz) {
3679867e207SSatish Balay       *idx = (int *) PetscMalloc( (*nz)*sizeof(int) ); CHKPTRQ(*idx);
3689867e207SSatish Balay       for ( i=0; i<M; i++ ) { /* for each block in the block row */
3699867e207SSatish Balay         idx_i = *idx + i*bs;
3709867e207SSatish Balay         itmp  = bs*aj[ai[bn] + i];
3719867e207SSatish Balay         for ( j=0; j<bs; j++ ) {idx_i[j] = itmp++;}
3729867e207SSatish Balay       }
3739867e207SSatish Balay     }
3749867e207SSatish Balay   }
3759867e207SSatish Balay   return 0;
3769867e207SSatish Balay }
3779867e207SSatish Balay 
3789867e207SSatish Balay int MatRestoreRow_SeqBAIJ(Mat A,int row,int *nz,int **idx,Scalar **v)
3799867e207SSatish Balay {
3809867e207SSatish Balay   if (idx) {if (*idx) PetscFree(*idx);}
3819867e207SSatish Balay   if (v)   {if (*v)   PetscFree(*v);}
3829867e207SSatish Balay   return 0;
3839867e207SSatish Balay }
384b6490206SBarry Smith 
385*584200bdSSatish Balay static int MatAssemblyEnd_SeqBAIJ(Mat A,MatAssemblyType mode)
386*584200bdSSatish Balay {
387*584200bdSSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
388*584200bdSSatish Balay   int        fshift = 0,i,j,*ai = a->i, *aj = a->j, *imax = a->imax;
389*584200bdSSatish Balay   int        m = a->m, *ip, N, *ailen = a->ilen,shift = a->indexshift;
390*584200bdSSatish Balay   int        bs = a->bs,  mbs = a->mbs, bs2 = bs*bs;
391*584200bdSSatish Balay   Scalar     *aa = a->a, *ap;
392*584200bdSSatish Balay 
393*584200bdSSatish Balay   if (mode == FLUSH_ASSEMBLY) return 0;
394*584200bdSSatish Balay 
395*584200bdSSatish Balay   for ( i=1; i<mbs; i++ ) {
396*584200bdSSatish Balay     /* move each row back by the amount of empty slots (fshift) before it*/
397*584200bdSSatish Balay     fshift += imax[i-1] - ailen[i-1];
398*584200bdSSatish Balay     if (fshift) {
399*584200bdSSatish Balay       ip = aj + ai[i] + shift; ap = aa + bs2*ai[i] + shift;
400*584200bdSSatish Balay       N = ailen[i];
401*584200bdSSatish Balay       for ( j=0; j<N; j++ ) {
402*584200bdSSatish Balay         ip[j-fshift] = ip[j];
403*584200bdSSatish Balay         PetscMemcpy(ap+(j-fshift)*bs2,ap+j+bs2,bs2);
404*584200bdSSatish Balay       }
405*584200bdSSatish Balay     }
406*584200bdSSatish Balay     ai[i] = ai[i-1] + ailen[i-1];
407*584200bdSSatish Balay   }
408*584200bdSSatish Balay   if (mbs) {
409*584200bdSSatish Balay     fshift += imax[mbs-1] - ailen[mbs-1];
410*584200bdSSatish Balay     ai[mbs] = ai[mbs-1] + ailen[mbs-1];
411*584200bdSSatish Balay   }
412*584200bdSSatish Balay   /* reset ilen and imax for each row */
413*584200bdSSatish Balay   for ( i=0; i<mbs; i++ ) {
414*584200bdSSatish Balay     ailen[i] = imax[i] = ai[i+1] - ai[i];
415*584200bdSSatish Balay   }
416*584200bdSSatish Balay   a->nz = (ai[m] + shift)*bs2;
417*584200bdSSatish Balay 
418*584200bdSSatish Balay   /* diagonals may have moved, so kill the diagonal pointers */
419*584200bdSSatish Balay   if (fshift && a->diag) {
420*584200bdSSatish Balay     PetscFree(a->diag);
421*584200bdSSatish Balay     PLogObjectMemory(A,-(m+1)*sizeof(int));
422*584200bdSSatish Balay     a->diag = 0;
423*584200bdSSatish Balay   }
424*584200bdSSatish Balay   PLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Unneeded storage space %d used %d rows %d\n",
425*584200bdSSatish Balay            fshift,a->nz,m);
426*584200bdSSatish Balay   PLogInfo(A,"MatAssemblyEnd_SeqBAIJ:Number of mallocs during MatSetValues %d\n",
427*584200bdSSatish Balay            a->reallocs);
428*584200bdSSatish Balay   return 0;
429*584200bdSSatish Balay }
430*584200bdSSatish Balay 
431b6490206SBarry Smith static int MatZeroEntries_SeqBAIJ(Mat A)
4322593348eSBarry Smith {
433b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
434de6a44a3SBarry Smith   PetscMemzero(a->a,a->bs*a->bs*a->i[a->mbs]*sizeof(Scalar));
4352593348eSBarry Smith   return 0;
4362593348eSBarry Smith }
4372593348eSBarry Smith 
438b6490206SBarry Smith int MatDestroy_SeqBAIJ(PetscObject obj)
4392593348eSBarry Smith {
4402593348eSBarry Smith   Mat         A  = (Mat) obj;
441b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
4422593348eSBarry Smith 
4432593348eSBarry Smith #if defined(PETSC_LOG)
4442593348eSBarry Smith   PLogObjectState(obj,"Rows=%d, Cols=%d, NZ=%d",a->m,a->n,a->nz);
4452593348eSBarry Smith #endif
4462593348eSBarry Smith   PetscFree(a->a);
4472593348eSBarry Smith   if (!a->singlemalloc) { PetscFree(a->i); PetscFree(a->j);}
4482593348eSBarry Smith   if (a->diag) PetscFree(a->diag);
4492593348eSBarry Smith   if (a->ilen) PetscFree(a->ilen);
4502593348eSBarry Smith   if (a->imax) PetscFree(a->imax);
4512593348eSBarry Smith   if (a->solve_work) PetscFree(a->solve_work);
452de6a44a3SBarry Smith   if (a->mult_work) PetscFree(a->mult_work);
4532593348eSBarry Smith   PetscFree(a);
454f2655603SLois Curfman McInnes   PLogObjectDestroy(A);
455f2655603SLois Curfman McInnes   PetscHeaderDestroy(A);
4562593348eSBarry Smith   return 0;
4572593348eSBarry Smith }
4582593348eSBarry Smith 
459b6490206SBarry Smith static int MatSetOption_SeqBAIJ(Mat A,MatOption op)
4602593348eSBarry Smith {
461b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
4622593348eSBarry Smith   if      (op == ROW_ORIENTED)              a->roworiented = 1;
4632593348eSBarry Smith   else if (op == COLUMN_ORIENTED)           a->roworiented = 0;
4642593348eSBarry Smith   else if (op == COLUMNS_SORTED)            a->sorted      = 1;
4652593348eSBarry Smith   else if (op == NO_NEW_NONZERO_LOCATIONS)  a->nonew       = 1;
4662593348eSBarry Smith   else if (op == YES_NEW_NONZERO_LOCATIONS) a->nonew       = 0;
4672593348eSBarry Smith   else if (op == ROWS_SORTED ||
4682593348eSBarry Smith            op == SYMMETRIC_MATRIX ||
4692593348eSBarry Smith            op == STRUCTURALLY_SYMMETRIC_MATRIX ||
4702593348eSBarry Smith            op == YES_NEW_DIAGONALS)
47194a424c1SBarry Smith     PLogInfo(A,"Info:MatSetOption_SeqBAIJ:Option ignored\n");
4722593348eSBarry Smith   else if (op == NO_NEW_DIAGONALS)
473b6490206SBarry Smith     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqBAIJ:NO_NEW_DIAGONALS");}
4742593348eSBarry Smith   else
475b6490206SBarry Smith     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqBAIJ:unknown option");}
4762593348eSBarry Smith   return 0;
4772593348eSBarry Smith }
4782593348eSBarry Smith 
4792593348eSBarry Smith 
4802593348eSBarry Smith /* -------------------------------------------------------*/
4812593348eSBarry Smith /* Should check that shapes of vectors and matrices match */
4822593348eSBarry Smith /* -------------------------------------------------------*/
483b6490206SBarry Smith #include "pinclude/plapack.h"
484b6490206SBarry Smith 
485b6490206SBarry Smith static int MatMult_SeqBAIJ(Mat A,Vec xx,Vec yy)
4862593348eSBarry Smith {
487b6490206SBarry Smith   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
488b6490206SBarry Smith   Scalar          *xg,*yg;
489b6490206SBarry Smith   register Scalar *x, *y, *v, sum,*xb, sum1,sum2,sum3,sum4,sum5;
490b6490206SBarry Smith   register Scalar x1,x2,x3,x4,x5;
491b6490206SBarry Smith   int             mbs = a->mbs, m = a->m, i, *idx,*ii;
492b6490206SBarry Smith   int             bs = a->bs,j,n,bs2 = bs*bs;
4932593348eSBarry Smith 
494b6490206SBarry Smith   VecGetArray(xx,&xg); x = xg;  VecGetArray(yy,&yg); y = yg;
495b6490206SBarry Smith   PetscMemzero(y,m*sizeof(Scalar));
496b6490206SBarry Smith   x     = x;
4972593348eSBarry Smith   idx   = a->j;
4982593348eSBarry Smith   v     = a->a;
4992593348eSBarry Smith   ii    = a->i;
500b6490206SBarry Smith 
501b6490206SBarry Smith   switch (bs) {
502b6490206SBarry Smith     case 1:
5032593348eSBarry Smith      for ( i=0; i<m; i++ ) {
5042593348eSBarry Smith        n    = ii[1] - ii[0]; ii++;
5052593348eSBarry Smith        sum  = 0.0;
5062593348eSBarry Smith        while (n--) sum += *v++ * x[*idx++];
5072593348eSBarry Smith        y[i] = sum;
5082593348eSBarry Smith       }
5092593348eSBarry Smith       break;
510b6490206SBarry Smith     case 2:
511b6490206SBarry Smith       for ( i=0; i<mbs; i++ ) {
512de6a44a3SBarry Smith         n  = ii[1] - ii[0]; ii++;
513b6490206SBarry Smith         sum1 = 0.0; sum2 = 0.0;
514b6490206SBarry Smith         for ( j=0; j<n; j++ ) {
515b6490206SBarry Smith           xb = x + 2*(*idx++); x1 = xb[0]; x2 = xb[1];
516b6490206SBarry Smith           sum1 += v[0]*x1 + v[2]*x2;
517b6490206SBarry Smith           sum2 += v[1]*x1 + v[3]*x2;
518b6490206SBarry Smith           v += 4;
519b6490206SBarry Smith         }
520b6490206SBarry Smith         y[0] += sum1; y[1] += sum2;
521b6490206SBarry Smith         y += 2;
522b6490206SBarry Smith       }
523b6490206SBarry Smith       break;
524b6490206SBarry Smith     case 3:
525b6490206SBarry Smith       for ( i=0; i<mbs; i++ ) {
526de6a44a3SBarry Smith         n  = ii[1] - ii[0]; ii++;
527b6490206SBarry Smith         sum1 = 0.0; sum2 = 0.0; sum3 = 0.0;
528b6490206SBarry Smith         for ( j=0; j<n; j++ ) {
529b6490206SBarry Smith           xb = x + 3*(*idx++); x1 = xb[0]; x2 = xb[1]; x3 = xb[2];
530b6490206SBarry Smith           sum1 += v[0]*x1 + v[3]*x2 + v[6]*x3;
531b6490206SBarry Smith           sum2 += v[1]*x1 + v[4]*x2 + v[7]*x3;
532b6490206SBarry Smith           sum3 += v[2]*x1 + v[5]*x2 + v[8]*x3;
533b6490206SBarry Smith           v += 9;
534b6490206SBarry Smith         }
535b6490206SBarry Smith         y[0] += sum1; y[1] += sum2; y[2] += sum3;
536b6490206SBarry Smith         y += 3;
537b6490206SBarry Smith       }
538b6490206SBarry Smith       break;
539b6490206SBarry Smith     case 4:
540b6490206SBarry Smith       for ( i=0; i<mbs; i++ ) {
541de6a44a3SBarry Smith         n  = ii[1] - ii[0]; ii++;
542b6490206SBarry Smith         sum1 = 0.0; sum2 = 0.0; sum3 = 0.0; sum4 = 0.0;
543b6490206SBarry Smith         for ( j=0; j<n; j++ ) {
544b6490206SBarry Smith           xb = x + 4*(*idx++);
545b6490206SBarry Smith           x1 = xb[0]; x2 = xb[1]; x3 = xb[2]; x4 = xb[3];
546b6490206SBarry Smith           sum1 += v[0]*x1 + v[4]*x2 + v[8]*x3   + v[12]*x4;
547b6490206SBarry Smith           sum2 += v[1]*x1 + v[5]*x2 + v[9]*x3   + v[13]*x4;
548b6490206SBarry Smith           sum3 += v[2]*x1 + v[6]*x2 + v[10]*x3  + v[14]*x4;
549b6490206SBarry Smith           sum4 += v[3]*x1 + v[7]*x2 + v[11]*x3  + v[15]*x4;
550b6490206SBarry Smith           v += 16;
551b6490206SBarry Smith         }
552b6490206SBarry Smith         y[0] += sum1; y[1] += sum2; y[2] += sum3; y[3] += sum4;
553b6490206SBarry Smith         y += 4;
554b6490206SBarry Smith       }
555b6490206SBarry Smith       break;
556b6490206SBarry Smith     case 5:
557b6490206SBarry Smith       for ( i=0; i<mbs; i++ ) {
558de6a44a3SBarry Smith         n  = ii[1] - ii[0]; ii++;
559b6490206SBarry Smith         sum1 = 0.0; sum2 = 0.0; sum3 = 0.0; sum4 = 0.0; sum5 = 0.0;
560b6490206SBarry Smith         for ( j=0; j<n; j++ ) {
561b6490206SBarry Smith           xb = x + 5*(*idx++);
562b6490206SBarry Smith           x1 = xb[0]; x2 = xb[1]; x3 = xb[2]; x4 = xb[3]; x5 = xb[4];
563b6490206SBarry Smith           sum1 += v[0]*x1 + v[5]*x2 + v[10]*x3  + v[15]*x4 + v[20]*x5;
564b6490206SBarry Smith           sum2 += v[1]*x1 + v[6]*x2 + v[11]*x3  + v[16]*x4 + v[21]*x5;
565b6490206SBarry Smith           sum3 += v[2]*x1 + v[7]*x2 + v[12]*x3  + v[17]*x4 + v[22]*x5;
566b6490206SBarry Smith           sum4 += v[3]*x1 + v[8]*x2 + v[13]*x3  + v[18]*x4 + v[23]*x5;
567b6490206SBarry Smith           sum5 += v[4]*x1 + v[9]*x2 + v[14]*x3  + v[19]*x4 + v[24]*x5;
568b6490206SBarry Smith           v += 25;
569b6490206SBarry Smith         }
570b6490206SBarry Smith         y[0] += sum1; y[1] += sum2; y[2] += sum3; y[3] += sum4; y[4] += sum5;
571b6490206SBarry Smith         y += 5;
572b6490206SBarry Smith       }
573b6490206SBarry Smith       break;
574b6490206SBarry Smith       /* block sizes larger then 5 by 5 are handled by BLAS */
575b6490206SBarry Smith     default: {
576de6a44a3SBarry Smith       int  _One = 1,ncols,k; Scalar _DOne = 1.0, *work,*workt;
577de6a44a3SBarry Smith       if (!a->mult_work) {
578de6a44a3SBarry Smith         a->mult_work = (Scalar *) PetscMalloc(a->m*sizeof(Scalar));
579de6a44a3SBarry Smith         CHKPTRQ(a->mult_work);
580de6a44a3SBarry Smith       }
581de6a44a3SBarry Smith       work = a->mult_work;
582b6490206SBarry Smith       for ( i=0; i<mbs; i++ ) {
583de6a44a3SBarry Smith         n     = ii[1] - ii[0]; ii++;
584de6a44a3SBarry Smith         ncols = n*bs;
585de6a44a3SBarry Smith         workt = work;
586b6490206SBarry Smith         for ( j=0; j<n; j++ ) {
587b6490206SBarry Smith           xb = x + bs*(*idx++);
588de6a44a3SBarry Smith           for ( k=0; k<bs; k++ ) workt[k] = xb[k];
589de6a44a3SBarry Smith           workt += bs;
590b6490206SBarry Smith         }
591de6a44a3SBarry Smith         LAgemv_("N",&bs,&ncols,&_DOne,v,&bs,work,&_One,&_DOne,y,&_One);
592de6a44a3SBarry Smith         v += n*bs2;
593b6490206SBarry Smith         y += bs;
5942593348eSBarry Smith       }
5952593348eSBarry Smith     }
5962593348eSBarry Smith   }
597b6490206SBarry Smith   PLogFlops(2*bs2*a->nz - m);
5982593348eSBarry Smith   return 0;
5992593348eSBarry Smith }
6002593348eSBarry Smith 
601de6a44a3SBarry Smith static int MatGetInfo_SeqBAIJ(Mat A,MatInfoType flag,int *nz,int *nza,int *mem)
6022593348eSBarry Smith {
603b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
604bcd2baecSBarry Smith   if (nz)  *nz  = a->bs*a->bs*a->nz;
605bcd2baecSBarry Smith   if (nza) *nza = a->maxnz;
606bcd2baecSBarry Smith   if (mem) *mem = (int)A->mem;
6072593348eSBarry Smith   return 0;
6082593348eSBarry Smith }
6092593348eSBarry Smith 
61091d316f6SSatish Balay static int MatEqual_SeqBAIJ(Mat A,Mat B, PetscTruth* flg)
61191d316f6SSatish Balay {
61291d316f6SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *)A->data, *b = (Mat_SeqBAIJ *)B->data;
61391d316f6SSatish Balay 
61491d316f6SSatish Balay   if (B->type !=MATSEQBAIJ)SETERRQ(1,"MatEqual_SeqBAIJ:Matrices must be same type");
61591d316f6SSatish Balay 
61691d316f6SSatish Balay   /* If the  matrix/block dimensions are not equal, or no of nonzeros or shift */
61791d316f6SSatish Balay   if ((a->m != b->m) || (a->n !=b->n) || (a->bs != b->bs)||
61891d316f6SSatish Balay       (a->nz != b->nz)||(a->indexshift != b->indexshift)) {
61991d316f6SSatish Balay     *flg = PETSC_FALSE; return 0;
62091d316f6SSatish Balay   }
62191d316f6SSatish Balay 
62291d316f6SSatish Balay   /* if the a->i are the same */
62391d316f6SSatish Balay   if (PetscMemcmp(a->i,b->i, (a->mbs+1)*sizeof(int))) {
62491d316f6SSatish Balay     *flg = PETSC_FALSE; return 0;
62591d316f6SSatish Balay   }
62691d316f6SSatish Balay 
62791d316f6SSatish Balay   /* if a->j are the same */
62891d316f6SSatish Balay   if (PetscMemcmp(a->j,b->j,(a->nz)*sizeof(int))) {
62991d316f6SSatish Balay     *flg = PETSC_FALSE; return 0;
63091d316f6SSatish Balay   }
63191d316f6SSatish Balay 
63291d316f6SSatish Balay   /* if a->a are the same */
63391d316f6SSatish Balay   if (PetscMemcmp(a->a, b->a,(a->nz)*(a->bs)*(a->bs)*sizeof(Scalar))) {
63491d316f6SSatish Balay     *flg = PETSC_FALSE; return 0;
63591d316f6SSatish Balay   }
63691d316f6SSatish Balay   *flg = PETSC_TRUE;
63791d316f6SSatish Balay   return 0;
63891d316f6SSatish Balay 
63991d316f6SSatish Balay }
64091d316f6SSatish Balay 
64191d316f6SSatish Balay static int MatGetDiagonal_SeqBAIJ(Mat A,Vec v)
64291d316f6SSatish Balay {
64391d316f6SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
64417e48fc4SSatish Balay   int         i,j,k,n,row,bs,*ai,*aj,ambs;
64517e48fc4SSatish Balay   Scalar      *x, zero = 0.0,*aa,*aa_j;
64617e48fc4SSatish Balay 
64717e48fc4SSatish Balay   bs  = a->bs;
64817e48fc4SSatish Balay   aa   = a->a;
64917e48fc4SSatish Balay   ai   = a->i;
65017e48fc4SSatish Balay   aj   = a->j;
65117e48fc4SSatish Balay   ambs = a->mbs;
65291d316f6SSatish Balay 
65391d316f6SSatish Balay   VecSet(&zero,v);
65491d316f6SSatish Balay   VecGetArray(v,&x); VecGetLocalSize(v,&n);
6559867e207SSatish Balay   if (n != a->m) SETERRQ(1,"MatGetDiagonal_SeqBAIJ:Nonconforming matrix and vector");
65617e48fc4SSatish Balay   for ( i=0; i<ambs; i++ ) {
65717e48fc4SSatish Balay     for ( j=ai[i]; j<ai[i+1]; j++ ) {
65817e48fc4SSatish Balay       if (aj[j] == i) {
65917e48fc4SSatish Balay         row  = i*bs;
66017e48fc4SSatish Balay         aa_j = aa+j*bs*bs;
66117e48fc4SSatish Balay         for (k=0; k<bs*bs; k+=(bs+1),row++) x[row] = aa_j[k];
66291d316f6SSatish Balay         break;
66391d316f6SSatish Balay       }
66491d316f6SSatish Balay     }
66591d316f6SSatish Balay   }
66691d316f6SSatish Balay   return 0;
66791d316f6SSatish Balay }
66891d316f6SSatish Balay 
6699867e207SSatish Balay static int MatDiagonalScale_SeqBAIJ(Mat A,Vec ll,Vec rr)
6709867e207SSatish Balay {
6719867e207SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
6729867e207SSatish Balay   Scalar      *l,*r,x,*v,*aa,*li,*ri;
6739867e207SSatish Balay   int         i,j,k,lm,rn,M,m,n,*ai,*aj,mbs,tmp,bs;
6749867e207SSatish Balay 
6759867e207SSatish Balay   ai  = a->i;
6769867e207SSatish Balay   aj  = a->j;
6779867e207SSatish Balay   aa  = a->a;
6789867e207SSatish Balay   m   = a->m;
6799867e207SSatish Balay   n   = a->n;
6809867e207SSatish Balay   bs  = a->bs;
6819867e207SSatish Balay   mbs = a->mbs;
6829867e207SSatish Balay 
6839867e207SSatish Balay   if (ll) {
6849867e207SSatish Balay     VecGetArray(ll,&l); VecGetSize(ll,&lm);
6859867e207SSatish Balay     if (lm != m) SETERRQ(1,"MatDiagonalScale_SeqBAIJ:Left scaling vector wrong length");
6869867e207SSatish Balay     for ( i=0; i<mbs; i++ ) { /* for each block row */
6879867e207SSatish Balay       M  = ai[i+1] - ai[i];
6889867e207SSatish Balay       li = l + i*bs;
6899867e207SSatish Balay       v  = aa + bs*bs*ai[i];
6909867e207SSatish Balay       for ( j=0; j<M; j++ ) { /* for each block */
6919867e207SSatish Balay         for ( k=0; k<bs*bs; k++ ) {
6929867e207SSatish Balay           (*v++) *= li[k%bs];
6939867e207SSatish Balay         }
6949867e207SSatish Balay       }
6959867e207SSatish Balay     }
6969867e207SSatish Balay   }
6979867e207SSatish Balay 
6989867e207SSatish Balay   if (rr) {
6999867e207SSatish Balay     VecGetArray(rr,&r); VecGetSize(rr,&rn);
7009867e207SSatish Balay     if (rn != n) SETERRQ(1,"MatDiagonalScale_SeqBAIJ:Right scaling vector wrong length");
7019867e207SSatish Balay     for ( i=0; i<mbs; i++ ) { /* for each block row */
7029867e207SSatish Balay       M  = ai[i+1] - ai[i];
7039867e207SSatish Balay       v  = aa + bs*bs*ai[i];
7049867e207SSatish Balay       for ( j=0; j<M; j++ ) { /* for each block */
7059867e207SSatish Balay         ri = r + bs*aj[ai[i]+j];
7069867e207SSatish Balay         for ( k=0; k<bs; k++ ) {
7079867e207SSatish Balay           x = ri[k];
7089867e207SSatish Balay           for ( tmp=0; tmp<bs; tmp++ ) (*v++) *= x;
7099867e207SSatish Balay         }
7109867e207SSatish Balay       }
7119867e207SSatish Balay     }
7129867e207SSatish Balay   }
7139867e207SSatish Balay   return 0;
7149867e207SSatish Balay }
7159867e207SSatish Balay 
7169867e207SSatish Balay 
717b6490206SBarry Smith extern int MatLUFactorSymbolic_SeqBAIJ(Mat,IS,IS,double,Mat*);
718b6490206SBarry Smith extern int MatLUFactor_SeqBAIJ(Mat,IS,IS,double);
719b6490206SBarry Smith extern int MatSolve_SeqBAIJ(Mat,Vec,Vec);
7207fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_N(Mat,Mat*);
7217fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_1(Mat,Mat*);
7227fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_2(Mat,Mat*);
7237fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_3(Mat,Mat*);
7247fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_4(Mat,Mat*);
7257fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_5(Mat,Mat*);
7262593348eSBarry Smith 
727b6490206SBarry Smith static int MatNorm_SeqBAIJ(Mat A,NormType type,double *norm)
7282593348eSBarry Smith {
729b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
7302593348eSBarry Smith   Scalar      *v = a->a;
7312593348eSBarry Smith   double      sum = 0.0;
732b6490206SBarry Smith   int         i;
7332593348eSBarry Smith 
7342593348eSBarry Smith   if (type == NORM_FROBENIUS) {
7352593348eSBarry Smith     for (i=0; i<a->nz; i++ ) {
7362593348eSBarry Smith #if defined(PETSC_COMPLEX)
7372593348eSBarry Smith       sum += real(conj(*v)*(*v)); v++;
7382593348eSBarry Smith #else
7392593348eSBarry Smith       sum += (*v)*(*v); v++;
7402593348eSBarry Smith #endif
7412593348eSBarry Smith     }
7422593348eSBarry Smith     *norm = sqrt(sum);
7432593348eSBarry Smith   }
7442593348eSBarry Smith   else {
745b6490206SBarry Smith     SETERRQ(1,"MatNorm_SeqBAIJ:No support for this norm yet");
7462593348eSBarry Smith   }
7472593348eSBarry Smith   return 0;
7482593348eSBarry Smith }
7492593348eSBarry Smith 
7502593348eSBarry Smith /*
7512593348eSBarry Smith      note: This can only work for identity for row and col. It would
7522593348eSBarry Smith    be good to check this and otherwise generate an error.
7532593348eSBarry Smith */
754b6490206SBarry Smith static int MatILUFactor_SeqBAIJ(Mat inA,IS row,IS col,double efill,int fill)
7552593348eSBarry Smith {
756b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) inA->data;
7572593348eSBarry Smith   Mat         outA;
758de6a44a3SBarry Smith   int         ierr;
7592593348eSBarry Smith 
760b6490206SBarry Smith   if (fill != 0) SETERRQ(1,"MatILUFactor_SeqBAIJ:Only fill=0 supported");
7612593348eSBarry Smith 
7622593348eSBarry Smith   outA          = inA;
7632593348eSBarry Smith   inA->factor   = FACTOR_LU;
7642593348eSBarry Smith   a->row        = row;
7652593348eSBarry Smith   a->col        = col;
7662593348eSBarry Smith 
767de6a44a3SBarry Smith   a->solve_work = (Scalar *) PetscMalloc((a->m+a->bs)*sizeof(Scalar));CHKPTRQ(a->solve_work);
7682593348eSBarry Smith 
7692593348eSBarry Smith   if (!a->diag) {
770b6490206SBarry Smith     ierr = MatMarkDiag_SeqBAIJ(inA); CHKERRQ(ierr);
7712593348eSBarry Smith   }
7727fc0212eSBarry Smith   ierr = MatLUFactorNumeric(inA,&outA); CHKERRQ(ierr);
7732593348eSBarry Smith   return 0;
7742593348eSBarry Smith }
7752593348eSBarry Smith 
776b6490206SBarry Smith static int MatScale_SeqBAIJ(Scalar *alpha,Mat inA)
7772593348eSBarry Smith {
778b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) inA->data;
779b6490206SBarry Smith   int         one = 1, totalnz = a->bs*a->bs*a->nz;
780b6490206SBarry Smith   BLscal_( &totalnz, alpha, a->a, &one );
781b6490206SBarry Smith   PLogFlops(totalnz);
7822593348eSBarry Smith   return 0;
7832593348eSBarry Smith }
7842593348eSBarry Smith 
785b6490206SBarry Smith int MatPrintHelp_SeqBAIJ(Mat A)
7862593348eSBarry Smith {
7872593348eSBarry Smith   static int called = 0;
7882593348eSBarry Smith 
7892593348eSBarry Smith   if (called) return 0; else called = 1;
7902593348eSBarry Smith   return 0;
7912593348eSBarry Smith }
7922593348eSBarry Smith /* -------------------------------------------------------------------*/
793cd0e1443SSatish Balay static struct _MatOps MatOps = {MatSetValues_SeqBAIJ,
7949867e207SSatish Balay        MatGetRow_SeqBAIJ,MatRestoreRow_SeqBAIJ,
795b6490206SBarry Smith        MatMult_SeqBAIJ,0,
796b6490206SBarry Smith        0,0,
797de6a44a3SBarry Smith        MatSolve_SeqBAIJ,0,
798b6490206SBarry Smith        0,0,
799de6a44a3SBarry Smith        MatLUFactor_SeqBAIJ,0,
800b6490206SBarry Smith        0,
801b6490206SBarry Smith        0,
80217e48fc4SSatish Balay        MatGetInfo_SeqBAIJ,MatEqual_SeqBAIJ,
8039867e207SSatish Balay        MatGetDiagonal_SeqBAIJ,MatDiagonalScale_SeqBAIJ,MatNorm_SeqBAIJ,
804*584200bdSSatish Balay        0,MatAssemblyEnd_SeqBAIJ,
805b6490206SBarry Smith        0,
806b6490206SBarry Smith        MatSetOption_SeqBAIJ,MatZeroEntries_SeqBAIJ,0,
807b6490206SBarry Smith        MatGetReordering_SeqBAIJ,
8087fc0212eSBarry Smith        MatLUFactorSymbolic_SeqBAIJ,MatLUFactorNumeric_SeqBAIJ_N,0,0,
809b6490206SBarry Smith        MatGetSize_SeqBAIJ,MatGetSize_SeqBAIJ,MatGetOwnershipRange_SeqBAIJ,
810de6a44a3SBarry Smith        MatILUFactorSymbolic_SeqBAIJ,0,
811b6490206SBarry Smith        0,0,/*  MatConvert_SeqBAIJ  */ 0,
812b6490206SBarry Smith        0,0,
813b6490206SBarry Smith        MatConvertSameType_SeqBAIJ,0,0,
814b6490206SBarry Smith        MatILUFactor_SeqBAIJ,0,0,
815b6490206SBarry Smith        0,0,
816b6490206SBarry Smith        0,0,
817b6490206SBarry Smith        MatPrintHelp_SeqBAIJ,MatScale_SeqBAIJ,
818b6490206SBarry Smith        0};
8192593348eSBarry Smith 
8202593348eSBarry Smith /*@C
821b6490206SBarry Smith    MatCreateSeqBAIJ - Creates a sparse matrix in AIJ (compressed row) format
8222593348eSBarry Smith    (the default parallel PETSc format).  For good matrix assembly performance
8232593348eSBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
8242593348eSBarry Smith    (or nzz).  By setting these parameters accurately, performance can be
8252593348eSBarry Smith    increased by more than a factor of 50.
8262593348eSBarry Smith 
8272593348eSBarry Smith    Input Parameters:
8282593348eSBarry Smith .  comm - MPI communicator, set to MPI_COMM_SELF
829b6490206SBarry Smith .  bs - size of block
8302593348eSBarry Smith .  m - number of rows
8312593348eSBarry Smith .  n - number of columns
832b6490206SBarry Smith .  nz - number of block nonzeros per block row (same for all rows)
833b6490206SBarry Smith .  nzz - number of block nonzeros per block row or PETSC_NULL
834b6490206SBarry Smith          (possibly different for each row)
8352593348eSBarry Smith 
8362593348eSBarry Smith    Output Parameter:
8372593348eSBarry Smith .  A - the matrix
8382593348eSBarry Smith 
8392593348eSBarry Smith    Notes:
840b6490206SBarry Smith    The BAIJ format, is fully compatible with standard Fortran 77
8412593348eSBarry Smith    storage.  That is, the stored row and column indices can begin at
8422593348eSBarry Smith    either one (as in Fortran) or zero.  See the users manual for details.
8432593348eSBarry Smith 
8442593348eSBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
8452593348eSBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
8462593348eSBarry Smith    allocation.  For additional details, see the users manual chapter on
8472593348eSBarry Smith    matrices and the file $(PETSC_DIR)/Performance.
8482593348eSBarry Smith 
8492593348eSBarry Smith .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues()
8502593348eSBarry Smith @*/
851b6490206SBarry Smith int MatCreateSeqBAIJ(MPI_Comm comm,int bs,int m,int n,int nz,int *nnz, Mat *A)
8522593348eSBarry Smith {
8532593348eSBarry Smith   Mat         B;
854b6490206SBarry Smith   Mat_SeqBAIJ *b;
855b6490206SBarry Smith   int         i,len,ierr, flg,mbs = m/bs;
856b6490206SBarry Smith 
857b6490206SBarry Smith   if (mbs*bs != m)
858b6490206SBarry Smith     SETERRQ(1,"MatCreateSeqBAIJ:Number rows must be divisible by blocksize");
8592593348eSBarry Smith 
8602593348eSBarry Smith   *A      = 0;
861b6490206SBarry Smith   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSEQBAIJ,comm);
8622593348eSBarry Smith   PLogObjectCreate(B);
863b6490206SBarry Smith   B->data             = (void *) (b = PetscNew(Mat_SeqBAIJ)); CHKPTRQ(b);
8642593348eSBarry Smith   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
8657fc0212eSBarry Smith   switch (bs) {
8667fc0212eSBarry Smith     case 1:
8677fc0212eSBarry Smith       B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_1;
8687fc0212eSBarry Smith       break;
8694eeb42bcSBarry Smith     case 2:
8704eeb42bcSBarry Smith       B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_2;
8716d84be18SBarry Smith       break;
872f327dd97SBarry Smith     case 3:
873f327dd97SBarry Smith       B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_3;
8744eeb42bcSBarry Smith       break;
8756d84be18SBarry Smith     case 4:
8766d84be18SBarry Smith       B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_4;
8776d84be18SBarry Smith       break;
8786d84be18SBarry Smith     case 5:
8796d84be18SBarry Smith       B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_5;
8806d84be18SBarry Smith       break;
8817fc0212eSBarry Smith   }
882b6490206SBarry Smith   B->destroy          = MatDestroy_SeqBAIJ;
883b6490206SBarry Smith   B->view             = MatView_SeqBAIJ;
8842593348eSBarry Smith   B->factor           = 0;
8852593348eSBarry Smith   B->lupivotthreshold = 1.0;
8862593348eSBarry Smith   b->row              = 0;
8872593348eSBarry Smith   b->col              = 0;
8882593348eSBarry Smith   b->reallocs         = 0;
8892593348eSBarry Smith 
8902593348eSBarry Smith   b->m       = m;
891b6490206SBarry Smith   b->mbs     = mbs;
8922593348eSBarry Smith   b->n       = n;
893b6490206SBarry Smith   b->imax    = (int *) PetscMalloc( (mbs+1)*sizeof(int) ); CHKPTRQ(b->imax);
8942593348eSBarry Smith   if (nnz == PETSC_NULL) {
895de6a44a3SBarry Smith     if (nz == PETSC_DEFAULT) nz = 5;
8962593348eSBarry Smith     else if (nz <= 0)        nz = 1;
897b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) b->imax[i] = nz;
898b6490206SBarry Smith     nz = nz*mbs;
8992593348eSBarry Smith   }
9002593348eSBarry Smith   else {
9012593348eSBarry Smith     nz = 0;
902b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) {b->imax[i] = nnz[i]; nz += nnz[i];}
9032593348eSBarry Smith   }
9042593348eSBarry Smith 
9052593348eSBarry Smith   /* allocate the matrix space */
906b6490206SBarry Smith   len   = nz*sizeof(int) + nz*bs*bs*sizeof(Scalar) + (b->m+1)*sizeof(int);
9072593348eSBarry Smith   b->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(b->a);
908b6490206SBarry Smith   PetscMemzero(b->a,nz*bs*bs*sizeof(Scalar));
909b6490206SBarry Smith   b->j  = (int *) (b->a + nz*bs*bs);
9102593348eSBarry Smith   PetscMemzero(b->j,nz*sizeof(int));
9112593348eSBarry Smith   b->i  = b->j + nz;
9122593348eSBarry Smith   b->singlemalloc = 1;
9132593348eSBarry Smith 
914de6a44a3SBarry Smith   b->i[0] = 0;
915b6490206SBarry Smith   for (i=1; i<mbs+1; i++) {
9162593348eSBarry Smith     b->i[i] = b->i[i-1] + b->imax[i-1];
9172593348eSBarry Smith   }
9182593348eSBarry Smith 
919b6490206SBarry Smith   /* b->ilen will count nonzeros in each block row so far. */
920b6490206SBarry Smith   b->ilen = (int *) PetscMalloc((mbs+1)*sizeof(int));
921b6490206SBarry Smith   PLogObjectMemory(B,len+2*(mbs+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqBAIJ));
922b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) { b->ilen[i] = 0;}
9232593348eSBarry Smith 
924b6490206SBarry Smith   b->bs               = bs;
925b6490206SBarry Smith   b->mbs              = mbs;
9262593348eSBarry Smith   b->nz               = 0;
9272593348eSBarry Smith   b->maxnz            = nz;
9282593348eSBarry Smith   b->sorted           = 0;
9292593348eSBarry Smith   b->roworiented      = 1;
9302593348eSBarry Smith   b->nonew            = 0;
9312593348eSBarry Smith   b->diag             = 0;
9322593348eSBarry Smith   b->solve_work       = 0;
933de6a44a3SBarry Smith   b->mult_work        = 0;
9342593348eSBarry Smith   b->spptr            = 0;
9352593348eSBarry Smith 
9362593348eSBarry Smith   *A = B;
9372593348eSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-help", &flg); CHKERRQ(ierr);
9382593348eSBarry Smith   if (flg) {ierr = MatPrintHelp(B); CHKERRQ(ierr); }
9392593348eSBarry Smith   return 0;
9402593348eSBarry Smith }
9412593348eSBarry Smith 
942b6490206SBarry Smith int MatConvertSameType_SeqBAIJ(Mat A,Mat *B,int cpvalues)
9432593348eSBarry Smith {
9442593348eSBarry Smith   Mat         C;
945b6490206SBarry Smith   Mat_SeqBAIJ *c,*a = (Mat_SeqBAIJ *) A->data;
946de6a44a3SBarry Smith   int         i,len, mbs = a->mbs, bs = a->bs,nz = a->nz;
947de6a44a3SBarry Smith 
948de6a44a3SBarry Smith   if (a->i[mbs] != nz) SETERRQ(1,"MatConvertSameType_SeqBAIJ:Corrupt matrix");
9492593348eSBarry Smith 
9502593348eSBarry Smith   *B = 0;
951b6490206SBarry Smith   PetscHeaderCreate(C,_Mat,MAT_COOKIE,MATSEQBAIJ,A->comm);
9522593348eSBarry Smith   PLogObjectCreate(C);
953b6490206SBarry Smith   C->data       = (void *) (c = PetscNew(Mat_SeqBAIJ)); CHKPTRQ(c);
9542593348eSBarry Smith   PetscMemcpy(&C->ops,&A->ops,sizeof(struct _MatOps));
955b6490206SBarry Smith   C->destroy    = MatDestroy_SeqBAIJ;
956b6490206SBarry Smith   C->view       = MatView_SeqBAIJ;
9572593348eSBarry Smith   C->factor     = A->factor;
9582593348eSBarry Smith   c->row        = 0;
9592593348eSBarry Smith   c->col        = 0;
9602593348eSBarry Smith   C->assembled  = PETSC_TRUE;
9612593348eSBarry Smith 
9622593348eSBarry Smith   c->m          = a->m;
9632593348eSBarry Smith   c->n          = a->n;
964b6490206SBarry Smith   c->bs         = a->bs;
965b6490206SBarry Smith   c->mbs        = a->mbs;
966b6490206SBarry Smith   c->nbs        = a->nbs;
9672593348eSBarry Smith 
968b6490206SBarry Smith   c->imax       = (int *) PetscMalloc((mbs+1)*sizeof(int)); CHKPTRQ(c->imax);
969b6490206SBarry Smith   c->ilen       = (int *) PetscMalloc((mbs+1)*sizeof(int)); CHKPTRQ(c->ilen);
970b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
9712593348eSBarry Smith     c->imax[i] = a->imax[i];
9722593348eSBarry Smith     c->ilen[i] = a->ilen[i];
9732593348eSBarry Smith   }
9742593348eSBarry Smith 
9752593348eSBarry Smith   /* allocate the matrix space */
9762593348eSBarry Smith   c->singlemalloc = 1;
977de6a44a3SBarry Smith   len   = (mbs+1)*sizeof(int) + nz*(bs*bs*sizeof(Scalar) + sizeof(int));
9782593348eSBarry Smith   c->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(c->a);
979de6a44a3SBarry Smith   c->j  = (int *) (c->a + nz*bs*bs);
980de6a44a3SBarry Smith   c->i  = c->j + nz;
981b6490206SBarry Smith   PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(int));
982b6490206SBarry Smith   if (mbs > 0) {
983de6a44a3SBarry Smith     PetscMemcpy(c->j,a->j,nz*sizeof(int));
9842593348eSBarry Smith     if (cpvalues == COPY_VALUES) {
985de6a44a3SBarry Smith       PetscMemcpy(c->a,a->a,bs*bs*nz*sizeof(Scalar));
9862593348eSBarry Smith     }
9872593348eSBarry Smith   }
9882593348eSBarry Smith 
989b6490206SBarry Smith   PLogObjectMemory(C,len+2*(mbs+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqBAIJ));
9902593348eSBarry Smith   c->sorted      = a->sorted;
9912593348eSBarry Smith   c->roworiented = a->roworiented;
9922593348eSBarry Smith   c->nonew       = a->nonew;
9932593348eSBarry Smith 
9942593348eSBarry Smith   if (a->diag) {
995b6490206SBarry Smith     c->diag = (int *) PetscMalloc( (mbs+1)*sizeof(int) ); CHKPTRQ(c->diag);
996b6490206SBarry Smith     PLogObjectMemory(C,(mbs+1)*sizeof(int));
997b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) {
9982593348eSBarry Smith       c->diag[i] = a->diag[i];
9992593348eSBarry Smith     }
10002593348eSBarry Smith   }
10012593348eSBarry Smith   else c->diag          = 0;
10022593348eSBarry Smith   c->nz                 = a->nz;
10032593348eSBarry Smith   c->maxnz              = a->maxnz;
10042593348eSBarry Smith   c->solve_work         = 0;
10052593348eSBarry Smith   c->spptr              = 0;      /* Dangerous -I'm throwing away a->spptr */
10067fc0212eSBarry Smith   c->mult_work          = 0;
10072593348eSBarry Smith   *B = C;
10082593348eSBarry Smith   return 0;
10092593348eSBarry Smith }
10102593348eSBarry Smith 
101119bcc07fSBarry Smith int MatLoad_SeqBAIJ(Viewer viewer,MatType type,Mat *A)
10122593348eSBarry Smith {
1013b6490206SBarry Smith   Mat_SeqBAIJ  *a;
10142593348eSBarry Smith   Mat          B;
1015de6a44a3SBarry Smith   int          i,nz,ierr,fd,header[4],size,*rowlengths=0,M,N,bs=1,flg;
1016b6490206SBarry Smith   int          *mask,mbs,*jj,j,rowcount,nzcount,k,*browlengths,maskcount;
101735aab85fSBarry Smith   int          kmax,jcount,block,idx,point,nzcountb,extra_rows;
1018de6a44a3SBarry Smith   int          *masked, nmask,tmp,ishift,bs2;
1019b6490206SBarry Smith   Scalar       *aa;
102019bcc07fSBarry Smith   MPI_Comm     comm = ((PetscObject) viewer)->comm;
10212593348eSBarry Smith 
102235aab85fSBarry Smith   ierr = OptionsGetInt(PETSC_NULL,"-mat_block_size",&bs,&flg);CHKERRQ(ierr);
1023de6a44a3SBarry Smith   bs2  = bs*bs;
1024b6490206SBarry Smith 
10252593348eSBarry Smith   MPI_Comm_size(comm,&size);
1026b6490206SBarry Smith   if (size > 1) SETERRQ(1,"MatLoad_SeqBAIJ:view must have one processor");
102790ace30eSBarry Smith   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
102877c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,header,4,BINARY_INT); CHKERRQ(ierr);
1029de6a44a3SBarry Smith   if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_SeqBAIJ:not Mat object");
10302593348eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
10312593348eSBarry Smith 
1032b6490206SBarry Smith   if (M != N) SETERRQ(1,"MatLoad_SeqBAIJ:Can only do square matrices");
103335aab85fSBarry Smith 
103435aab85fSBarry Smith   /*
103535aab85fSBarry Smith      This code adds extra rows to make sure the number of rows is
103635aab85fSBarry Smith     divisible by the blocksize
103735aab85fSBarry Smith   */
1038b6490206SBarry Smith   mbs        = M/bs;
103935aab85fSBarry Smith   extra_rows = bs - M + bs*(mbs);
104035aab85fSBarry Smith   if (extra_rows == bs) extra_rows = 0;
104135aab85fSBarry Smith   else                  mbs++;
104235aab85fSBarry Smith   if (extra_rows) {
104335aab85fSBarry Smith     PLogInfo(0,"MatLoad_SeqBAIJ:Padding loading matrix to match blocksize");
104435aab85fSBarry Smith   }
1045b6490206SBarry Smith 
10462593348eSBarry Smith   /* read in row lengths */
104735aab85fSBarry Smith   rowlengths = (int*) PetscMalloc((M+extra_rows)*sizeof(int));CHKPTRQ(rowlengths);
104877c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,rowlengths,M,BINARY_INT); CHKERRQ(ierr);
104935aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) rowlengths[M+i] = 1;
10502593348eSBarry Smith 
1051b6490206SBarry Smith   /* read in column indices */
105235aab85fSBarry Smith   jj = (int*) PetscMalloc( (nz+extra_rows)*sizeof(int) ); CHKPTRQ(jj);
105377c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,jj,nz,BINARY_INT); CHKERRQ(ierr);
105435aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) jj[nz+i] = M+i;
1055b6490206SBarry Smith 
1056b6490206SBarry Smith   /* loop over row lengths determining block row lengths */
1057b6490206SBarry Smith   browlengths = (int *) PetscMalloc(mbs*sizeof(int));CHKPTRQ(browlengths);
1058b6490206SBarry Smith   PetscMemzero(browlengths,mbs*sizeof(int));
105935aab85fSBarry Smith   mask   = (int *) PetscMalloc( 2*mbs*sizeof(int) ); CHKPTRQ(mask);
106035aab85fSBarry Smith   PetscMemzero(mask,mbs*sizeof(int));
106135aab85fSBarry Smith   masked = mask + mbs;
1062b6490206SBarry Smith   rowcount = 0; nzcount = 0;
1063b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
106435aab85fSBarry Smith     nmask = 0;
1065b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
1066b6490206SBarry Smith       kmax = rowlengths[rowcount];
1067b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
106835aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
106935aab85fSBarry Smith         if (!mask[tmp]) {masked[nmask++] = tmp; mask[tmp] = 1;}
1070b6490206SBarry Smith       }
1071b6490206SBarry Smith       rowcount++;
1072b6490206SBarry Smith     }
107335aab85fSBarry Smith     browlengths[i] += nmask;
107435aab85fSBarry Smith     /* zero out the mask elements we set */
107535aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) mask[masked[j]] = 0;
1076b6490206SBarry Smith   }
1077b6490206SBarry Smith 
10782593348eSBarry Smith   /* create our matrix */
107935aab85fSBarry Smith   ierr = MatCreateSeqBAIJ(comm,bs,M+extra_rows,N+extra_rows,0,browlengths,A);
108035aab85fSBarry Smith          CHKERRQ(ierr);
10812593348eSBarry Smith   B = *A;
1082b6490206SBarry Smith   a = (Mat_SeqBAIJ *) B->data;
10832593348eSBarry Smith 
10842593348eSBarry Smith   /* set matrix "i" values */
1085de6a44a3SBarry Smith   a->i[0] = 0;
1086b6490206SBarry Smith   for ( i=1; i<= mbs; i++ ) {
1087b6490206SBarry Smith     a->i[i]      = a->i[i-1] + browlengths[i-1];
1088b6490206SBarry Smith     a->ilen[i-1] = browlengths[i-1];
10892593348eSBarry Smith   }
10909867e207SSatish Balay   a->indexshift = 0;
1091b6490206SBarry Smith   a->nz         = 0;
1092b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) a->nz += browlengths[i];
10932593348eSBarry Smith 
1094b6490206SBarry Smith   /* read in nonzero values */
109535aab85fSBarry Smith   aa = (Scalar *) PetscMalloc((nz+extra_rows)*sizeof(Scalar));CHKPTRQ(aa);
109677c4ece6SBarry Smith   ierr = PetscBinaryRead(fd,aa,nz,BINARY_SCALAR); CHKERRQ(ierr);
109735aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) aa[nz+i] = 1.0;
1098b6490206SBarry Smith 
1099b6490206SBarry Smith   /* set "a" and "j" values into matrix */
1100b6490206SBarry Smith   nzcount = 0; jcount = 0;
1101b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
1102b6490206SBarry Smith     nzcountb = nzcount;
110335aab85fSBarry Smith     nmask    = 0;
1104b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
1105b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
1106b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
110735aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
110835aab85fSBarry Smith 	if (!mask[tmp]) { masked[nmask++] = tmp; mask[tmp] = 1;}
1109b6490206SBarry Smith       }
1110b6490206SBarry Smith       rowcount++;
1111b6490206SBarry Smith     }
1112de6a44a3SBarry Smith     /* sort the masked values */
111377c4ece6SBarry Smith     PetscSortInt(nmask,masked);
1114de6a44a3SBarry Smith 
1115b6490206SBarry Smith     /* set "j" values into matrix */
1116b6490206SBarry Smith     maskcount = 1;
111735aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) {
111835aab85fSBarry Smith       a->j[jcount++]  = masked[j];
1119de6a44a3SBarry Smith       mask[masked[j]] = maskcount++;
1120b6490206SBarry Smith     }
1121b6490206SBarry Smith     /* set "a" values into matrix */
1122de6a44a3SBarry Smith     ishift = bs2*a->i[i];
1123b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
1124b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
1125b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
1126de6a44a3SBarry Smith         tmp    = jj[nzcountb]/bs ;
1127de6a44a3SBarry Smith         block  = mask[tmp] - 1;
1128de6a44a3SBarry Smith         point  = jj[nzcountb] - bs*tmp;
1129de6a44a3SBarry Smith         idx    = ishift + bs2*block + j + bs*point;
1130b6490206SBarry Smith         a->a[idx] = aa[nzcountb++];
1131b6490206SBarry Smith       }
1132b6490206SBarry Smith     }
113335aab85fSBarry Smith     /* zero out the mask elements we set */
113435aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) mask[masked[j]] = 0;
1135b6490206SBarry Smith   }
113635aab85fSBarry Smith   if (jcount != a->nz) SETERRQ(1,"MatLoad_SeqBAIJ:Error bad binary matrix");
1137b6490206SBarry Smith 
1138b6490206SBarry Smith   PetscFree(rowlengths);
1139b6490206SBarry Smith   PetscFree(browlengths);
1140b6490206SBarry Smith   PetscFree(aa);
1141b6490206SBarry Smith   PetscFree(jj);
1142b6490206SBarry Smith   PetscFree(mask);
1143b6490206SBarry Smith 
1144b6490206SBarry Smith   B->assembled = PETSC_TRUE;
1145de6a44a3SBarry Smith 
1146de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_info",&flg); CHKERRQ(ierr);
1147de6a44a3SBarry Smith   if (flg) {
114819bcc07fSBarry Smith     Viewer tviewer;
114919bcc07fSBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&tviewer);CHKERRQ(ierr);
115090ace30eSBarry Smith     ierr = ViewerSetFormat(tviewer,ASCII_FORMAT_INFO,0);CHKERRQ(ierr);
115119bcc07fSBarry Smith     ierr = MatView(B,tviewer); CHKERRQ(ierr);
115219bcc07fSBarry Smith     ierr = ViewerDestroy(tviewer); CHKERRQ(ierr);
1153de6a44a3SBarry Smith   }
1154de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_info_detailed",&flg);CHKERRQ(ierr);
1155de6a44a3SBarry Smith   if (flg) {
115619bcc07fSBarry Smith     Viewer tviewer;
115719bcc07fSBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&tviewer);CHKERRQ(ierr);
115890ace30eSBarry Smith     ierr = ViewerSetFormat(tviewer,ASCII_FORMAT_INFO_DETAILED,0);CHKERRQ(ierr);
115919bcc07fSBarry Smith     ierr = MatView(B,tviewer); CHKERRQ(ierr);
116019bcc07fSBarry Smith     ierr = ViewerDestroy(tviewer); CHKERRQ(ierr);
1161de6a44a3SBarry Smith   }
1162de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view",&flg); CHKERRQ(ierr);
1163de6a44a3SBarry Smith   if (flg) {
116419bcc07fSBarry Smith     Viewer tviewer;
116519bcc07fSBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&tviewer);CHKERRQ(ierr);
116619bcc07fSBarry Smith     ierr = MatView(B,tviewer); CHKERRQ(ierr);
116719bcc07fSBarry Smith     ierr = ViewerDestroy(tviewer); CHKERRQ(ierr);
1168de6a44a3SBarry Smith   }
1169de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_matlab",&flg); CHKERRQ(ierr);
1170de6a44a3SBarry Smith   if (flg) {
117119bcc07fSBarry Smith     Viewer tviewer;
117219bcc07fSBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&tviewer);CHKERRQ(ierr);
117390ace30eSBarry Smith     ierr = ViewerSetFormat(tviewer,ASCII_FORMAT_MATLAB,"M");CHKERRQ(ierr);
117419bcc07fSBarry Smith     ierr = MatView(B,tviewer); CHKERRQ(ierr);
117519bcc07fSBarry Smith     ierr = ViewerDestroy(tviewer); CHKERRQ(ierr);
1176de6a44a3SBarry Smith   }
1177de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_draw",&flg); CHKERRQ(ierr);
1178de6a44a3SBarry Smith   if (flg) {
117919bcc07fSBarry Smith     Viewer tviewer;
118019bcc07fSBarry Smith     ierr = ViewerDrawOpenX(B->comm,0,0,0,0,300,300,&tviewer); CHKERRQ(ierr);
118119bcc07fSBarry Smith     ierr = MatView(B,(Viewer)tviewer); CHKERRQ(ierr);
118219bcc07fSBarry Smith     ierr = ViewerFlush(tviewer); CHKERRQ(ierr);
118319bcc07fSBarry Smith     ierr = ViewerDestroy(tviewer); CHKERRQ(ierr);
1184de6a44a3SBarry Smith   }
11852593348eSBarry Smith   return 0;
11862593348eSBarry Smith }
11872593348eSBarry Smith 
11882593348eSBarry Smith 
11892593348eSBarry Smith 
1190