xref: /petsc/src/mat/impls/baij/seq/baij.c (revision 6d84be18fbb99ba69be7b8bdde5411a66955b7ea)
1b6490206SBarry Smith 
22593348eSBarry Smith #ifndef lint
3*6d84be18SBarry Smith static char vcid[] = "$Id: baij.c,v 1.8 1996/02/23 22:03:48 bsmith Exp bsmith $";
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 
15b6490206SBarry Smith extern int MatToSymmetricIJ_SeqAIJ(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;
20de6a44a3SBarry Smith   int         ierr, *ia, *ja,n = a->mbs,*idx,i;
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 
40de6a44a3SBarry Smith   ierr = MatToSymmetricIJ_SeqAIJ(n,a->i,a->j,0,&ia,&ja);CHKERRQ(ierr);
41de6a44a3SBarry Smith   ierr = MatGetReordering_IJ(n,ia,ja,type,rperm,cperm); CHKERRQ(ierr);
422593348eSBarry Smith 
432593348eSBarry Smith   PetscFree(ia); PetscFree(ja);
442593348eSBarry Smith   return 0;
452593348eSBarry Smith }
462593348eSBarry Smith 
47de6a44a3SBarry Smith /*
48de6a44a3SBarry Smith      Adds diagonal pointers to sparse matrix structure.
49de6a44a3SBarry Smith */
50de6a44a3SBarry Smith 
51de6a44a3SBarry Smith int MatMarkDiag_SeqBAIJ(Mat A)
52de6a44a3SBarry Smith {
53de6a44a3SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
547fc0212eSBarry Smith   int         i,j, *diag, m = a->mbs;
55de6a44a3SBarry Smith 
56de6a44a3SBarry Smith   diag = (int *) PetscMalloc( (m+1)*sizeof(int)); CHKPTRQ(diag);
57de6a44a3SBarry Smith   PLogObjectMemory(A,(m+1)*sizeof(int));
587fc0212eSBarry Smith   for ( i=0; i<m; i++ ) {
59de6a44a3SBarry Smith     for ( j=a->i[i]; j<a->i[i+1]; j++ ) {
60de6a44a3SBarry Smith       if (a->j[j] == i) {
61de6a44a3SBarry Smith         diag[i] = j;
62de6a44a3SBarry Smith         break;
63de6a44a3SBarry Smith       }
64de6a44a3SBarry Smith     }
65de6a44a3SBarry Smith   }
66de6a44a3SBarry Smith   a->diag = diag;
67de6a44a3SBarry Smith   return 0;
68de6a44a3SBarry Smith }
692593348eSBarry Smith 
702593348eSBarry Smith #include "draw.h"
712593348eSBarry Smith #include "pinclude/pviewer.h"
722593348eSBarry Smith #include "sysio.h"
732593348eSBarry Smith 
74b6490206SBarry Smith static int MatView_SeqBAIJ_Binary(Mat A,Viewer viewer)
752593348eSBarry Smith {
76b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
77b6490206SBarry Smith   int         i, fd, *col_lens, ierr, bs = a->bs,count,*jj,j,k,l;
78b6490206SBarry Smith   Scalar      *aa;
792593348eSBarry Smith 
802593348eSBarry Smith   ierr = ViewerFileGetDescriptor_Private(viewer,&fd); CHKERRQ(ierr);
812593348eSBarry Smith   col_lens = (int *) PetscMalloc((4+a->m)*sizeof(int));CHKPTRQ(col_lens);
822593348eSBarry Smith   col_lens[0] = MAT_COOKIE;
832593348eSBarry Smith   col_lens[1] = a->m;
842593348eSBarry Smith   col_lens[2] = a->n;
85b6490206SBarry Smith   col_lens[3] = a->nz*bs*bs;
862593348eSBarry Smith 
872593348eSBarry Smith   /* store lengths of each row and write (including header) to file */
88b6490206SBarry Smith   count = 0;
89b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
90b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
91b6490206SBarry Smith       col_lens[4+count++] = bs*(a->i[i+1] - a->i[i]);
92b6490206SBarry Smith     }
932593348eSBarry Smith   }
942593348eSBarry Smith   ierr = SYWrite(fd,col_lens,4+a->m,SYINT,1); CHKERRQ(ierr);
952593348eSBarry Smith   PetscFree(col_lens);
962593348eSBarry Smith 
972593348eSBarry Smith   /* store column indices (zero start index) */
98b6490206SBarry Smith   jj = (int *) PetscMalloc( a->nz*bs*bs*sizeof(int) ); CHKPTRQ(jj);
99b6490206SBarry Smith   count = 0;
100b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
101b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
102b6490206SBarry Smith       for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
103b6490206SBarry Smith         for ( l=0; l<bs; l++ ) {
104b6490206SBarry Smith           jj[count++] = bs*a->j[k] + l;
1052593348eSBarry Smith         }
1062593348eSBarry Smith       }
107b6490206SBarry Smith     }
108b6490206SBarry Smith   }
109b6490206SBarry Smith   ierr = SYWrite(fd,jj,bs*bs*a->nz,SYINT,0); CHKERRQ(ierr);
110b6490206SBarry Smith   PetscFree(jj);
1112593348eSBarry Smith 
1122593348eSBarry Smith   /* store nonzero values */
113b6490206SBarry Smith   aa = (Scalar *) PetscMalloc(a->nz*bs*bs*sizeof(Scalar)); CHKPTRQ(aa);
114b6490206SBarry Smith   count = 0;
115b6490206SBarry Smith   for ( i=0; i<a->mbs; i++ ) {
116b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
117b6490206SBarry Smith       for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
118b6490206SBarry Smith         for ( l=0; l<bs; l++ ) {
119b6490206SBarry Smith           aa[count++] = a->a[bs*bs*k + l*bs + j];
120b6490206SBarry Smith         }
121b6490206SBarry Smith       }
122b6490206SBarry Smith     }
123b6490206SBarry Smith   }
124b6490206SBarry Smith   ierr = SYWrite(fd,aa,bs*bs*a->nz,SYSCALAR,0); CHKERRQ(ierr);
125b6490206SBarry Smith   PetscFree(aa);
1262593348eSBarry Smith   return 0;
1272593348eSBarry Smith }
1282593348eSBarry Smith 
129b6490206SBarry Smith static int MatView_SeqBAIJ_ASCII(Mat A,Viewer viewer)
1302593348eSBarry Smith {
131b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
132de6a44a3SBarry Smith   int         ierr, i,j,format,bs = a->bs,k,l;
1332593348eSBarry Smith   FILE        *fd;
1342593348eSBarry Smith   char        *outputname;
1352593348eSBarry Smith 
1362593348eSBarry Smith   ierr = ViewerFileGetPointer(viewer,&fd); CHKERRQ(ierr);
1372593348eSBarry Smith   ierr = ViewerFileGetOutputname_Private(viewer,&outputname);CHKERRQ(ierr);
1382593348eSBarry Smith   ierr = ViewerFileGetFormat_Private(viewer,&format);
1392593348eSBarry Smith   if (format == FILE_FORMAT_INFO) {
1402593348eSBarry Smith     /* no need to print additional information */ ;
1412593348eSBarry Smith   }
1422593348eSBarry Smith   else if (format == FILE_FORMAT_MATLAB) {
143b6490206SBarry Smith     SETERRQ(1,"MatView_SeqBAIJ_ASCII:Matlab format not supported");
1442593348eSBarry Smith   }
1452593348eSBarry Smith   else {
146b6490206SBarry Smith     for ( i=0; i<a->mbs; i++ ) {
147b6490206SBarry Smith       for ( j=0; j<bs; j++ ) {
148b6490206SBarry Smith         fprintf(fd,"row %d:",i*bs+j);
149b6490206SBarry Smith         for ( k=a->i[i]; k<a->i[i+1]; k++ ) {
150b6490206SBarry Smith           for ( l=0; l<bs; l++ ) {
15188685aaeSLois Curfman McInnes #if defined(PETSC_COMPLEX)
15288685aaeSLois Curfman McInnes           if (imag(a->a[bs*bs*k + l*bs + j]) != 0.0) {
15388685aaeSLois Curfman McInnes             fprintf(fd," %d %g + %g i",bs*a->j[k]+l,
15488685aaeSLois Curfman McInnes               real(a->a[bs*bs*k + l*bs + j]),imag(a->a[bs*bs*k + l*bs + j]));
15588685aaeSLois Curfman McInnes           }
15688685aaeSLois Curfman McInnes           else {
15788685aaeSLois Curfman McInnes             fprintf(fd," %d %g",bs*a->j[k]+l,real(a->a[bs*bs*k + l*bs + j]));
15888685aaeSLois Curfman McInnes           }
15988685aaeSLois Curfman McInnes #else
160de6a44a3SBarry Smith             fprintf(fd," %d %g",bs*a->j[k]+l,a->a[bs*bs*k + l*bs + j]);
16188685aaeSLois Curfman McInnes #endif
1622593348eSBarry Smith           }
1632593348eSBarry Smith         }
1642593348eSBarry Smith         fprintf(fd,"\n");
1652593348eSBarry Smith       }
1662593348eSBarry Smith     }
167b6490206SBarry Smith   }
1682593348eSBarry Smith   fflush(fd);
1692593348eSBarry Smith   return 0;
1702593348eSBarry Smith }
1712593348eSBarry Smith 
172b6490206SBarry Smith static int MatView_SeqBAIJ(PetscObject obj,Viewer viewer)
1732593348eSBarry Smith {
1742593348eSBarry Smith   Mat         A = (Mat) obj;
1752593348eSBarry Smith   PetscObject vobj = (PetscObject) viewer;
1762593348eSBarry Smith 
1772593348eSBarry Smith   if (!viewer) {
1782593348eSBarry Smith     viewer = STDOUT_VIEWER_SELF; vobj = (PetscObject) viewer;
1792593348eSBarry Smith   }
1802593348eSBarry Smith   if (vobj->cookie == VIEWER_COOKIE) {
1812593348eSBarry Smith     if (vobj->type == MATLAB_VIEWER) {
182b6490206SBarry Smith       SETERRQ(1,"MatView_SeqBAIJ:Matlab viewer not supported");
1832593348eSBarry Smith     }
1842593348eSBarry Smith     else if (vobj->type == ASCII_FILE_VIEWER||vobj->type == ASCII_FILES_VIEWER){
185b6490206SBarry Smith       return MatView_SeqBAIJ_ASCII(A,viewer);
1862593348eSBarry Smith     }
1872593348eSBarry Smith     else if (vobj->type == BINARY_FILE_VIEWER) {
188b6490206SBarry Smith       return MatView_SeqBAIJ_Binary(A,viewer);
1892593348eSBarry Smith     }
1902593348eSBarry Smith   }
1912593348eSBarry Smith   else if (vobj->cookie == DRAW_COOKIE) {
1922593348eSBarry Smith     if (vobj->type == NULLWINDOW) return 0;
193b6490206SBarry Smith     SETERRQ(1,"MatView_SeqBAIJ:Draw viewer not supported");
1942593348eSBarry Smith   }
1952593348eSBarry Smith   return 0;
1962593348eSBarry Smith }
197b6490206SBarry Smith 
198b6490206SBarry Smith 
199b6490206SBarry Smith static int MatZeroEntries_SeqBAIJ(Mat A)
2002593348eSBarry Smith {
201b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
202de6a44a3SBarry Smith   PetscMemzero(a->a,a->bs*a->bs*a->i[a->mbs]*sizeof(Scalar));
2032593348eSBarry Smith   return 0;
2042593348eSBarry Smith }
2052593348eSBarry Smith 
206b6490206SBarry Smith int MatDestroy_SeqBAIJ(PetscObject obj)
2072593348eSBarry Smith {
2082593348eSBarry Smith   Mat        A  = (Mat) obj;
209b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
2102593348eSBarry Smith 
2112593348eSBarry Smith #if defined(PETSC_LOG)
2122593348eSBarry Smith   PLogObjectState(obj,"Rows=%d, Cols=%d, NZ=%d",a->m,a->n,a->nz);
2132593348eSBarry Smith #endif
2142593348eSBarry Smith   PetscFree(a->a);
2152593348eSBarry Smith   if (!a->singlemalloc) { PetscFree(a->i); PetscFree(a->j);}
2162593348eSBarry Smith   if (a->diag) PetscFree(a->diag);
2172593348eSBarry Smith   if (a->ilen) PetscFree(a->ilen);
2182593348eSBarry Smith   if (a->imax) PetscFree(a->imax);
2192593348eSBarry Smith   if (a->solve_work) PetscFree(a->solve_work);
220de6a44a3SBarry Smith   if (a->mult_work) PetscFree(a->mult_work);
2212593348eSBarry Smith   PetscFree(a);
2222593348eSBarry Smith   PLogObjectDestroy(A);
2232593348eSBarry Smith   PetscHeaderDestroy(A);
2242593348eSBarry Smith   return 0;
2252593348eSBarry Smith }
2262593348eSBarry Smith 
227b6490206SBarry Smith static int MatSetOption_SeqBAIJ(Mat A,MatOption op)
2282593348eSBarry Smith {
229b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
2302593348eSBarry Smith   if      (op == ROW_ORIENTED)              a->roworiented = 1;
2312593348eSBarry Smith   else if (op == COLUMN_ORIENTED)           a->roworiented = 0;
2322593348eSBarry Smith   else if (op == COLUMNS_SORTED)            a->sorted      = 1;
2332593348eSBarry Smith   else if (op == NO_NEW_NONZERO_LOCATIONS)  a->nonew       = 1;
2342593348eSBarry Smith   else if (op == YES_NEW_NONZERO_LOCATIONS) a->nonew       = 0;
2352593348eSBarry Smith   else if (op == ROWS_SORTED ||
2362593348eSBarry Smith            op == SYMMETRIC_MATRIX ||
2372593348eSBarry Smith            op == STRUCTURALLY_SYMMETRIC_MATRIX ||
2382593348eSBarry Smith            op == YES_NEW_DIAGONALS)
239b6490206SBarry Smith     PLogInfo((PetscObject)A,"Info:MatSetOption_SeqBAIJ:Option ignored\n");
2402593348eSBarry Smith   else if (op == NO_NEW_DIAGONALS)
241b6490206SBarry Smith     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqBAIJ:NO_NEW_DIAGONALS");}
2422593348eSBarry Smith   else
243b6490206SBarry Smith     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_SeqBAIJ:unknown option");}
2442593348eSBarry Smith   return 0;
2452593348eSBarry Smith }
2462593348eSBarry Smith 
2472593348eSBarry Smith 
2482593348eSBarry Smith /* -------------------------------------------------------*/
2492593348eSBarry Smith /* Should check that shapes of vectors and matrices match */
2502593348eSBarry Smith /* -------------------------------------------------------*/
251b6490206SBarry Smith #include "pinclude/plapack.h"
252b6490206SBarry Smith 
253b6490206SBarry Smith static int MatMult_SeqBAIJ(Mat A,Vec xx,Vec yy)
2542593348eSBarry Smith {
255b6490206SBarry Smith   Mat_SeqBAIJ     *a = (Mat_SeqBAIJ *) A->data;
256b6490206SBarry Smith   Scalar          *xg,*yg;
257b6490206SBarry Smith   register Scalar *x, *y, *v, sum,*xb, sum1,sum2,sum3,sum4,sum5;
258b6490206SBarry Smith   register Scalar x1,x2,x3,x4,x5;
259b6490206SBarry Smith   int             mbs = a->mbs, m = a->m, i, *idx,*ii;
260b6490206SBarry Smith   int             bs = a->bs,j,n,bs2 = bs*bs;
2612593348eSBarry Smith 
262b6490206SBarry Smith   VecGetArray(xx,&xg); x = xg;  VecGetArray(yy,&yg); y = yg;
263b6490206SBarry Smith   PetscMemzero(y,m*sizeof(Scalar));
264b6490206SBarry Smith   x     = x;
2652593348eSBarry Smith   idx   = a->j;
2662593348eSBarry Smith   v     = a->a;
2672593348eSBarry Smith   ii    = a->i;
268b6490206SBarry Smith 
269b6490206SBarry Smith   switch (bs) {
270b6490206SBarry Smith     case 1:
2712593348eSBarry Smith      for ( i=0; i<m; i++ ) {
2722593348eSBarry Smith        n    = ii[1] - ii[0]; ii++;
2732593348eSBarry Smith        sum  = 0.0;
2742593348eSBarry Smith        while (n--) sum += *v++ * x[*idx++];
2752593348eSBarry Smith        y[i] = sum;
2762593348eSBarry Smith       }
2772593348eSBarry Smith       break;
278b6490206SBarry Smith     case 2:
279b6490206SBarry Smith       for ( i=0; i<mbs; i++ ) {
280de6a44a3SBarry Smith         n  = ii[1] - ii[0]; ii++;
281b6490206SBarry Smith         sum1 = 0.0; sum2 = 0.0;
282b6490206SBarry Smith         for ( j=0; j<n; j++ ) {
283b6490206SBarry Smith           xb = x + 2*(*idx++); x1 = xb[0]; x2 = xb[1];
284b6490206SBarry Smith           sum1 += v[0]*x1 + v[2]*x2;
285b6490206SBarry Smith           sum2 += v[1]*x1 + v[3]*x2;
286b6490206SBarry Smith           v += 4;
287b6490206SBarry Smith         }
288b6490206SBarry Smith         y[0] += sum1; y[1] += sum2;
289b6490206SBarry Smith         y += 2;
290b6490206SBarry Smith       }
291b6490206SBarry Smith       break;
292b6490206SBarry Smith     case 3:
293b6490206SBarry Smith       for ( i=0; i<mbs; i++ ) {
294de6a44a3SBarry Smith         n  = ii[1] - ii[0]; ii++;
295b6490206SBarry Smith         sum1 = 0.0; sum2 = 0.0; sum3 = 0.0;
296b6490206SBarry Smith         for ( j=0; j<n; j++ ) {
297b6490206SBarry Smith           xb = x + 3*(*idx++); x1 = xb[0]; x2 = xb[1]; x3 = xb[2];
298b6490206SBarry Smith           sum1 += v[0]*x1 + v[3]*x2 + v[6]*x3;
299b6490206SBarry Smith           sum2 += v[1]*x1 + v[4]*x2 + v[7]*x3;
300b6490206SBarry Smith           sum3 += v[2]*x1 + v[5]*x2 + v[8]*x3;
301b6490206SBarry Smith           v += 9;
302b6490206SBarry Smith         }
303b6490206SBarry Smith         y[0] += sum1; y[1] += sum2; y[2] += sum3;
304b6490206SBarry Smith         y += 3;
305b6490206SBarry Smith       }
306b6490206SBarry Smith       break;
307b6490206SBarry Smith     case 4:
308b6490206SBarry Smith       for ( i=0; i<mbs; i++ ) {
309de6a44a3SBarry Smith         n  = ii[1] - ii[0]; ii++;
310b6490206SBarry Smith         sum1 = 0.0; sum2 = 0.0; sum3 = 0.0; sum4 = 0.0;
311b6490206SBarry Smith         for ( j=0; j<n; j++ ) {
312b6490206SBarry Smith           xb = x + 4*(*idx++);
313b6490206SBarry Smith           x1 = xb[0]; x2 = xb[1]; x3 = xb[2]; x4 = xb[3];
314b6490206SBarry Smith           sum1 += v[0]*x1 + v[4]*x2 + v[8]*x3   + v[12]*x4;
315b6490206SBarry Smith           sum2 += v[1]*x1 + v[5]*x2 + v[9]*x3   + v[13]*x4;
316b6490206SBarry Smith           sum3 += v[2]*x1 + v[6]*x2 + v[10]*x3  + v[14]*x4;
317b6490206SBarry Smith           sum4 += v[3]*x1 + v[7]*x2 + v[11]*x3  + v[15]*x4;
318b6490206SBarry Smith           v += 16;
319b6490206SBarry Smith         }
320b6490206SBarry Smith         y[0] += sum1; y[1] += sum2; y[2] += sum3; y[3] += sum4;
321b6490206SBarry Smith         y += 4;
322b6490206SBarry Smith       }
323b6490206SBarry Smith       break;
324b6490206SBarry Smith     case 5:
325b6490206SBarry Smith       for ( i=0; i<mbs; i++ ) {
326de6a44a3SBarry Smith         n  = ii[1] - ii[0]; ii++;
327b6490206SBarry Smith         sum1 = 0.0; sum2 = 0.0; sum3 = 0.0; sum4 = 0.0; sum5 = 0.0;
328b6490206SBarry Smith         for ( j=0; j<n; j++ ) {
329b6490206SBarry Smith           xb = x + 5*(*idx++);
330b6490206SBarry Smith           x1 = xb[0]; x2 = xb[1]; x3 = xb[2]; x4 = xb[3]; x5 = xb[4];
331b6490206SBarry Smith           sum1 += v[0]*x1 + v[5]*x2 + v[10]*x3  + v[15]*x4 + v[20]*x5;
332b6490206SBarry Smith           sum2 += v[1]*x1 + v[6]*x2 + v[11]*x3  + v[16]*x4 + v[21]*x5;
333b6490206SBarry Smith           sum3 += v[2]*x1 + v[7]*x2 + v[12]*x3  + v[17]*x4 + v[22]*x5;
334b6490206SBarry Smith           sum4 += v[3]*x1 + v[8]*x2 + v[13]*x3  + v[18]*x4 + v[23]*x5;
335b6490206SBarry Smith           sum5 += v[4]*x1 + v[9]*x2 + v[14]*x3  + v[19]*x4 + v[24]*x5;
336b6490206SBarry Smith           v += 25;
337b6490206SBarry Smith         }
338b6490206SBarry Smith         y[0] += sum1; y[1] += sum2; y[2] += sum3; y[3] += sum4; y[4] += sum5;
339b6490206SBarry Smith         y += 5;
340b6490206SBarry Smith       }
341b6490206SBarry Smith       break;
342b6490206SBarry Smith       /* block sizes larger then 5 by 5 are handled by BLAS */
343b6490206SBarry Smith     default: {
344de6a44a3SBarry Smith       int  _One = 1,ncols,k; Scalar _DOne = 1.0, *work,*workt;
345de6a44a3SBarry Smith       if (!a->mult_work) {
346de6a44a3SBarry Smith         a->mult_work = (Scalar *) PetscMalloc(a->m*sizeof(Scalar));
347de6a44a3SBarry Smith         CHKPTRQ(a->mult_work);
348de6a44a3SBarry Smith       }
349de6a44a3SBarry Smith       work = a->mult_work;
350b6490206SBarry Smith       for ( i=0; i<mbs; i++ ) {
351de6a44a3SBarry Smith         n     = ii[1] - ii[0]; ii++;
352de6a44a3SBarry Smith         ncols = n*bs;
353de6a44a3SBarry Smith         workt = work;
354b6490206SBarry Smith         for ( j=0; j<n; j++ ) {
355b6490206SBarry Smith           xb = x + bs*(*idx++);
356de6a44a3SBarry Smith           for ( k=0; k<bs; k++ ) workt[k] = xb[k];
357de6a44a3SBarry Smith           workt += bs;
358b6490206SBarry Smith         }
359de6a44a3SBarry Smith         LAgemv_("N",&bs,&ncols,&_DOne,v,&bs,work,&_One,&_DOne,y,&_One);
360de6a44a3SBarry Smith         v += n*bs2;
361b6490206SBarry Smith         y += bs;
3622593348eSBarry Smith       }
3632593348eSBarry Smith     }
3642593348eSBarry Smith   }
365b6490206SBarry Smith   PLogFlops(2*bs2*a->nz - m);
3662593348eSBarry Smith   return 0;
3672593348eSBarry Smith }
3682593348eSBarry Smith 
369de6a44a3SBarry Smith static int MatGetInfo_SeqBAIJ(Mat A,MatInfoType flag,int *nz,int *nza,int *mem)
3702593348eSBarry Smith {
371b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
37235aab85fSBarry Smith   *nz  = a->bs*a->bs*a->nz;
373de6a44a3SBarry Smith   *nza = a->maxnz;
3742593348eSBarry Smith   *mem = (int)A->mem;
3752593348eSBarry Smith   return 0;
3762593348eSBarry Smith }
3772593348eSBarry Smith 
378b6490206SBarry Smith extern int MatLUFactorSymbolic_SeqBAIJ(Mat,IS,IS,double,Mat*);
379b6490206SBarry Smith extern int MatLUFactor_SeqBAIJ(Mat,IS,IS,double);
380b6490206SBarry Smith extern int MatSolve_SeqBAIJ(Mat,Vec,Vec);
3817fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_N(Mat,Mat*);
3827fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_1(Mat,Mat*);
3837fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_2(Mat,Mat*);
3847fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_3(Mat,Mat*);
3857fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_4(Mat,Mat*);
3867fc0212eSBarry Smith extern int MatLUFactorNumeric_SeqBAIJ_5(Mat,Mat*);
3872593348eSBarry Smith 
388b6490206SBarry Smith static int MatGetSize_SeqBAIJ(Mat A,int *m,int *n)
3892593348eSBarry Smith {
390b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
3912593348eSBarry Smith   *m = a->m; *n = a->n;
3922593348eSBarry Smith   return 0;
3932593348eSBarry Smith }
3942593348eSBarry Smith 
395b6490206SBarry Smith static int MatGetOwnershipRange_SeqBAIJ(Mat A,int *m,int *n)
3962593348eSBarry Smith {
397b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
3982593348eSBarry Smith   *m = 0; *n = a->m;
3992593348eSBarry Smith   return 0;
4002593348eSBarry Smith }
401b6490206SBarry Smith 
402b6490206SBarry Smith static int MatNorm_SeqBAIJ(Mat A,NormType type,double *norm)
4032593348eSBarry Smith {
404b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) A->data;
4052593348eSBarry Smith   Scalar      *v = a->a;
4062593348eSBarry Smith   double      sum = 0.0;
407b6490206SBarry Smith   int         i;
4082593348eSBarry Smith 
4092593348eSBarry Smith   if (type == NORM_FROBENIUS) {
4102593348eSBarry Smith     for (i=0; i<a->nz; i++ ) {
4112593348eSBarry Smith #if defined(PETSC_COMPLEX)
4122593348eSBarry Smith       sum += real(conj(*v)*(*v)); v++;
4132593348eSBarry Smith #else
4142593348eSBarry Smith       sum += (*v)*(*v); v++;
4152593348eSBarry Smith #endif
4162593348eSBarry Smith     }
4172593348eSBarry Smith     *norm = sqrt(sum);
4182593348eSBarry Smith   }
4192593348eSBarry Smith   else {
420b6490206SBarry Smith     SETERRQ(1,"MatNorm_SeqBAIJ:No support for this norm yet");
4212593348eSBarry Smith   }
4222593348eSBarry Smith   return 0;
4232593348eSBarry Smith }
4242593348eSBarry Smith 
4252593348eSBarry Smith /*
4262593348eSBarry Smith      note: This can only work for identity for row and col. It would
4272593348eSBarry Smith    be good to check this and otherwise generate an error.
4282593348eSBarry Smith */
429b6490206SBarry Smith static int MatILUFactor_SeqBAIJ(Mat inA,IS row,IS col,double efill,int fill)
4302593348eSBarry Smith {
431b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) inA->data;
4322593348eSBarry Smith   Mat         outA;
433de6a44a3SBarry Smith   int         ierr;
4342593348eSBarry Smith 
435b6490206SBarry Smith   if (fill != 0) SETERRQ(1,"MatILUFactor_SeqBAIJ:Only fill=0 supported");
4362593348eSBarry Smith 
4372593348eSBarry Smith   outA          = inA;
4382593348eSBarry Smith   inA->factor   = FACTOR_LU;
4392593348eSBarry Smith   a->row        = row;
4402593348eSBarry Smith   a->col        = col;
4412593348eSBarry Smith 
442de6a44a3SBarry Smith   a->solve_work = (Scalar *) PetscMalloc((a->m+a->bs)*sizeof(Scalar));CHKPTRQ(a->solve_work);
4432593348eSBarry Smith 
4442593348eSBarry Smith   if (!a->diag) {
445b6490206SBarry Smith     ierr = MatMarkDiag_SeqBAIJ(inA); CHKERRQ(ierr);
4462593348eSBarry Smith   }
4477fc0212eSBarry Smith   ierr = MatLUFactorNumeric(inA,&outA); CHKERRQ(ierr);
4482593348eSBarry Smith   return 0;
4492593348eSBarry Smith }
4502593348eSBarry Smith 
451b6490206SBarry Smith static int MatScale_SeqBAIJ(Scalar *alpha,Mat inA)
4522593348eSBarry Smith {
453b6490206SBarry Smith   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) inA->data;
454b6490206SBarry Smith   int         one = 1, totalnz = a->bs*a->bs*a->nz;
455b6490206SBarry Smith   BLscal_( &totalnz, alpha, a->a, &one );
456b6490206SBarry Smith   PLogFlops(totalnz);
4572593348eSBarry Smith   return 0;
4582593348eSBarry Smith }
4592593348eSBarry Smith 
460b6490206SBarry Smith int MatPrintHelp_SeqBAIJ(Mat A)
4612593348eSBarry Smith {
4622593348eSBarry Smith   static int called = 0;
4632593348eSBarry Smith 
4642593348eSBarry Smith   if (called) return 0; else called = 1;
4652593348eSBarry Smith   return 0;
4662593348eSBarry Smith }
4672593348eSBarry Smith /* -------------------------------------------------------------------*/
468b6490206SBarry Smith static struct _MatOps MatOps = {0,
469b6490206SBarry Smith        0,0,
470b6490206SBarry Smith        MatMult_SeqBAIJ,0,
471b6490206SBarry Smith        0,0,
472de6a44a3SBarry Smith        MatSolve_SeqBAIJ,0,
473b6490206SBarry Smith        0,0,
474de6a44a3SBarry Smith        MatLUFactor_SeqBAIJ,0,
475b6490206SBarry Smith        0,
476b6490206SBarry Smith        0,
477b6490206SBarry Smith        MatGetInfo_SeqBAIJ,0,
478b6490206SBarry Smith        0,0,MatNorm_SeqBAIJ,
479b6490206SBarry Smith        0,0,
480b6490206SBarry Smith        0,
481b6490206SBarry Smith        MatSetOption_SeqBAIJ,MatZeroEntries_SeqBAIJ,0,
482b6490206SBarry Smith        MatGetReordering_SeqBAIJ,
4837fc0212eSBarry Smith        MatLUFactorSymbolic_SeqBAIJ,MatLUFactorNumeric_SeqBAIJ_N,0,0,
484b6490206SBarry Smith        MatGetSize_SeqBAIJ,MatGetSize_SeqBAIJ,MatGetOwnershipRange_SeqBAIJ,
485de6a44a3SBarry Smith        MatILUFactorSymbolic_SeqBAIJ,0,
486b6490206SBarry Smith        0,0,/*MatConvert_SeqBAIJ*/ 0,
487b6490206SBarry Smith        0,0,
488b6490206SBarry Smith        MatConvertSameType_SeqBAIJ,0,0,
489b6490206SBarry Smith        MatILUFactor_SeqBAIJ,0,0,
490b6490206SBarry Smith        0,0,
491b6490206SBarry Smith        0,0,
492b6490206SBarry Smith        MatPrintHelp_SeqBAIJ,MatScale_SeqBAIJ,
493b6490206SBarry Smith        0};
4942593348eSBarry Smith 
4952593348eSBarry Smith /*@C
496b6490206SBarry Smith    MatCreateSeqBAIJ - Creates a sparse matrix in AIJ (compressed row) format
4972593348eSBarry Smith    (the default parallel PETSc format).  For good matrix assembly performance
4982593348eSBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
4992593348eSBarry Smith    (or nzz).  By setting these parameters accurately, performance can be
5002593348eSBarry Smith    increased by more than a factor of 50.
5012593348eSBarry Smith 
5022593348eSBarry Smith    Input Parameters:
5032593348eSBarry Smith .  comm - MPI communicator, set to MPI_COMM_SELF
504b6490206SBarry Smith .  bs - size of block
5052593348eSBarry Smith .  m - number of rows
5062593348eSBarry Smith .  n - number of columns
507b6490206SBarry Smith .  nz - number of block nonzeros per block row (same for all rows)
508b6490206SBarry Smith .  nzz - number of block nonzeros per block row or PETSC_NULL
509b6490206SBarry Smith          (possibly different for each row)
5102593348eSBarry Smith 
5112593348eSBarry Smith    Output Parameter:
5122593348eSBarry Smith .  A - the matrix
5132593348eSBarry Smith 
5142593348eSBarry Smith    Notes:
515b6490206SBarry Smith    The BAIJ format, is fully compatible with standard Fortran 77
5162593348eSBarry Smith    storage.  That is, the stored row and column indices can begin at
5172593348eSBarry Smith    either one (as in Fortran) or zero.  See the users manual for details.
5182593348eSBarry Smith 
5192593348eSBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
5202593348eSBarry Smith    Set nz=PETSC_DEFAULT and nnz=PETSC_NULL for PETSc to control dynamic memory
5212593348eSBarry Smith    allocation.  For additional details, see the users manual chapter on
5222593348eSBarry Smith    matrices and the file $(PETSC_DIR)/Performance.
5232593348eSBarry Smith 
5242593348eSBarry Smith .seealso: MatCreate(), MatCreateMPIAIJ(), MatSetValues()
5252593348eSBarry Smith @*/
526b6490206SBarry Smith int MatCreateSeqBAIJ(MPI_Comm comm,int bs,int m,int n,int nz,int *nnz, Mat *A)
5272593348eSBarry Smith {
5282593348eSBarry Smith   Mat         B;
529b6490206SBarry Smith   Mat_SeqBAIJ *b;
530b6490206SBarry Smith   int         i,len,ierr, flg,mbs = m/bs;
531b6490206SBarry Smith 
532b6490206SBarry Smith   if (mbs*bs != m)
533b6490206SBarry Smith     SETERRQ(1,"MatCreateSeqBAIJ:Number rows must be divisible by blocksize");
5342593348eSBarry Smith 
5352593348eSBarry Smith   *A      = 0;
536b6490206SBarry Smith   PetscHeaderCreate(B,_Mat,MAT_COOKIE,MATSEQBAIJ,comm);
5372593348eSBarry Smith   PLogObjectCreate(B);
538b6490206SBarry Smith   B->data             = (void *) (b = PetscNew(Mat_SeqBAIJ)); CHKPTRQ(b);
5392593348eSBarry Smith   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
5407fc0212eSBarry Smith   switch (bs) {
5417fc0212eSBarry Smith     case 1:
5427fc0212eSBarry Smith       B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_1;
5437fc0212eSBarry Smith       break;
5444eeb42bcSBarry Smith     case 2:
5454eeb42bcSBarry Smith       B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_2;
546*6d84be18SBarry Smith       break;
547f327dd97SBarry Smith     case 3:
548f327dd97SBarry Smith       B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_3;
5494eeb42bcSBarry Smith       break;
550*6d84be18SBarry Smith     case 4:
551*6d84be18SBarry Smith       B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_4;
552*6d84be18SBarry Smith       break;
553*6d84be18SBarry Smith     case 5:
554*6d84be18SBarry Smith       B->ops.lufactornumeric = MatLUFactorNumeric_SeqBAIJ_5;
555*6d84be18SBarry Smith       break;
5567fc0212eSBarry Smith   }
557b6490206SBarry Smith   B->destroy          = MatDestroy_SeqBAIJ;
558b6490206SBarry Smith   B->view             = MatView_SeqBAIJ;
5592593348eSBarry Smith   B->factor           = 0;
5602593348eSBarry Smith   B->lupivotthreshold = 1.0;
5612593348eSBarry Smith   b->row              = 0;
5622593348eSBarry Smith   b->col              = 0;
5632593348eSBarry Smith   b->reallocs         = 0;
5642593348eSBarry Smith 
5652593348eSBarry Smith   b->m       = m;
566b6490206SBarry Smith   b->mbs     = mbs;
5672593348eSBarry Smith   b->n       = n;
568b6490206SBarry Smith   b->imax    = (int *) PetscMalloc( (mbs+1)*sizeof(int) ); CHKPTRQ(b->imax);
5692593348eSBarry Smith   if (nnz == PETSC_NULL) {
570de6a44a3SBarry Smith     if (nz == PETSC_DEFAULT) nz = 5;
5712593348eSBarry Smith     else if (nz <= 0)        nz = 1;
572b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) b->imax[i] = nz;
573b6490206SBarry Smith     nz = nz*mbs;
5742593348eSBarry Smith   }
5752593348eSBarry Smith   else {
5762593348eSBarry Smith     nz = 0;
577b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) {b->imax[i] = nnz[i]; nz += nnz[i];}
5782593348eSBarry Smith   }
5792593348eSBarry Smith 
5802593348eSBarry Smith   /* allocate the matrix space */
581b6490206SBarry Smith   len   = nz*sizeof(int) + nz*bs*bs*sizeof(Scalar) + (b->m+1)*sizeof(int);
5822593348eSBarry Smith   b->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(b->a);
583b6490206SBarry Smith   PetscMemzero(b->a,nz*bs*bs*sizeof(Scalar));
584b6490206SBarry Smith   b->j  = (int *) (b->a + nz*bs*bs);
5852593348eSBarry Smith   PetscMemzero(b->j,nz*sizeof(int));
5862593348eSBarry Smith   b->i  = b->j + nz;
5872593348eSBarry Smith   b->singlemalloc = 1;
5882593348eSBarry Smith 
589de6a44a3SBarry Smith   b->i[0] = 0;
590b6490206SBarry Smith   for (i=1; i<mbs+1; i++) {
5912593348eSBarry Smith     b->i[i] = b->i[i-1] + b->imax[i-1];
5922593348eSBarry Smith   }
5932593348eSBarry Smith 
594b6490206SBarry Smith   /* b->ilen will count nonzeros in each block row so far. */
595b6490206SBarry Smith   b->ilen = (int *) PetscMalloc((mbs+1)*sizeof(int));
596b6490206SBarry Smith   PLogObjectMemory(B,len+2*(mbs+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqBAIJ));
597b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) { b->ilen[i] = 0;}
5982593348eSBarry Smith 
599b6490206SBarry Smith   b->bs               = bs;
600b6490206SBarry Smith   b->mbs              = mbs;
6012593348eSBarry Smith   b->nz               = 0;
6022593348eSBarry Smith   b->maxnz            = nz;
6032593348eSBarry Smith   b->sorted           = 0;
6042593348eSBarry Smith   b->roworiented      = 1;
6052593348eSBarry Smith   b->nonew            = 0;
6062593348eSBarry Smith   b->diag             = 0;
6072593348eSBarry Smith   b->solve_work       = 0;
608de6a44a3SBarry Smith   b->mult_work        = 0;
6092593348eSBarry Smith   b->spptr            = 0;
6102593348eSBarry Smith 
6112593348eSBarry Smith   *A = B;
6122593348eSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-help", &flg); CHKERRQ(ierr);
6132593348eSBarry Smith   if (flg) {ierr = MatPrintHelp(B); CHKERRQ(ierr); }
6142593348eSBarry Smith   return 0;
6152593348eSBarry Smith }
6162593348eSBarry Smith 
617b6490206SBarry Smith int MatConvertSameType_SeqBAIJ(Mat A,Mat *B,int cpvalues)
6182593348eSBarry Smith {
6192593348eSBarry Smith   Mat         C;
620b6490206SBarry Smith   Mat_SeqBAIJ *c,*a = (Mat_SeqBAIJ *) A->data;
621de6a44a3SBarry Smith   int         i,len, mbs = a->mbs, bs = a->bs,nz = a->nz;
622de6a44a3SBarry Smith 
623de6a44a3SBarry Smith   if (a->i[mbs] != nz) SETERRQ(1,"MatConvertSameType_SeqBAIJ:Corrupt matrix");
6242593348eSBarry Smith 
6252593348eSBarry Smith   *B = 0;
626b6490206SBarry Smith   PetscHeaderCreate(C,_Mat,MAT_COOKIE,MATSEQBAIJ,A->comm);
6272593348eSBarry Smith   PLogObjectCreate(C);
628b6490206SBarry Smith   C->data       = (void *) (c = PetscNew(Mat_SeqBAIJ)); CHKPTRQ(c);
6292593348eSBarry Smith   PetscMemcpy(&C->ops,&A->ops,sizeof(struct _MatOps));
630b6490206SBarry Smith   C->destroy    = MatDestroy_SeqBAIJ;
631b6490206SBarry Smith   C->view       = MatView_SeqBAIJ;
6322593348eSBarry Smith   C->factor     = A->factor;
6332593348eSBarry Smith   c->row        = 0;
6342593348eSBarry Smith   c->col        = 0;
6352593348eSBarry Smith   C->assembled  = PETSC_TRUE;
6362593348eSBarry Smith 
6372593348eSBarry Smith   c->m          = a->m;
6382593348eSBarry Smith   c->n          = a->n;
639b6490206SBarry Smith   c->bs         = a->bs;
640b6490206SBarry Smith   c->mbs        = a->mbs;
641b6490206SBarry Smith   c->nbs        = a->nbs;
6422593348eSBarry Smith 
643b6490206SBarry Smith   c->imax       = (int *) PetscMalloc((mbs+1)*sizeof(int)); CHKPTRQ(c->imax);
644b6490206SBarry Smith   c->ilen       = (int *) PetscMalloc((mbs+1)*sizeof(int)); CHKPTRQ(c->ilen);
645b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
6462593348eSBarry Smith     c->imax[i] = a->imax[i];
6472593348eSBarry Smith     c->ilen[i] = a->ilen[i];
6482593348eSBarry Smith   }
6492593348eSBarry Smith 
6502593348eSBarry Smith   /* allocate the matrix space */
6512593348eSBarry Smith   c->singlemalloc = 1;
652de6a44a3SBarry Smith   len   = (mbs+1)*sizeof(int) + nz*(bs*bs*sizeof(Scalar) + sizeof(int));
6532593348eSBarry Smith   c->a  = (Scalar *) PetscMalloc( len ); CHKPTRQ(c->a);
654de6a44a3SBarry Smith   c->j  = (int *) (c->a + nz*bs*bs);
655de6a44a3SBarry Smith   c->i  = c->j + nz;
656b6490206SBarry Smith   PetscMemcpy(c->i,a->i,(mbs+1)*sizeof(int));
657b6490206SBarry Smith   if (mbs > 0) {
658de6a44a3SBarry Smith     PetscMemcpy(c->j,a->j,nz*sizeof(int));
6592593348eSBarry Smith     if (cpvalues == COPY_VALUES) {
660de6a44a3SBarry Smith       PetscMemcpy(c->a,a->a,bs*bs*nz*sizeof(Scalar));
6612593348eSBarry Smith     }
6622593348eSBarry Smith   }
6632593348eSBarry Smith 
664b6490206SBarry Smith   PLogObjectMemory(C,len+2*(mbs+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_SeqBAIJ));
6652593348eSBarry Smith   c->sorted      = a->sorted;
6662593348eSBarry Smith   c->roworiented = a->roworiented;
6672593348eSBarry Smith   c->nonew       = a->nonew;
6682593348eSBarry Smith 
6692593348eSBarry Smith   if (a->diag) {
670b6490206SBarry Smith     c->diag = (int *) PetscMalloc( (mbs+1)*sizeof(int) ); CHKPTRQ(c->diag);
671b6490206SBarry Smith     PLogObjectMemory(C,(mbs+1)*sizeof(int));
672b6490206SBarry Smith     for ( i=0; i<mbs; i++ ) {
6732593348eSBarry Smith       c->diag[i] = a->diag[i];
6742593348eSBarry Smith     }
6752593348eSBarry Smith   }
6762593348eSBarry Smith   else c->diag          = 0;
6772593348eSBarry Smith   c->nz                 = a->nz;
6782593348eSBarry Smith   c->maxnz              = a->maxnz;
6792593348eSBarry Smith   c->solve_work         = 0;
6802593348eSBarry Smith   c->spptr              = 0;      /* Dangerous -I'm throwing away a->spptr */
6817fc0212eSBarry Smith   c->mult_work          = 0;
6822593348eSBarry Smith   *B = C;
6832593348eSBarry Smith   return 0;
6842593348eSBarry Smith }
6852593348eSBarry Smith 
686b6490206SBarry Smith int MatLoad_SeqBAIJ(Viewer bview,MatType type,Mat *A)
6872593348eSBarry Smith {
688b6490206SBarry Smith   Mat_SeqBAIJ  *a;
6892593348eSBarry Smith   Mat          B;
690de6a44a3SBarry Smith   int          i,nz,ierr,fd,header[4],size,*rowlengths=0,M,N,bs=1,flg;
691b6490206SBarry Smith   int          *mask,mbs,*jj,j,rowcount,nzcount,k,*browlengths,maskcount;
69235aab85fSBarry Smith   int          kmax,jcount,block,idx,point,nzcountb,extra_rows;
693de6a44a3SBarry Smith   int          *masked, nmask,tmp,ishift,bs2;
694b6490206SBarry Smith   Scalar       *aa;
6952593348eSBarry Smith   PetscObject  vobj = (PetscObject) bview;
6962593348eSBarry Smith   MPI_Comm     comm = vobj->comm;
6972593348eSBarry Smith 
69835aab85fSBarry Smith   ierr = OptionsGetInt(PETSC_NULL,"-mat_block_size",&bs,&flg);CHKERRQ(ierr);
699de6a44a3SBarry Smith   bs2  = bs*bs;
700b6490206SBarry Smith 
7012593348eSBarry Smith   MPI_Comm_size(comm,&size);
702b6490206SBarry Smith   if (size > 1) SETERRQ(1,"MatLoad_SeqBAIJ:view must have one processor");
7032593348eSBarry Smith   ierr = ViewerFileGetDescriptor_Private(bview,&fd); CHKERRQ(ierr);
7042593348eSBarry Smith   ierr = SYRead(fd,header,4,SYINT); CHKERRQ(ierr);
705de6a44a3SBarry Smith   if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_SeqBAIJ:not Mat object");
7062593348eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
7072593348eSBarry Smith 
708b6490206SBarry Smith   if (M != N) SETERRQ(1,"MatLoad_SeqBAIJ:Can only do square matrices");
70935aab85fSBarry Smith 
71035aab85fSBarry Smith   /*
71135aab85fSBarry Smith      This code adds extra rows to make sure the number of rows is
71235aab85fSBarry Smith     divisible by the blocksize
71335aab85fSBarry Smith   */
714b6490206SBarry Smith   mbs        = M/bs;
71535aab85fSBarry Smith   extra_rows = bs - M + bs*(mbs);
71635aab85fSBarry Smith   if (extra_rows == bs) extra_rows = 0;
71735aab85fSBarry Smith   else                  mbs++;
71835aab85fSBarry Smith   if (extra_rows) {
71935aab85fSBarry Smith     PLogInfo(0,"MatLoad_SeqBAIJ:Padding loading matrix to match blocksize");
72035aab85fSBarry Smith   }
721b6490206SBarry Smith 
7222593348eSBarry Smith   /* read in row lengths */
72335aab85fSBarry Smith   rowlengths = (int*) PetscMalloc((M+extra_rows)*sizeof(int));CHKPTRQ(rowlengths);
7242593348eSBarry Smith   ierr = SYRead(fd,rowlengths,M,SYINT); CHKERRQ(ierr);
72535aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) rowlengths[M+i] = 1;
7262593348eSBarry Smith 
727b6490206SBarry Smith   /* read in column indices */
72835aab85fSBarry Smith   jj = (int*) PetscMalloc( (nz+extra_rows)*sizeof(int) ); CHKPTRQ(jj);
729b6490206SBarry Smith   ierr = SYRead(fd,jj,nz,SYINT); CHKERRQ(ierr);
73035aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) jj[nz+i] = M+i;
731b6490206SBarry Smith 
732b6490206SBarry Smith   /* loop over row lengths determining block row lengths */
733b6490206SBarry Smith   browlengths = (int *) PetscMalloc(mbs*sizeof(int));CHKPTRQ(browlengths);
734b6490206SBarry Smith   PetscMemzero(browlengths,mbs*sizeof(int));
73535aab85fSBarry Smith   mask   = (int *) PetscMalloc( 2*mbs*sizeof(int) ); CHKPTRQ(mask);
73635aab85fSBarry Smith   PetscMemzero(mask,mbs*sizeof(int));
73735aab85fSBarry Smith   masked = mask + mbs;
738b6490206SBarry Smith   rowcount = 0; nzcount = 0;
739b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
74035aab85fSBarry Smith     nmask = 0;
741b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
742b6490206SBarry Smith       kmax = rowlengths[rowcount];
743b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
74435aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
74535aab85fSBarry Smith         if (!mask[tmp]) {masked[nmask++] = tmp; mask[tmp] = 1;}
746b6490206SBarry Smith       }
747b6490206SBarry Smith       rowcount++;
748b6490206SBarry Smith     }
74935aab85fSBarry Smith     browlengths[i] += nmask;
75035aab85fSBarry Smith     /* zero out the mask elements we set */
75135aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) mask[masked[j]] = 0;
752b6490206SBarry Smith   }
753b6490206SBarry Smith 
7542593348eSBarry Smith   /* create our matrix */
75535aab85fSBarry Smith   ierr = MatCreateSeqBAIJ(comm,bs,M+extra_rows,N+extra_rows,0,browlengths,A);
75635aab85fSBarry Smith          CHKERRQ(ierr);
7572593348eSBarry Smith   B = *A;
758b6490206SBarry Smith   a = (Mat_SeqBAIJ *) B->data;
7592593348eSBarry Smith 
7602593348eSBarry Smith   /* set matrix "i" values */
761de6a44a3SBarry Smith   a->i[0] = 0;
762b6490206SBarry Smith   for ( i=1; i<= mbs; i++ ) {
763b6490206SBarry Smith     a->i[i]      = a->i[i-1] + browlengths[i-1];
764b6490206SBarry Smith     a->ilen[i-1] = browlengths[i-1];
7652593348eSBarry Smith   }
766b6490206SBarry Smith   a->nz = 0;
767b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) a->nz += browlengths[i];
7682593348eSBarry Smith 
769b6490206SBarry Smith   /* read in nonzero values */
77035aab85fSBarry Smith   aa = (Scalar *) PetscMalloc((nz+extra_rows)*sizeof(Scalar));CHKPTRQ(aa);
771b6490206SBarry Smith   ierr = SYRead(fd,aa,nz,SYSCALAR); CHKERRQ(ierr);
77235aab85fSBarry Smith   for ( i=0; i<extra_rows; i++ ) aa[nz+i] = 1.0;
773b6490206SBarry Smith 
774b6490206SBarry Smith   /* set "a" and "j" values into matrix */
775b6490206SBarry Smith   nzcount = 0; jcount = 0;
776b6490206SBarry Smith   for ( i=0; i<mbs; i++ ) {
777b6490206SBarry Smith     nzcountb = nzcount;
77835aab85fSBarry Smith     nmask    = 0;
779b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
780b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
781b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
78235aab85fSBarry Smith         tmp = jj[nzcount++]/bs;
78335aab85fSBarry Smith 	if (!mask[tmp]) { masked[nmask++] = tmp; mask[tmp] = 1;}
784b6490206SBarry Smith       }
785b6490206SBarry Smith       rowcount++;
786b6490206SBarry Smith     }
787de6a44a3SBarry Smith     /* sort the masked values */
788de6a44a3SBarry Smith     SYIsort(nmask,masked);
789de6a44a3SBarry Smith 
790b6490206SBarry Smith     /* set "j" values into matrix */
791b6490206SBarry Smith     maskcount = 1;
79235aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) {
79335aab85fSBarry Smith       a->j[jcount++]  = masked[j];
794de6a44a3SBarry Smith       mask[masked[j]] = maskcount++;
795b6490206SBarry Smith     }
796b6490206SBarry Smith     /* set "a" values into matrix */
797de6a44a3SBarry Smith     ishift = bs2*a->i[i];
798b6490206SBarry Smith     for ( j=0; j<bs; j++ ) {
799b6490206SBarry Smith       kmax = rowlengths[i*bs+j];
800b6490206SBarry Smith       for ( k=0; k<kmax; k++ ) {
801de6a44a3SBarry Smith         tmp    = jj[nzcountb]/bs ;
802de6a44a3SBarry Smith         block  = mask[tmp] - 1;
803de6a44a3SBarry Smith         point  = jj[nzcountb] - bs*tmp;
804de6a44a3SBarry Smith         idx    = ishift + bs2*block + j + bs*point;
805b6490206SBarry Smith         a->a[idx] = aa[nzcountb++];
806b6490206SBarry Smith       }
807b6490206SBarry Smith     }
80835aab85fSBarry Smith     /* zero out the mask elements we set */
80935aab85fSBarry Smith     for ( j=0; j<nmask; j++ ) mask[masked[j]] = 0;
810b6490206SBarry Smith   }
81135aab85fSBarry Smith   if (jcount != a->nz) SETERRQ(1,"MatLoad_SeqBAIJ:Error bad binary matrix");
812b6490206SBarry Smith 
813b6490206SBarry Smith   PetscFree(rowlengths);
814b6490206SBarry Smith   PetscFree(browlengths);
815b6490206SBarry Smith   PetscFree(aa);
816b6490206SBarry Smith   PetscFree(jj);
817b6490206SBarry Smith   PetscFree(mask);
818b6490206SBarry Smith 
819b6490206SBarry Smith   B->assembled = PETSC_TRUE;
820de6a44a3SBarry Smith 
821de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_info",&flg); CHKERRQ(ierr);
822de6a44a3SBarry Smith   if (flg) {
823de6a44a3SBarry Smith     Viewer viewer;
824de6a44a3SBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&viewer);CHKERRQ(ierr);
825de6a44a3SBarry Smith     ierr = ViewerFileSetFormat(viewer,FILE_FORMAT_INFO,0);CHKERRQ(ierr);
826de6a44a3SBarry Smith     ierr = MatView(B,viewer); CHKERRQ(ierr);
827de6a44a3SBarry Smith     ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
828de6a44a3SBarry Smith   }
829de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_info_detailed",&flg);CHKERRQ(ierr);
830de6a44a3SBarry Smith   if (flg) {
831de6a44a3SBarry Smith     Viewer viewer;
832de6a44a3SBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&viewer);CHKERRQ(ierr);
833de6a44a3SBarry Smith     ierr = ViewerFileSetFormat(viewer,FILE_FORMAT_INFO_DETAILED,0);CHKERRQ(ierr);
834de6a44a3SBarry Smith     ierr = MatView(B,viewer); CHKERRQ(ierr);
835de6a44a3SBarry Smith     ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
836de6a44a3SBarry Smith   }
837de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view",&flg); CHKERRQ(ierr);
838de6a44a3SBarry Smith   if (flg) {
839de6a44a3SBarry Smith     Viewer viewer;
840de6a44a3SBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&viewer);CHKERRQ(ierr);
841de6a44a3SBarry Smith     ierr = MatView(B,viewer); CHKERRQ(ierr);
842de6a44a3SBarry Smith     ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
843de6a44a3SBarry Smith   }
844de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_matlab",&flg); CHKERRQ(ierr);
845de6a44a3SBarry Smith   if (flg) {
846de6a44a3SBarry Smith     Viewer viewer;
847de6a44a3SBarry Smith     ierr = ViewerFileOpenASCII(B->comm,"stdout",&viewer);CHKERRQ(ierr);
848de6a44a3SBarry Smith     ierr = ViewerFileSetFormat(viewer,FILE_FORMAT_MATLAB,"M");CHKERRQ(ierr);
849de6a44a3SBarry Smith     ierr = MatView(B,viewer); CHKERRQ(ierr);
850de6a44a3SBarry Smith     ierr = ViewerDestroy(viewer); CHKERRQ(ierr);
851de6a44a3SBarry Smith   }
852de6a44a3SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_view_draw",&flg); CHKERRQ(ierr);
853de6a44a3SBarry Smith   if (flg) {
854de6a44a3SBarry Smith     Draw    win;
855de6a44a3SBarry Smith     ierr = DrawOpenX(B->comm,0,0,0,0,300,300,&win); CHKERRQ(ierr);
856de6a44a3SBarry Smith     ierr = MatView(B,(Viewer)win); CHKERRQ(ierr);
857de6a44a3SBarry Smith     ierr = DrawSyncFlush(win); CHKERRQ(ierr);
858de6a44a3SBarry Smith     ierr = DrawDestroy(win); CHKERRQ(ierr);
859de6a44a3SBarry Smith   }
8602593348eSBarry Smith   return 0;
8612593348eSBarry Smith }
8622593348eSBarry Smith 
8632593348eSBarry Smith 
8642593348eSBarry Smith 
865