xref: /petsc/src/mat/impls/baij/mpi/mpibaij.c (revision 7ef1d9bd187294aa042bd52ec02f5579326131eb)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*7ef1d9bdSSatish Balay static char vcid[] = "$Id: mpibaij.c,v 1.158 1999/03/11 22:30:18 balay Exp balay $";
379bdfe76SSatish Balay #endif
479bdfe76SSatish Balay 
577ed5343SBarry Smith #include "src/mat/impls/baij/mpi/mpibaij.h"   /*I  "mat.h"  I*/
6c16cb8f2SBarry Smith #include "src/vec/vecimpl.h"
779bdfe76SSatish Balay 
857b952d6SSatish Balay extern int MatSetUpMultiply_MPIBAIJ(Mat);
957b952d6SSatish Balay extern int DisAssemble_MPIBAIJ(Mat);
10d212a18eSSatish Balay extern int MatIncreaseOverlap_MPIBAIJ(Mat,int,IS *,int);
117b2a1423SBarry Smith extern int MatGetSubMatrices_MPIBAIJ(Mat,int,IS *,IS *,MatReuse,Mat **);
12946de2abSSatish Balay extern int MatGetValues_SeqBAIJ(Mat,int,int *,int,int *,Scalar *);
13bbb85fb3SSatish Balay extern int MatSetValues_SeqBAIJ(Mat,int,int *,int,int *,Scalar *,InsertMode);
14bbb85fb3SSatish Balay extern int MatSetValuesBlocked_SeqBAIJ(Mat,int,int*,int,int*,Scalar*,InsertMode);
15bbb85fb3SSatish Balay extern int MatGetRow_SeqBAIJ(Mat,int,int*,int**,Scalar**);
16bbb85fb3SSatish Balay extern int MatRestoreRow_SeqBAIJ(Mat,int,int*,int**,Scalar**);
17bbb85fb3SSatish Balay extern int MatPrintHelp_SeqBAIJ(Mat);
183b2fbd54SBarry Smith 
19537820f0SBarry Smith /*
20537820f0SBarry Smith      Local utility routine that creates a mapping from the global column
2157b952d6SSatish Balay    number to the local number in the off-diagonal part of the local
2257b952d6SSatish Balay    storage of the matrix.  This is done in a non scable way since the
2357b952d6SSatish Balay    length of colmap equals the global matrix length.
2457b952d6SSatish Balay */
255615d1e5SSatish Balay #undef __FUNC__
265615d1e5SSatish Balay #define __FUNC__ "CreateColmap_MPIBAIJ_Private"
2757b952d6SSatish Balay static int CreateColmap_MPIBAIJ_Private(Mat mat)
2857b952d6SSatish Balay {
2957b952d6SSatish Balay   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
3057b952d6SSatish Balay   Mat_SeqBAIJ *B = (Mat_SeqBAIJ*) baij->B->data;
316dee3f7eSBarry Smith   int         nbs = B->nbs,i,bs=B->bs;
326dee3f7eSBarry Smith #if defined (USE_CTABLE)
336dee3f7eSBarry Smith   int         ierr;
346dee3f7eSBarry Smith #endif
3557b952d6SSatish Balay 
36d64ed03dSBarry Smith   PetscFunctionBegin;
3748e59246SSatish Balay #if defined (USE_CTABLE)
38fa46199cSSatish Balay   ierr = TableCreate(baij->nbs/5,&baij->colmap); CHKERRQ(ierr);
3948e59246SSatish Balay   for ( i=0; i<nbs; i++ ){
4048e59246SSatish Balay     ierr = TableAdd(baij->colmap,baij->garray[i]+1,i*bs+1);CHKERRQ(ierr);
4148e59246SSatish Balay   }
4248e59246SSatish Balay #else
43758f045eSSatish Balay   baij->colmap = (int *) PetscMalloc((baij->Nbs+1)*sizeof(int));CHKPTRQ(baij->colmap);
4457b952d6SSatish Balay   PLogObjectMemory(mat,baij->Nbs*sizeof(int));
4557b952d6SSatish Balay   PetscMemzero(baij->colmap,baij->Nbs*sizeof(int));
46928fc39bSSatish Balay   for ( i=0; i<nbs; i++ ) baij->colmap[baij->garray[i]] = i*bs+1;
4748e59246SSatish Balay #endif
483a40ed3dSBarry Smith   PetscFunctionReturn(0);
4957b952d6SSatish Balay }
5057b952d6SSatish Balay 
5180c1aa95SSatish Balay #define CHUNKSIZE  10
5280c1aa95SSatish Balay 
53f5e9677aSSatish Balay #define  MatSetValues_SeqBAIJ_A_Private(row,col,value,addv) \
5480c1aa95SSatish Balay { \
5580c1aa95SSatish Balay  \
5680c1aa95SSatish Balay     brow = row/bs;  \
5780c1aa95SSatish Balay     rp   = aj + ai[brow]; ap = aa + bs2*ai[brow]; \
58ac7a638eSSatish Balay     rmax = aimax[brow]; nrow = ailen[brow]; \
5980c1aa95SSatish Balay       bcol = col/bs; \
6080c1aa95SSatish Balay       ridx = row % bs; cidx = col % bs; \
61ab26458aSBarry Smith       low = 0; high = nrow; \
62ab26458aSBarry Smith       while (high-low > 3) { \
63ab26458aSBarry Smith         t = (low+high)/2; \
64ab26458aSBarry Smith         if (rp[t] > bcol) high = t; \
65ab26458aSBarry Smith         else              low  = t; \
66ab26458aSBarry Smith       } \
67ab26458aSBarry Smith       for ( _i=low; _i<high; _i++ ) { \
6880c1aa95SSatish Balay         if (rp[_i] > bcol) break; \
6980c1aa95SSatish Balay         if (rp[_i] == bcol) { \
7080c1aa95SSatish Balay           bap  = ap +  bs2*_i + bs*cidx + ridx; \
71eada6651SSatish Balay           if (addv == ADD_VALUES) *bap += value;  \
72eada6651SSatish Balay           else                    *bap  = value;  \
73ac7a638eSSatish Balay           goto a_noinsert; \
7480c1aa95SSatish Balay         } \
7580c1aa95SSatish Balay       } \
7689280ab3SLois Curfman McInnes       if (a->nonew == 1) goto a_noinsert; \
77a8c6a408SBarry Smith       else if (a->nonew == -1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero into matrix"); \
7880c1aa95SSatish Balay       if (nrow >= rmax) { \
7980c1aa95SSatish Balay         /* there is no extra room in row, therefore enlarge */ \
8080c1aa95SSatish Balay         int    new_nz = ai[a->mbs] + CHUNKSIZE,len,*new_i,*new_j; \
8180c1aa95SSatish Balay         Scalar *new_a; \
8280c1aa95SSatish Balay  \
83a8c6a408SBarry Smith         if (a->nonew == -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix"); \
8489280ab3SLois Curfman McInnes  \
8580c1aa95SSatish Balay         /* malloc new storage space */ \
8680c1aa95SSatish Balay         len     = new_nz*(sizeof(int)+bs2*sizeof(Scalar))+(a->mbs+1)*sizeof(int); \
8780c1aa95SSatish Balay         new_a   = (Scalar *) PetscMalloc( len ); CHKPTRQ(new_a); \
8880c1aa95SSatish Balay         new_j   = (int *) (new_a + bs2*new_nz); \
8980c1aa95SSatish Balay         new_i   = new_j + new_nz; \
9080c1aa95SSatish Balay  \
9180c1aa95SSatish Balay         /* copy over old data into new slots */ \
9280c1aa95SSatish Balay         for ( ii=0; ii<brow+1; ii++ ) {new_i[ii] = ai[ii];} \
9380c1aa95SSatish Balay         for ( ii=brow+1; ii<a->mbs+1; ii++ ) {new_i[ii] = ai[ii]+CHUNKSIZE;} \
9480c1aa95SSatish Balay         PetscMemcpy(new_j,aj,(ai[brow]+nrow)*sizeof(int)); \
9580c1aa95SSatish Balay         len = (new_nz - CHUNKSIZE - ai[brow] - nrow); \
9680c1aa95SSatish Balay         PetscMemcpy(new_j+ai[brow]+nrow+CHUNKSIZE,aj+ai[brow]+nrow, \
9780c1aa95SSatish Balay                                                            len*sizeof(int)); \
9880c1aa95SSatish Balay         PetscMemcpy(new_a,aa,(ai[brow]+nrow)*bs2*sizeof(Scalar)); \
9980c1aa95SSatish Balay         PetscMemzero(new_a+bs2*(ai[brow]+nrow),bs2*CHUNKSIZE*sizeof(Scalar)); \
10080c1aa95SSatish Balay         PetscMemcpy(new_a+bs2*(ai[brow]+nrow+CHUNKSIZE), \
10180c1aa95SSatish Balay                     aa+bs2*(ai[brow]+nrow),bs2*len*sizeof(Scalar));  \
10280c1aa95SSatish Balay         /* free up old matrix storage */ \
10380c1aa95SSatish Balay         PetscFree(a->a);  \
10480c1aa95SSatish Balay         if (!a->singlemalloc) {PetscFree(a->i);PetscFree(a->j);} \
10580c1aa95SSatish Balay         aa = a->a = new_a; ai = a->i = new_i; aj = a->j = new_j;  \
10680c1aa95SSatish Balay         a->singlemalloc = 1; \
10780c1aa95SSatish Balay  \
10880c1aa95SSatish Balay         rp   = aj + ai[brow]; ap = aa + bs2*ai[brow]; \
109ac7a638eSSatish Balay         rmax = aimax[brow] = aimax[brow] + CHUNKSIZE; \
11080c1aa95SSatish Balay         PLogObjectMemory(A,CHUNKSIZE*(sizeof(int) + bs2*sizeof(Scalar))); \
11180c1aa95SSatish Balay         a->maxnz += bs2*CHUNKSIZE; \
11280c1aa95SSatish Balay         a->reallocs++; \
11380c1aa95SSatish Balay         a->nz++; \
11480c1aa95SSatish Balay       } \
11580c1aa95SSatish Balay       N = nrow++ - 1;  \
11680c1aa95SSatish Balay       /* shift up all the later entries in this row */ \
11780c1aa95SSatish Balay       for ( ii=N; ii>=_i; ii-- ) { \
11880c1aa95SSatish Balay         rp[ii+1] = rp[ii]; \
11980c1aa95SSatish Balay         PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(Scalar)); \
12080c1aa95SSatish Balay       } \
12180c1aa95SSatish Balay       if (N>=_i) PetscMemzero(ap+bs2*_i,bs2*sizeof(Scalar));  \
12280c1aa95SSatish Balay       rp[_i]                      = bcol;  \
12380c1aa95SSatish Balay       ap[bs2*_i + bs*cidx + ridx] = value;  \
124ac7a638eSSatish Balay       a_noinsert:; \
12580c1aa95SSatish Balay     ailen[brow] = nrow; \
12680c1aa95SSatish Balay }
12757b952d6SSatish Balay 
128ac7a638eSSatish Balay #define  MatSetValues_SeqBAIJ_B_Private(row,col,value,addv) \
129ac7a638eSSatish Balay { \
130ac7a638eSSatish Balay  \
131ac7a638eSSatish Balay     brow = row/bs;  \
132ac7a638eSSatish Balay     rp   = bj + bi[brow]; ap = ba + bs2*bi[brow]; \
133ac7a638eSSatish Balay     rmax = bimax[brow]; nrow = bilen[brow]; \
134ac7a638eSSatish Balay       bcol = col/bs; \
135ac7a638eSSatish Balay       ridx = row % bs; cidx = col % bs; \
136ac7a638eSSatish Balay       low = 0; high = nrow; \
137ac7a638eSSatish Balay       while (high-low > 3) { \
138ac7a638eSSatish Balay         t = (low+high)/2; \
139ac7a638eSSatish Balay         if (rp[t] > bcol) high = t; \
140ac7a638eSSatish Balay         else              low  = t; \
141ac7a638eSSatish Balay       } \
142ac7a638eSSatish Balay       for ( _i=low; _i<high; _i++ ) { \
143ac7a638eSSatish Balay         if (rp[_i] > bcol) break; \
144ac7a638eSSatish Balay         if (rp[_i] == bcol) { \
145ac7a638eSSatish Balay           bap  = ap +  bs2*_i + bs*cidx + ridx; \
146ac7a638eSSatish Balay           if (addv == ADD_VALUES) *bap += value;  \
147ac7a638eSSatish Balay           else                    *bap  = value;  \
148ac7a638eSSatish Balay           goto b_noinsert; \
149ac7a638eSSatish Balay         } \
150ac7a638eSSatish Balay       } \
15189280ab3SLois Curfman McInnes       if (b->nonew == 1) goto b_noinsert; \
152a8c6a408SBarry Smith       else if (b->nonew == -1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero into matrix"); \
153ac7a638eSSatish Balay       if (nrow >= rmax) { \
154ac7a638eSSatish Balay         /* there is no extra room in row, therefore enlarge */ \
15574c639caSSatish Balay         int    new_nz = bi[b->mbs] + CHUNKSIZE,len,*new_i,*new_j; \
156ac7a638eSSatish Balay         Scalar *new_a; \
157ac7a638eSSatish Balay  \
158a8c6a408SBarry Smith         if (b->nonew == -2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Inserting a new nonzero in the matrix"); \
15989280ab3SLois Curfman McInnes  \
160ac7a638eSSatish Balay         /* malloc new storage space */ \
16174c639caSSatish Balay         len     = new_nz*(sizeof(int)+bs2*sizeof(Scalar))+(b->mbs+1)*sizeof(int); \
162ac7a638eSSatish Balay         new_a   = (Scalar *) PetscMalloc( len ); CHKPTRQ(new_a); \
163ac7a638eSSatish Balay         new_j   = (int *) (new_a + bs2*new_nz); \
164ac7a638eSSatish Balay         new_i   = new_j + new_nz; \
165ac7a638eSSatish Balay  \
166ac7a638eSSatish Balay         /* copy over old data into new slots */ \
167ac7a638eSSatish Balay         for ( ii=0; ii<brow+1; ii++ ) {new_i[ii] = bi[ii];} \
16874c639caSSatish Balay         for ( ii=brow+1; ii<b->mbs+1; ii++ ) {new_i[ii] = bi[ii]+CHUNKSIZE;} \
169ac7a638eSSatish Balay         PetscMemcpy(new_j,bj,(bi[brow]+nrow)*sizeof(int)); \
170ac7a638eSSatish Balay         len = (new_nz - CHUNKSIZE - bi[brow] - nrow); \
171ac7a638eSSatish Balay         PetscMemcpy(new_j+bi[brow]+nrow+CHUNKSIZE,bj+bi[brow]+nrow, \
172ac7a638eSSatish Balay                                                            len*sizeof(int)); \
173ac7a638eSSatish Balay         PetscMemcpy(new_a,ba,(bi[brow]+nrow)*bs2*sizeof(Scalar)); \
174ac7a638eSSatish Balay         PetscMemzero(new_a+bs2*(bi[brow]+nrow),bs2*CHUNKSIZE*sizeof(Scalar)); \
175ac7a638eSSatish Balay         PetscMemcpy(new_a+bs2*(bi[brow]+nrow+CHUNKSIZE), \
176ac7a638eSSatish Balay                     ba+bs2*(bi[brow]+nrow),bs2*len*sizeof(Scalar));  \
177ac7a638eSSatish Balay         /* free up old matrix storage */ \
17874c639caSSatish Balay         PetscFree(b->a);  \
17974c639caSSatish Balay         if (!b->singlemalloc) {PetscFree(b->i);PetscFree(b->j);} \
18074c639caSSatish Balay         ba = b->a = new_a; bi = b->i = new_i; bj = b->j = new_j;  \
18174c639caSSatish Balay         b->singlemalloc = 1; \
182ac7a638eSSatish Balay  \
183ac7a638eSSatish Balay         rp   = bj + bi[brow]; ap = ba + bs2*bi[brow]; \
184ac7a638eSSatish Balay         rmax = bimax[brow] = bimax[brow] + CHUNKSIZE; \
18574c639caSSatish Balay         PLogObjectMemory(B,CHUNKSIZE*(sizeof(int) + bs2*sizeof(Scalar))); \
18674c639caSSatish Balay         b->maxnz += bs2*CHUNKSIZE; \
18774c639caSSatish Balay         b->reallocs++; \
18874c639caSSatish Balay         b->nz++; \
189ac7a638eSSatish Balay       } \
190ac7a638eSSatish Balay       N = nrow++ - 1;  \
191ac7a638eSSatish Balay       /* shift up all the later entries in this row */ \
192ac7a638eSSatish Balay       for ( ii=N; ii>=_i; ii-- ) { \
193ac7a638eSSatish Balay         rp[ii+1] = rp[ii]; \
194ac7a638eSSatish Balay         PetscMemcpy(ap+bs2*(ii+1),ap+bs2*(ii),bs2*sizeof(Scalar)); \
195ac7a638eSSatish Balay       } \
196ac7a638eSSatish Balay       if (N>=_i) PetscMemzero(ap+bs2*_i,bs2*sizeof(Scalar));  \
197ac7a638eSSatish Balay       rp[_i]                      = bcol;  \
198ac7a638eSSatish Balay       ap[bs2*_i + bs*cidx + ridx] = value;  \
199ac7a638eSSatish Balay       b_noinsert:; \
200ac7a638eSSatish Balay     bilen[brow] = nrow; \
201ac7a638eSSatish Balay }
202ac7a638eSSatish Balay 
2035615d1e5SSatish Balay #undef __FUNC__
2045615d1e5SSatish Balay #define __FUNC__ "MatSetValues_MPIBAIJ"
205ec1ea8d8SLois Curfman McInnes int MatSetValues_MPIBAIJ(Mat mat,int m,int *im,int n,int *in,Scalar *v,InsertMode addv)
20657b952d6SSatish Balay {
20757b952d6SSatish Balay   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
20857b952d6SSatish Balay   Scalar      value;
2094fa0d573SSatish Balay   int         ierr,i,j,row,col;
2104fa0d573SSatish Balay   int         roworiented = baij->roworiented,rstart_orig=baij->rstart_bs ;
2114fa0d573SSatish Balay   int         rend_orig=baij->rend_bs,cstart_orig=baij->cstart_bs;
2124fa0d573SSatish Balay   int         cend_orig=baij->cend_bs,bs=baij->bs;
21357b952d6SSatish Balay 
214eada6651SSatish Balay   /* Some Variables required in the macro */
21580c1aa95SSatish Balay   Mat         A = baij->A;
21680c1aa95SSatish Balay   Mat_SeqBAIJ *a = (Mat_SeqBAIJ *) (A)->data;
217ac7a638eSSatish Balay   int         *aimax=a->imax,*ai=a->i,*ailen=a->ilen,*aj=a->j;
218ac7a638eSSatish Balay   Scalar      *aa=a->a;
219ac7a638eSSatish Balay 
220ac7a638eSSatish Balay   Mat         B = baij->B;
221ac7a638eSSatish Balay   Mat_SeqBAIJ *b = (Mat_SeqBAIJ *) (B)->data;
222ac7a638eSSatish Balay   int         *bimax=b->imax,*bi=b->i,*bilen=b->ilen,*bj=b->j;
223ac7a638eSSatish Balay   Scalar      *ba=b->a;
224ac7a638eSSatish Balay 
225ac7a638eSSatish Balay   int         *rp,ii,nrow,_i,rmax,N,brow,bcol;
226ab26458aSBarry Smith   int         low,high,t,ridx,cidx,bs2=a->bs2;
227ac7a638eSSatish Balay   Scalar      *ap,*bap;
22880c1aa95SSatish Balay 
229d64ed03dSBarry Smith   PetscFunctionBegin;
23057b952d6SSatish Balay   for ( i=0; i<m; i++ ) {
2315ef9f2a5SBarry Smith     if (im[i] < 0) continue;
2323a40ed3dSBarry Smith #if defined(USE_PETSC_BOPT_g)
233a8c6a408SBarry Smith     if (im[i] >= baij->M) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large");
234639f9d9dSBarry Smith #endif
23557b952d6SSatish Balay     if (im[i] >= rstart_orig && im[i] < rend_orig) {
23657b952d6SSatish Balay       row = im[i] - rstart_orig;
23757b952d6SSatish Balay       for ( j=0; j<n; j++ ) {
23857b952d6SSatish Balay         if (in[j] >= cstart_orig && in[j] < cend_orig){
23957b952d6SSatish Balay           col = in[j] - cstart_orig;
24057b952d6SSatish Balay           if (roworiented) value = v[i*n+j]; else value = v[i+j*m];
241f5e9677aSSatish Balay           MatSetValues_SeqBAIJ_A_Private(row,col,value,addv);
24280c1aa95SSatish Balay           /* ierr = MatSetValues_SeqBAIJ(baij->A,1,&row,1,&col,&value,addv);CHKERRQ(ierr); */
24357b952d6SSatish Balay         }
2445ef9f2a5SBarry Smith         else if (in[j] < 0) continue;
2453a40ed3dSBarry Smith #if defined(USE_PETSC_BOPT_g)
246a8c6a408SBarry Smith         else if (in[j] >= baij->N) {SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Col too large");}
247639f9d9dSBarry Smith #endif
24857b952d6SSatish Balay         else {
24957b952d6SSatish Balay           if (mat->was_assembled) {
250905e6a2fSBarry Smith             if (!baij->colmap) {
251905e6a2fSBarry Smith               ierr = CreateColmap_MPIBAIJ_Private(mat);CHKERRQ(ierr);
252905e6a2fSBarry Smith             }
25348e59246SSatish Balay #if defined (USE_CTABLE)
254fa46199cSSatish Balay             ierr = TableFind(baij->colmap, in[j]/bs + 1,&col); CHKERRQ(ierr);
255fa46199cSSatish Balay             col  = col - 1 + in[j]%bs;
25648e59246SSatish Balay #else
257905e6a2fSBarry Smith             col = baij->colmap[in[j]/bs] - 1 + in[j]%bs;
25848e59246SSatish Balay #endif
25957b952d6SSatish Balay             if (col < 0 && !((Mat_SeqBAIJ*)(baij->A->data))->nonew) {
26057b952d6SSatish Balay               ierr = DisAssemble_MPIBAIJ(mat); CHKERRQ(ierr);
26157b952d6SSatish Balay               col =  in[j];
2629bf004c3SSatish Balay               /* Reinitialize the variables required by MatSetValues_SeqBAIJ_B_Private() */
2639bf004c3SSatish Balay               B = baij->B;
2649bf004c3SSatish Balay               b = (Mat_SeqBAIJ *) (B)->data;
2659bf004c3SSatish Balay               bimax=b->imax;bi=b->i;bilen=b->ilen;bj=b->j;
2669bf004c3SSatish Balay               ba=b->a;
26757b952d6SSatish Balay             }
268d64ed03dSBarry Smith           } else col = in[j];
26957b952d6SSatish Balay           if (roworiented) value = v[i*n+j]; else value = v[i+j*m];
270ac7a638eSSatish Balay           MatSetValues_SeqBAIJ_B_Private(row,col,value,addv);
271ac7a638eSSatish Balay           /* ierr = MatSetValues_SeqBAIJ(baij->B,1,&row,1,&col,&value,addv);CHKERRQ(ierr); */
27257b952d6SSatish Balay         }
27357b952d6SSatish Balay       }
274d64ed03dSBarry Smith     } else {
27590f02eecSBarry Smith       if (roworiented && !baij->donotstash) {
276a2d1c673SSatish Balay         ierr = StashValues_Private(&baij->stash,im[i],n,in,v+i*n);CHKERRQ(ierr);
277d64ed03dSBarry Smith       } else {
27890f02eecSBarry Smith         if (!baij->donotstash) {
27957b952d6SSatish Balay           row = im[i];
28057b952d6SSatish Balay 	  for ( j=0; j<n; j++ ) {
281a2d1c673SSatish Balay 	    ierr = StashValues_Private(&baij->stash,row,1,in+j,v+i+j*m);CHKERRQ(ierr);
28257b952d6SSatish Balay           }
28357b952d6SSatish Balay         }
28457b952d6SSatish Balay       }
28557b952d6SSatish Balay     }
28690f02eecSBarry Smith   }
2873a40ed3dSBarry Smith   PetscFunctionReturn(0);
28857b952d6SSatish Balay }
28957b952d6SSatish Balay 
290ab26458aSBarry Smith #undef __FUNC__
291ab26458aSBarry Smith #define __FUNC__ "MatSetValuesBlocked_MPIBAIJ"
292ec1ea8d8SLois Curfman McInnes int MatSetValuesBlocked_MPIBAIJ(Mat mat,int m,int *im,int n,int *in,Scalar *v,InsertMode addv)
293ab26458aSBarry Smith {
294ab26458aSBarry Smith   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
29530793edcSSatish Balay   Scalar      *value,*barray=baij->barray;
296*7ef1d9bdSSatish Balay   int         ierr,i,j,ii,jj,row,col;
297ab26458aSBarry Smith   int         roworiented = baij->roworiented,rstart=baij->rstart ;
298ab26458aSBarry Smith   int         rend=baij->rend,cstart=baij->cstart,stepval;
299ab26458aSBarry Smith   int         cend=baij->cend,bs=baij->bs,bs2=baij->bs2;
300ab26458aSBarry Smith 
30130793edcSSatish Balay   if(!barray) {
30247513183SBarry Smith     baij->barray = barray = (Scalar*) PetscMalloc(bs2*sizeof(Scalar)); CHKPTRQ(barray);
30330793edcSSatish Balay   }
30430793edcSSatish Balay 
305ab26458aSBarry Smith   if (roworiented) {
306ab26458aSBarry Smith     stepval = (n-1)*bs;
307ab26458aSBarry Smith   } else {
308ab26458aSBarry Smith     stepval = (m-1)*bs;
309ab26458aSBarry Smith   }
310ab26458aSBarry Smith   for ( i=0; i<m; i++ ) {
3115ef9f2a5SBarry Smith     if (im[i] < 0) continue;
3123a40ed3dSBarry Smith #if defined(USE_PETSC_BOPT_g)
3135ef9f2a5SBarry Smith     if (im[i] >= baij->Mbs) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large, row %d max %d",im[i],baij->Mbs);
314ab26458aSBarry Smith #endif
315ab26458aSBarry Smith     if (im[i] >= rstart && im[i] < rend) {
316ab26458aSBarry Smith       row = im[i] - rstart;
317ab26458aSBarry Smith       for ( j=0; j<n; j++ ) {
31815b57d14SSatish Balay         /* If NumCol = 1 then a copy is not required */
31915b57d14SSatish Balay         if ((roworiented) && (n == 1)) {
32015b57d14SSatish Balay           barray = v + i*bs2;
32115b57d14SSatish Balay         } else if((!roworiented) && (m == 1)) {
32215b57d14SSatish Balay           barray = v + j*bs2;
32315b57d14SSatish Balay         } else { /* Here a copy is required */
324ab26458aSBarry Smith           if (roworiented) {
325ab26458aSBarry Smith             value = v + i*(stepval+bs)*bs + j*bs;
326ab26458aSBarry Smith           } else {
327ab26458aSBarry Smith             value = v + j*(stepval+bs)*bs + i*bs;
328abef11f7SSatish Balay           }
32947513183SBarry Smith           for ( ii=0; ii<bs; ii++,value+=stepval ) {
33047513183SBarry Smith             for (jj=0; jj<bs; jj++ ) {
33130793edcSSatish Balay               *barray++  = *value++;
33247513183SBarry Smith             }
33347513183SBarry Smith           }
33430793edcSSatish Balay           barray -=bs2;
33515b57d14SSatish Balay         }
336abef11f7SSatish Balay 
337abef11f7SSatish Balay         if (in[j] >= cstart && in[j] < cend){
338abef11f7SSatish Balay           col  = in[j] - cstart;
33930793edcSSatish Balay           ierr = MatSetValuesBlocked_SeqBAIJ(baij->A,1,&row,1,&col,barray,addv);CHKERRQ(ierr);
340ab26458aSBarry Smith         }
3415ef9f2a5SBarry Smith         else if (in[j] < 0) continue;
3423a40ed3dSBarry Smith #if defined(USE_PETSC_BOPT_g)
3435ef9f2a5SBarry Smith         else if (in[j] >= baij->Nbs) {SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large, col %d max %d",in[j],baij->Nbs);}
344ab26458aSBarry Smith #endif
345ab26458aSBarry Smith         else {
346ab26458aSBarry Smith           if (mat->was_assembled) {
347ab26458aSBarry Smith             if (!baij->colmap) {
348ab26458aSBarry Smith               ierr = CreateColmap_MPIBAIJ_Private(mat);CHKERRQ(ierr);
349ab26458aSBarry Smith             }
350a5eb4965SSatish Balay 
3513a40ed3dSBarry Smith #if defined(USE_PETSC_BOPT_g)
35248e59246SSatish Balay #if defined (USE_CTABLE)
353fa46199cSSatish Balay             { int data;
354fa46199cSSatish Balay             ierr = TableFind(baij->colmap,in[j]+1,&data); CHKERRQ(ierr);
355fa46199cSSatish Balay             if((data - 1) % bs)
35648e59246SSatish Balay 	      {SETERRQ(PETSC_ERR_PLIB,0,"Incorrect colmap");}
357fa46199cSSatish Balay             }
35848e59246SSatish Balay #else
359a8c6a408SBarry Smith             if ((baij->colmap[in[j]] - 1) % bs) {SETERRQ(PETSC_ERR_PLIB,0,"Incorrect colmap");}
360a5eb4965SSatish Balay #endif
36148e59246SSatish Balay #endif
36248e59246SSatish Balay #if defined (USE_CTABLE)
363fa46199cSSatish Balay 	    ierr = TableFind(baij->colmap,in[j]+1,&col); CHKERRQ(ierr);
364fa46199cSSatish Balay             col  = (col - 1)/bs;
36548e59246SSatish Balay #else
366a5eb4965SSatish Balay             col = (baij->colmap[in[j]] - 1)/bs;
36748e59246SSatish Balay #endif
368ab26458aSBarry Smith             if (col < 0 && !((Mat_SeqBAIJ*)(baij->A->data))->nonew) {
369ab26458aSBarry Smith               ierr = DisAssemble_MPIBAIJ(mat); CHKERRQ(ierr);
370ab26458aSBarry Smith               col =  in[j];
371ab26458aSBarry Smith             }
372ab26458aSBarry Smith           }
373ab26458aSBarry Smith           else col = in[j];
37430793edcSSatish Balay           ierr = MatSetValuesBlocked_SeqBAIJ(baij->B,1,&row,1,&col,barray,addv);CHKERRQ(ierr);
375ab26458aSBarry Smith         }
376ab26458aSBarry Smith       }
377d64ed03dSBarry Smith     } else {
378ab26458aSBarry Smith       if (!baij->donotstash) {
379a2d1c673SSatish Balay         /*        ierr = StashValuesBlocked_Private(&baij->bstash,im[i],n,in,v+i*bs2*n,
380a2d1c673SSatish Balay                                           roworiented,stepval,addv);CHKERRQ(ierr); */
381a2d1c673SSatish Balay         ierr = StashValuesBlocked_Private(&baij->bstash,im[i],n,in,v,m,n,
382a2d1c673SSatish Balay                                           roworiented,i);CHKERRQ(ierr);
383abef11f7SSatish Balay       }
384ab26458aSBarry Smith     }
385ab26458aSBarry Smith   }
3863a40ed3dSBarry Smith   PetscFunctionReturn(0);
387ab26458aSBarry Smith }
3880bdbc534SSatish Balay #define HASH_KEY 0.6180339887
389c2760754SSatish Balay /* #define HASH1(size,key) ((int)((size)*fmod(((key)*HASH_KEY),1))) */
390c2760754SSatish Balay #define HASH(size,key,tmp) (tmp = (key)*HASH_KEY,(int)((size)*(tmp-(int)tmp)))
391c2760754SSatish Balay /* #define HASH(size,key,tmp) ((int)((size)*fmod(((key)*HASH_KEY),1))) */
3925615d1e5SSatish Balay #undef __FUNC__
3930bdbc534SSatish Balay #define __FUNC__ "MatSetValues_MPIBAIJ_HT"
3940bdbc534SSatish Balay int MatSetValues_MPIBAIJ_HT(Mat mat,int m,int *im,int n,int *in,Scalar *v,InsertMode addv)
3950bdbc534SSatish Balay {
3960bdbc534SSatish Balay   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
3970bdbc534SSatish Balay   int         ierr,i,j,row,col;
3980bdbc534SSatish Balay   int         roworiented = baij->roworiented,rstart_orig=baij->rstart_bs ;
399c2760754SSatish Balay   int         rend_orig=baij->rend_bs,Nbs=baij->Nbs;
400c2760754SSatish Balay   int         h1,key,size=baij->ht_size,bs=baij->bs,*HT=baij->ht,idx;
401c2760754SSatish Balay   double      tmp;
402b9e4cc15SSatish Balay   Scalar      ** HD = baij->hd,value;
4034a15367fSSatish Balay #if defined(USE_PETSC_BOPT_g)
4044a15367fSSatish Balay   int         total_ct=baij->ht_total_ct,insert_ct=baij->ht_insert_ct;
4054a15367fSSatish Balay #endif
4060bdbc534SSatish Balay 
4070bdbc534SSatish Balay   PetscFunctionBegin;
4080bdbc534SSatish Balay 
4090bdbc534SSatish Balay   for ( i=0; i<m; i++ ) {
4100bdbc534SSatish Balay #if defined(USE_PETSC_BOPT_g)
4110bdbc534SSatish Balay     if (im[i] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative row");
4120bdbc534SSatish Balay     if (im[i] >= baij->M) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large");
4130bdbc534SSatish Balay #endif
4140bdbc534SSatish Balay       row = im[i];
415c2760754SSatish Balay     if (row >= rstart_orig && row < rend_orig) {
4160bdbc534SSatish Balay       for ( j=0; j<n; j++ ) {
4170bdbc534SSatish Balay         col = in[j];
4180bdbc534SSatish Balay         if (roworiented) value = v[i*n+j]; else value = v[i+j*m];
4190bdbc534SSatish Balay         /* Look up into the Hash Table */
420c2760754SSatish Balay         key = (row/bs)*Nbs+(col/bs)+1;
421c2760754SSatish Balay         h1  = HASH(size,key,tmp);
4220bdbc534SSatish Balay 
423c2760754SSatish Balay 
424c2760754SSatish Balay         idx = h1;
425187ce0cbSSatish Balay #if defined(USE_PETSC_BOPT_g)
426187ce0cbSSatish Balay         insert_ct++;
427187ce0cbSSatish Balay         total_ct++;
428187ce0cbSSatish Balay         if (HT[idx] != key) {
429187ce0cbSSatish Balay           for ( idx=h1; (idx<size) && (HT[idx]!=key); idx++,total_ct++);
430187ce0cbSSatish Balay           if (idx == size) {
431187ce0cbSSatish Balay             for ( idx=0; (idx<h1) && (HT[idx]!=key); idx++,total_ct++);
432187ce0cbSSatish Balay             if (idx == h1) {
433187ce0cbSSatish Balay               SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"(row,col) has no entry in the hash table");
434187ce0cbSSatish Balay             }
435187ce0cbSSatish Balay           }
436187ce0cbSSatish Balay         }
437187ce0cbSSatish Balay #else
438c2760754SSatish Balay         if (HT[idx] != key) {
439c2760754SSatish Balay           for ( idx=h1; (idx<size) && (HT[idx]!=key); idx++);
440c2760754SSatish Balay           if (idx == size) {
441c2760754SSatish Balay             for ( idx=0; (idx<h1) && (HT[idx]!=key); idx++);
442c2760754SSatish Balay             if (idx == h1) {
443c2760754SSatish Balay               SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"(row,col) has no entry in the hash table");
444c2760754SSatish Balay             }
445c2760754SSatish Balay           }
446c2760754SSatish Balay         }
447187ce0cbSSatish Balay #endif
448c2760754SSatish Balay         /* A HASH table entry is found, so insert the values at the correct address */
449c2760754SSatish Balay         if (addv == ADD_VALUES) *(HD[idx]+ (col % bs)*bs + (row % bs)) += value;
450c2760754SSatish Balay         else                    *(HD[idx]+ (col % bs)*bs + (row % bs))  = value;
4510bdbc534SSatish Balay       }
4520bdbc534SSatish Balay     } else {
4530bdbc534SSatish Balay       if (roworiented && !baij->donotstash) {
454a2d1c673SSatish Balay         ierr = StashValues_Private(&baij->stash,im[i],n,in,v+i*n);CHKERRQ(ierr);
4550bdbc534SSatish Balay       } else {
4560bdbc534SSatish Balay         if (!baij->donotstash) {
4570bdbc534SSatish Balay           row = im[i];
4580bdbc534SSatish Balay 	  for ( j=0; j<n; j++ ) {
459a2d1c673SSatish Balay 	    ierr = StashValues_Private(&baij->stash,row,1,in+j,v+i+j*m);CHKERRQ(ierr);
4600bdbc534SSatish Balay           }
4610bdbc534SSatish Balay         }
4620bdbc534SSatish Balay       }
4630bdbc534SSatish Balay     }
4640bdbc534SSatish Balay   }
465187ce0cbSSatish Balay #if defined(USE_PETSC_BOPT_g)
466187ce0cbSSatish Balay   baij->ht_total_ct = total_ct;
467187ce0cbSSatish Balay   baij->ht_insert_ct = insert_ct;
468187ce0cbSSatish Balay #endif
4690bdbc534SSatish Balay   PetscFunctionReturn(0);
4700bdbc534SSatish Balay }
4710bdbc534SSatish Balay 
4720bdbc534SSatish Balay #undef __FUNC__
4730bdbc534SSatish Balay #define __FUNC__ "MatSetValuesBlocked_MPIBAIJ_HT"
4740bdbc534SSatish Balay int MatSetValuesBlocked_MPIBAIJ_HT(Mat mat,int m,int *im,int n,int *in,Scalar *v,InsertMode addv)
4750bdbc534SSatish Balay {
4760bdbc534SSatish Balay   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
4770bdbc534SSatish Balay   int         ierr,i,j,ii,jj,row,col,k,l;
4780bdbc534SSatish Balay   int         roworiented = baij->roworiented,rstart=baij->rstart ;
479b4cc0f5aSSatish Balay   int         rend=baij->rend,stepval,bs=baij->bs,bs2=baij->bs2;
480c2760754SSatish Balay   int         h1,key,size=baij->ht_size,idx,*HT=baij->ht,Nbs=baij->Nbs;
481c2760754SSatish Balay   double      tmp;
482187ce0cbSSatish Balay   Scalar      ** HD = baij->hd,*value,*v_t,*baij_a;
4834a15367fSSatish Balay #if defined(USE_PETSC_BOPT_g)
4844a15367fSSatish Balay   int         total_ct=baij->ht_total_ct,insert_ct=baij->ht_insert_ct;
4854a15367fSSatish Balay #endif
4860bdbc534SSatish Balay 
487d0a41580SSatish Balay   PetscFunctionBegin;
488d0a41580SSatish Balay 
4890bdbc534SSatish Balay   if (roworiented) {
4900bdbc534SSatish Balay     stepval = (n-1)*bs;
4910bdbc534SSatish Balay   } else {
4920bdbc534SSatish Balay     stepval = (m-1)*bs;
4930bdbc534SSatish Balay   }
4940bdbc534SSatish Balay   for ( i=0; i<m; i++ ) {
4950bdbc534SSatish Balay #if defined(USE_PETSC_BOPT_g)
4960bdbc534SSatish Balay     if (im[i] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative row");
4970bdbc534SSatish Balay     if (im[i] >= baij->Mbs) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large");
4980bdbc534SSatish Balay #endif
4990bdbc534SSatish Balay     row   = im[i];
500187ce0cbSSatish Balay     v_t   = v + i*bs2;
501c2760754SSatish Balay     if (row >= rstart && row < rend) {
5020bdbc534SSatish Balay       for ( j=0; j<n; j++ ) {
5030bdbc534SSatish Balay         col = in[j];
5040bdbc534SSatish Balay 
5050bdbc534SSatish Balay         /* Look up into the Hash Table */
506c2760754SSatish Balay         key = row*Nbs+col+1;
507c2760754SSatish Balay         h1  = HASH(size,key,tmp);
5080bdbc534SSatish Balay 
509c2760754SSatish Balay         idx = h1;
510187ce0cbSSatish Balay #if defined(USE_PETSC_BOPT_g)
511187ce0cbSSatish Balay         total_ct++;
512187ce0cbSSatish Balay         insert_ct++;
513187ce0cbSSatish Balay        if (HT[idx] != key) {
514187ce0cbSSatish Balay           for ( idx=h1; (idx<size) && (HT[idx]!=key); idx++,total_ct++);
515187ce0cbSSatish Balay           if (idx == size) {
516187ce0cbSSatish Balay             for ( idx=0; (idx<h1) && (HT[idx]!=key); idx++,total_ct++);
517187ce0cbSSatish Balay             if (idx == h1) {
518187ce0cbSSatish Balay               SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"(row,col) has no entry in the hash table");
519187ce0cbSSatish Balay             }
520187ce0cbSSatish Balay           }
521187ce0cbSSatish Balay         }
522187ce0cbSSatish Balay #else
523c2760754SSatish Balay         if (HT[idx] != key) {
524c2760754SSatish Balay           for ( idx=h1; (idx<size) && (HT[idx]!=key); idx++);
525c2760754SSatish Balay           if (idx == size) {
526c2760754SSatish Balay             for ( idx=0; (idx<h1) && (HT[idx]!=key); idx++);
527c2760754SSatish Balay             if (idx == h1) {
528c2760754SSatish Balay               SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"(row,col) has no entry in the hash table");
529c2760754SSatish Balay             }
530c2760754SSatish Balay           }
531c2760754SSatish Balay         }
532187ce0cbSSatish Balay #endif
533c2760754SSatish Balay         baij_a = HD[idx];
5340bdbc534SSatish Balay         if (roworiented) {
535c2760754SSatish Balay           /*value = v + i*(stepval+bs)*bs + j*bs;*/
536187ce0cbSSatish Balay           /* value = v + (i*(stepval+bs)+j)*bs; */
537187ce0cbSSatish Balay           value = v_t;
538187ce0cbSSatish Balay           v_t  += bs;
539fef45726SSatish Balay           if (addv == ADD_VALUES) {
540c2760754SSatish Balay             for ( ii=0; ii<bs; ii++,value+=stepval) {
541c2760754SSatish Balay               for ( jj=ii; jj<bs2; jj+=bs ) {
542fef45726SSatish Balay                 baij_a[jj]  += *value++;
543b4cc0f5aSSatish Balay               }
544b4cc0f5aSSatish Balay             }
545fef45726SSatish Balay           } else {
546c2760754SSatish Balay             for ( ii=0; ii<bs; ii++,value+=stepval) {
547c2760754SSatish Balay               for ( jj=ii; jj<bs2; jj+=bs ) {
548fef45726SSatish Balay                 baij_a[jj]  = *value++;
549fef45726SSatish Balay               }
550fef45726SSatish Balay             }
551fef45726SSatish Balay           }
5520bdbc534SSatish Balay         } else {
5530bdbc534SSatish Balay           value = v + j*(stepval+bs)*bs + i*bs;
554fef45726SSatish Balay           if (addv == ADD_VALUES) {
555b4cc0f5aSSatish Balay             for ( ii=0; ii<bs; ii++,value+=stepval,baij_a+=bs ) {
5560bdbc534SSatish Balay               for ( jj=0; jj<bs; jj++ ) {
557fef45726SSatish Balay                 baij_a[jj]  += *value++;
558fef45726SSatish Balay               }
559fef45726SSatish Balay             }
560fef45726SSatish Balay           } else {
561fef45726SSatish Balay             for ( ii=0; ii<bs; ii++,value+=stepval,baij_a+=bs ) {
562fef45726SSatish Balay               for ( jj=0; jj<bs; jj++ ) {
563fef45726SSatish Balay                 baij_a[jj]  = *value++;
564fef45726SSatish Balay               }
565b4cc0f5aSSatish Balay             }
5660bdbc534SSatish Balay           }
5670bdbc534SSatish Balay         }
5680bdbc534SSatish Balay       }
5690bdbc534SSatish Balay     } else {
5700bdbc534SSatish Balay       if (!baij->donotstash) {
5710bdbc534SSatish Balay         if (roworiented ) {
5720bdbc534SSatish Balay           row   = im[i]*bs;
5730bdbc534SSatish Balay           value = v + i*(stepval+bs)*bs;
5740bdbc534SSatish Balay           for ( j=0; j<bs; j++,row++ ) {
5750bdbc534SSatish Balay             for ( k=0; k<n; k++ ) {
5760bdbc534SSatish Balay               for ( col=in[k]*bs,l=0; l<bs; l++,col++) {
577a2d1c673SSatish Balay                 ierr = StashValues_Private(&baij->stash,row,1,&col,value++);CHKERRQ(ierr);
5780bdbc534SSatish Balay               }
5790bdbc534SSatish Balay             }
5800bdbc534SSatish Balay           }
5810bdbc534SSatish Balay         } else {
5820bdbc534SSatish Balay           for ( j=0; j<n; j++ ) {
5830bdbc534SSatish Balay             value = v + j*(stepval+bs)*bs + i*bs;
5840bdbc534SSatish Balay             col   = in[j]*bs;
5850bdbc534SSatish Balay             for ( k=0; k<bs; k++,col++,value+=stepval) {
5860bdbc534SSatish Balay               for ( row = im[i]*bs,l=0; l<bs; l++,row++) {
587a2d1c673SSatish Balay                 ierr = StashValues_Private(&baij->stash,row,1,&col,value++);CHKERRQ(ierr);
5880bdbc534SSatish Balay               }
5890bdbc534SSatish Balay             }
5900bdbc534SSatish Balay           }
5910bdbc534SSatish Balay         }
5920bdbc534SSatish Balay       }
5930bdbc534SSatish Balay     }
5940bdbc534SSatish Balay   }
595187ce0cbSSatish Balay #if defined(USE_PETSC_BOPT_g)
596187ce0cbSSatish Balay   baij->ht_total_ct = total_ct;
597187ce0cbSSatish Balay   baij->ht_insert_ct = insert_ct;
598187ce0cbSSatish Balay #endif
5990bdbc534SSatish Balay   PetscFunctionReturn(0);
6000bdbc534SSatish Balay }
601133cdb44SSatish Balay 
6020bdbc534SSatish Balay #undef __FUNC__
6035615d1e5SSatish Balay #define __FUNC__ "MatGetValues_MPIBAIJ"
604ec1ea8d8SLois Curfman McInnes int MatGetValues_MPIBAIJ(Mat mat,int m,int *idxm,int n,int *idxn,Scalar *v)
605d6de1c52SSatish Balay {
606d6de1c52SSatish Balay   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
607d6de1c52SSatish Balay   int        bs=baij->bs,ierr,i,j, bsrstart = baij->rstart*bs, bsrend = baij->rend*bs;
60848e59246SSatish Balay   int        bscstart = baij->cstart*bs, bscend = baij->cend*bs,row,col,data;
609d6de1c52SSatish Balay 
610133cdb44SSatish Balay   PetscFunctionBegin;
611d6de1c52SSatish Balay   for ( i=0; i<m; i++ ) {
612a8c6a408SBarry Smith     if (idxm[i] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative row");
613a8c6a408SBarry Smith     if (idxm[i] >= baij->M) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large");
614d6de1c52SSatish Balay     if (idxm[i] >= bsrstart && idxm[i] < bsrend) {
615d6de1c52SSatish Balay       row = idxm[i] - bsrstart;
616d6de1c52SSatish Balay       for ( j=0; j<n; j++ ) {
617a8c6a408SBarry Smith         if (idxn[j] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative column");
618a8c6a408SBarry Smith         if (idxn[j] >= baij->N) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large");
619d6de1c52SSatish Balay         if (idxn[j] >= bscstart && idxn[j] < bscend){
620d6de1c52SSatish Balay           col = idxn[j] - bscstart;
62198dd23e9SBarry Smith           ierr = MatGetValues_SeqBAIJ(baij->A,1,&row,1,&col,v+i*n+j); CHKERRQ(ierr);
622d64ed03dSBarry Smith         } else {
623905e6a2fSBarry Smith           if (!baij->colmap) {
624905e6a2fSBarry Smith             ierr = CreateColmap_MPIBAIJ_Private(mat);CHKERRQ(ierr);
625905e6a2fSBarry Smith           }
62648e59246SSatish Balay #if defined (USE_CTABLE)
627fa46199cSSatish Balay           ierr = TableFind(baij->colmap,idxn[j]/bs+1,&data); CHKERRQ(ierr);
628fa46199cSSatish Balay           data --;
62948e59246SSatish Balay #else
63048e59246SSatish Balay           data = baij->colmap[idxn[j]/bs]-1;
63148e59246SSatish Balay #endif
63248e59246SSatish Balay           if((data < 0) || (baij->garray[data/bs] != idxn[j]/bs)) *(v+i*n+j) = 0.0;
633d9d09a02SSatish Balay           else {
63448e59246SSatish Balay             col  = data + idxn[j]%bs;
63598dd23e9SBarry Smith             ierr = MatGetValues_SeqBAIJ(baij->B,1,&row,1,&col,v+i*n+j); CHKERRQ(ierr);
636d6de1c52SSatish Balay           }
637d6de1c52SSatish Balay         }
638d6de1c52SSatish Balay       }
639d64ed03dSBarry Smith     } else {
640a8c6a408SBarry Smith       SETERRQ(PETSC_ERR_SUP,0,"Only local values currently supported");
641d6de1c52SSatish Balay     }
642d6de1c52SSatish Balay   }
6433a40ed3dSBarry Smith  PetscFunctionReturn(0);
644d6de1c52SSatish Balay }
645d6de1c52SSatish Balay 
6465615d1e5SSatish Balay #undef __FUNC__
6475615d1e5SSatish Balay #define __FUNC__ "MatNorm_MPIBAIJ"
648ec1ea8d8SLois Curfman McInnes int MatNorm_MPIBAIJ(Mat mat,NormType type,double *norm)
649d6de1c52SSatish Balay {
650d6de1c52SSatish Balay   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
651d6de1c52SSatish Balay   Mat_SeqBAIJ *amat = (Mat_SeqBAIJ*) baij->A->data, *bmat = (Mat_SeqBAIJ*) baij->B->data;
652acdf5bf4SSatish Balay   int        ierr, i,bs2=baij->bs2;
653d6de1c52SSatish Balay   double     sum = 0.0;
654d6de1c52SSatish Balay   Scalar     *v;
655d6de1c52SSatish Balay 
656d64ed03dSBarry Smith   PetscFunctionBegin;
657d6de1c52SSatish Balay   if (baij->size == 1) {
658d6de1c52SSatish Balay     ierr =  MatNorm(baij->A,type,norm); CHKERRQ(ierr);
659d6de1c52SSatish Balay   } else {
660d6de1c52SSatish Balay     if (type == NORM_FROBENIUS) {
661d6de1c52SSatish Balay       v = amat->a;
662d6de1c52SSatish Balay       for (i=0; i<amat->nz*bs2; i++ ) {
6633a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
664e20fef11SSatish Balay         sum += PetscReal(PetscConj(*v)*(*v)); v++;
665d6de1c52SSatish Balay #else
666d6de1c52SSatish Balay         sum += (*v)*(*v); v++;
667d6de1c52SSatish Balay #endif
668d6de1c52SSatish Balay       }
669d6de1c52SSatish Balay       v = bmat->a;
670d6de1c52SSatish Balay       for (i=0; i<bmat->nz*bs2; i++ ) {
6713a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
672e20fef11SSatish Balay         sum += PetscReal(PetscConj(*v)*(*v)); v++;
673d6de1c52SSatish Balay #else
674d6de1c52SSatish Balay         sum += (*v)*(*v); v++;
675d6de1c52SSatish Balay #endif
676d6de1c52SSatish Balay       }
677ca161407SBarry Smith       ierr = MPI_Allreduce(&sum,norm,1,MPI_DOUBLE,MPI_SUM,mat->comm);CHKERRQ(ierr);
678d6de1c52SSatish Balay       *norm = sqrt(*norm);
679d64ed03dSBarry Smith     } else {
680e3372554SBarry Smith       SETERRQ(PETSC_ERR_SUP,0,"No support for this norm yet");
681d6de1c52SSatish Balay     }
682d64ed03dSBarry Smith   }
6833a40ed3dSBarry Smith   PetscFunctionReturn(0);
684d6de1c52SSatish Balay }
68557b952d6SSatish Balay 
686bd7f49f5SSatish Balay 
687fef45726SSatish Balay /*
688fef45726SSatish Balay   Creates the hash table, and sets the table
689fef45726SSatish Balay   This table is created only once.
690fef45726SSatish Balay   If new entried need to be added to the matrix
691fef45726SSatish Balay   then the hash table has to be destroyed and
692fef45726SSatish Balay   recreated.
693fef45726SSatish Balay */
694fef45726SSatish Balay #undef __FUNC__
695fef45726SSatish Balay #define __FUNC__ "MatCreateHashTable_MPIBAIJ_Private"
696d0a41580SSatish Balay int MatCreateHashTable_MPIBAIJ_Private(Mat mat,double factor)
697596b8d2eSBarry Smith {
698596b8d2eSBarry Smith   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
699596b8d2eSBarry Smith   Mat         A = baij->A, B=baij->B;
700596b8d2eSBarry Smith   Mat_SeqBAIJ *a=(Mat_SeqBAIJ *)A->data, *b=(Mat_SeqBAIJ *)B->data;
7010bdbc534SSatish Balay   int         i,j,k,nz=a->nz+b->nz,h1,*ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j;
7024a15367fSSatish Balay   int         size,bs2=baij->bs2,rstart=baij->rstart;
703187ce0cbSSatish Balay   int         cstart=baij->cstart,*garray=baij->garray,row,col,Nbs=baij->Nbs;
704fef45726SSatish Balay   int         *HT,key;
7050bdbc534SSatish Balay   Scalar      **HD;
706c2760754SSatish Balay   double      tmp;
7074a15367fSSatish Balay #if defined(USE_PETSC_BOPT_g)
7084a15367fSSatish Balay   int         ct=0,max=0;
7094a15367fSSatish Balay #endif
710fef45726SSatish Balay 
711d64ed03dSBarry Smith   PetscFunctionBegin;
7120bdbc534SSatish Balay   baij->ht_size=(int)(factor*nz);
7130bdbc534SSatish Balay   size = baij->ht_size;
714fef45726SSatish Balay 
7150bdbc534SSatish Balay   if (baij->ht) {
7160bdbc534SSatish Balay     PetscFunctionReturn(0);
717596b8d2eSBarry Smith   }
7180bdbc534SSatish Balay 
719fef45726SSatish Balay   /* Allocate Memory for Hash Table */
720b9e4cc15SSatish Balay   baij->hd = (Scalar**)PetscMalloc((size)*(sizeof(int)+sizeof(Scalar*))+1); CHKPTRQ(baij->hd);
721b9e4cc15SSatish Balay   baij->ht = (int*)(baij->hd + size);
722b9e4cc15SSatish Balay   HD = baij->hd;
723a07cd24cSSatish Balay   HT = baij->ht;
724b9e4cc15SSatish Balay 
725b9e4cc15SSatish Balay 
726c2760754SSatish Balay   PetscMemzero(HD,size*(sizeof(int)+sizeof(Scalar*)));
7270bdbc534SSatish Balay 
728596b8d2eSBarry Smith 
729596b8d2eSBarry Smith   /* Loop Over A */
7300bdbc534SSatish Balay   for ( i=0; i<a->mbs; i++ ) {
731596b8d2eSBarry Smith     for ( j=ai[i]; j<ai[i+1]; j++ ) {
7320bdbc534SSatish Balay       row = i+rstart;
7330bdbc534SSatish Balay       col = aj[j]+cstart;
734596b8d2eSBarry Smith 
735187ce0cbSSatish Balay       key = row*Nbs + col + 1;
736c2760754SSatish Balay       h1  = HASH(size,key,tmp);
7370bdbc534SSatish Balay       for ( k=0; k<size; k++ ){
7380bdbc534SSatish Balay         if (HT[(h1+k)%size] == 0.0) {
7390bdbc534SSatish Balay           HT[(h1+k)%size] = key;
7400bdbc534SSatish Balay           HD[(h1+k)%size] = a->a + j*bs2;
741596b8d2eSBarry Smith           break;
742187ce0cbSSatish Balay #if defined(USE_PETSC_BOPT_g)
743187ce0cbSSatish Balay         } else {
744187ce0cbSSatish Balay           ct++;
745187ce0cbSSatish Balay #endif
746596b8d2eSBarry Smith         }
747187ce0cbSSatish Balay       }
748187ce0cbSSatish Balay #if defined(USE_PETSC_BOPT_g)
749187ce0cbSSatish Balay       if (k> max) max = k;
750187ce0cbSSatish Balay #endif
751596b8d2eSBarry Smith     }
752596b8d2eSBarry Smith   }
753596b8d2eSBarry Smith   /* Loop Over B */
7540bdbc534SSatish Balay   for ( i=0; i<b->mbs; i++ ) {
755596b8d2eSBarry Smith     for ( j=bi[i]; j<bi[i+1]; j++ ) {
7560bdbc534SSatish Balay       row = i+rstart;
7570bdbc534SSatish Balay       col = garray[bj[j]];
758187ce0cbSSatish Balay       key = row*Nbs + col + 1;
759c2760754SSatish Balay       h1  = HASH(size,key,tmp);
7600bdbc534SSatish Balay       for ( k=0; k<size; k++ ){
7610bdbc534SSatish Balay         if (HT[(h1+k)%size] == 0.0) {
7620bdbc534SSatish Balay           HT[(h1+k)%size] = key;
7630bdbc534SSatish Balay           HD[(h1+k)%size] = b->a + j*bs2;
764596b8d2eSBarry Smith           break;
765187ce0cbSSatish Balay #if defined(USE_PETSC_BOPT_g)
766187ce0cbSSatish Balay         } else {
767187ce0cbSSatish Balay           ct++;
768187ce0cbSSatish Balay #endif
769596b8d2eSBarry Smith         }
770187ce0cbSSatish Balay       }
771187ce0cbSSatish Balay #if defined(USE_PETSC_BOPT_g)
772187ce0cbSSatish Balay       if (k> max) max = k;
773187ce0cbSSatish Balay #endif
774596b8d2eSBarry Smith     }
775596b8d2eSBarry Smith   }
776596b8d2eSBarry Smith 
777596b8d2eSBarry Smith   /* Print Summary */
778187ce0cbSSatish Balay #if defined(USE_PETSC_BOPT_g)
779c2760754SSatish Balay   for ( i=0,j=0; i<size; i++)
780596b8d2eSBarry Smith     if (HT[i]) {j++;}
781187ce0cbSSatish Balay   PLogInfo(0,"MatCreateHashTable_MPIBAIJ_Private: Average Search = %5.2f,max search = %d\n",
782187ce0cbSSatish Balay            (j== 0)? 0.0:((double)(ct+j))/j,max);
783187ce0cbSSatish Balay #endif
7843a40ed3dSBarry Smith   PetscFunctionReturn(0);
785596b8d2eSBarry Smith }
78657b952d6SSatish Balay 
787bbb85fb3SSatish Balay #undef __FUNC__
788bbb85fb3SSatish Balay #define __FUNC__ "MatAssemblyBegin_MPIBAIJ"
789bbb85fb3SSatish Balay int MatAssemblyBegin_MPIBAIJ(Mat mat,MatAssemblyType mode)
790bbb85fb3SSatish Balay {
791bbb85fb3SSatish Balay   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
792bbb85fb3SSatish Balay   int         ierr;
793bbb85fb3SSatish Balay   InsertMode  addv;
794bbb85fb3SSatish Balay 
795bbb85fb3SSatish Balay   PetscFunctionBegin;
796bbb85fb3SSatish Balay   if (baij->donotstash) {
797bbb85fb3SSatish Balay     PetscFunctionReturn(0);
798bbb85fb3SSatish Balay   }
799bbb85fb3SSatish Balay 
800bbb85fb3SSatish Balay   /* make sure all processors are either in INSERTMODE or ADDMODE */
801bbb85fb3SSatish Balay   ierr = MPI_Allreduce(&mat->insertmode,&addv,1,MPI_INT,MPI_BOR,mat->comm);CHKERRQ(ierr);
802bbb85fb3SSatish Balay   if (addv == (ADD_VALUES|INSERT_VALUES)) {
803bbb85fb3SSatish Balay     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"Some processors inserted others added");
804bbb85fb3SSatish Balay   }
805bbb85fb3SSatish Balay   mat->insertmode = addv; /* in case this processor had no cache */
806bbb85fb3SSatish Balay 
807bbb85fb3SSatish Balay   ierr =  StashScatterBegin_Private(&baij->stash,baij->rowners); CHKERRQ(ierr);
808a2d1c673SSatish Balay   ierr =  StashScatterBegin_Private(&baij->bstash,baij->rowners); CHKERRQ(ierr);
809bbb85fb3SSatish Balay 
810bbb85fb3SSatish Balay   /* Free cache space */
811bbb85fb3SSatish Balay   PLogInfo(baij->A,"MatAssemblyBegin_MPIBAIJ:Number of off-processor values %d\n",baij->stash.n);
812bbb85fb3SSatish Balay   PetscFunctionReturn(0);
813bbb85fb3SSatish Balay }
814bbb85fb3SSatish Balay 
815bbb85fb3SSatish Balay #undef __FUNC__
816bbb85fb3SSatish Balay #define __FUNC__ "MatAssemblyEnd_MPIBAIJ"
817bbb85fb3SSatish Balay int MatAssemblyEnd_MPIBAIJ(Mat mat,MatAssemblyType mode)
818bbb85fb3SSatish Balay {
819bbb85fb3SSatish Balay   Mat_MPIBAIJ *baij=(Mat_MPIBAIJ *) mat->data;
820a2d1c673SSatish Balay   Mat_SeqBAIJ *a=(Mat_SeqBAIJ*)baij->A->data,*b=(Mat_SeqBAIJ*)baij->B->data;
821a2d1c673SSatish Balay   int         i,j,rstart,ncols,n,ierr,flg,bs2=baij->bs2;
822a2d1c673SSatish Balay   int         *row,*col,other_disassembled,r1,r2,r3;
823bbb85fb3SSatish Balay   Scalar      *val;
824bbb85fb3SSatish Balay   InsertMode  addv = mat->insertmode;
825bbb85fb3SSatish Balay 
826bbb85fb3SSatish Balay   PetscFunctionBegin;
827bbb85fb3SSatish Balay   if (!baij->donotstash) {
828a2d1c673SSatish Balay     while (1) {
829a2d1c673SSatish Balay       ierr = StashScatterGetMesg_Private(&baij->stash,&n,&row,&col,&val,&flg); CHKERRQ(ierr);
830a2d1c673SSatish Balay       if (!flg) break;
831a2d1c673SSatish Balay 
832bbb85fb3SSatish Balay       for ( i=0; i<n; ) {
833bbb85fb3SSatish Balay         /* Now identify the consecutive vals belonging to the same row */
834bbb85fb3SSatish Balay         for ( j=i,rstart=row[j]; j<n; j++ ) { if (row[j] != rstart) break; }
835bbb85fb3SSatish Balay         if (j < n) ncols = j-i;
836bbb85fb3SSatish Balay         else       ncols = n-i;
837bbb85fb3SSatish Balay         /* Now assemble all these values with a single function call */
838bbb85fb3SSatish Balay         ierr = MatSetValues_MPIBAIJ(mat,1,row+i,ncols,col+i,val+i,addv); CHKERRQ(ierr);
839bbb85fb3SSatish Balay         i = j;
840bbb85fb3SSatish Balay       }
841bbb85fb3SSatish Balay     }
842a2d1c673SSatish Balay     ierr = StashScatterEnd_Private(&baij->stash); CHKERRQ(ierr);
843a2d1c673SSatish Balay     /* Now process the block-stash. Since the values are stashed column-oriented,
844a2d1c673SSatish Balay        set the roworiented flag to column oriented, and after MatSetValues()
845a2d1c673SSatish Balay        restore the original flags */
846a2d1c673SSatish Balay     r1 = baij->roworiented;
847a2d1c673SSatish Balay     r2 = a->roworiented;
848a2d1c673SSatish Balay     r3 = b->roworiented;
849a2d1c673SSatish Balay     baij->roworiented = 0;
850a2d1c673SSatish Balay     a->roworiented    = 0;
851a2d1c673SSatish Balay     b->roworiented    = 0;
852a2d1c673SSatish Balay     while (1) {
853a2d1c673SSatish Balay       ierr = StashScatterGetMesg_Private(&baij->bstash,&n,&row,&col,&val,&flg); CHKERRQ(ierr);
854a2d1c673SSatish Balay       if (!flg) break;
855a2d1c673SSatish Balay 
856a2d1c673SSatish Balay       for ( i=0; i<n; ) {
857a2d1c673SSatish Balay         /* Now identify the consecutive vals belonging to the same row */
858a2d1c673SSatish Balay         for ( j=i,rstart=row[j]; j<n; j++ ) { if (row[j] != rstart) break; }
859a2d1c673SSatish Balay         if (j < n) ncols = j-i;
860a2d1c673SSatish Balay         else       ncols = n-i;
861a2d1c673SSatish Balay         ierr = MatSetValuesBlocked_MPIBAIJ(mat,1,row+i,ncols,col+i,val+i*bs2,addv); CHKERRQ(ierr);
862a2d1c673SSatish Balay         i = j;
863a2d1c673SSatish Balay       }
864a2d1c673SSatish Balay     }
865a2d1c673SSatish Balay     ierr = StashScatterEnd_Private(&baij->bstash); CHKERRQ(ierr);
866a2d1c673SSatish Balay     baij->roworiented = r1;
867a2d1c673SSatish Balay     a->roworiented    = r2;
868a2d1c673SSatish Balay     b->roworiented    = r3;
869bbb85fb3SSatish Balay   }
870bbb85fb3SSatish Balay 
871bbb85fb3SSatish Balay   ierr = MatAssemblyBegin(baij->A,mode); CHKERRQ(ierr);
872bbb85fb3SSatish Balay   ierr = MatAssemblyEnd(baij->A,mode); CHKERRQ(ierr);
873bbb85fb3SSatish Balay 
874bbb85fb3SSatish Balay   /* determine if any processor has disassembled, if so we must
875bbb85fb3SSatish Balay      also disassemble ourselfs, in order that we may reassemble. */
876bbb85fb3SSatish Balay   /*
877bbb85fb3SSatish Balay      if nonzero structure of submatrix B cannot change then we know that
878bbb85fb3SSatish Balay      no processor disassembled thus we can skip this stuff
879bbb85fb3SSatish Balay   */
880bbb85fb3SSatish Balay   if (!((Mat_SeqBAIJ*) baij->B->data)->nonew)  {
881bbb85fb3SSatish Balay     ierr = MPI_Allreduce(&mat->was_assembled,&other_disassembled,1,MPI_INT,MPI_PROD,mat->comm);CHKERRQ(ierr);
882bbb85fb3SSatish Balay     if (mat->was_assembled && !other_disassembled) {
883bbb85fb3SSatish Balay       ierr = DisAssemble_MPIBAIJ(mat); CHKERRQ(ierr);
884bbb85fb3SSatish Balay     }
885bbb85fb3SSatish Balay   }
886bbb85fb3SSatish Balay 
887bbb85fb3SSatish Balay   if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) {
888bbb85fb3SSatish Balay     ierr = MatSetUpMultiply_MPIBAIJ(mat); CHKERRQ(ierr);
889bbb85fb3SSatish Balay   }
890bbb85fb3SSatish Balay   ierr = MatAssemblyBegin(baij->B,mode); CHKERRQ(ierr);
891bbb85fb3SSatish Balay   ierr = MatAssemblyEnd(baij->B,mode); CHKERRQ(ierr);
892bbb85fb3SSatish Balay 
893bbb85fb3SSatish Balay #if defined(USE_PETSC_BOPT_g)
894bbb85fb3SSatish Balay   if (baij->ht && mode== MAT_FINAL_ASSEMBLY) {
895bbb85fb3SSatish Balay     PLogInfo(0,"MatAssemblyEnd_MPIBAIJ:Average Hash Table Search in MatSetValues = %5.2f\n",
896bbb85fb3SSatish Balay              ((double)baij->ht_total_ct)/baij->ht_insert_ct);
897bbb85fb3SSatish Balay     baij->ht_total_ct  = 0;
898bbb85fb3SSatish Balay     baij->ht_insert_ct = 0;
899bbb85fb3SSatish Balay   }
900bbb85fb3SSatish Balay #endif
901bbb85fb3SSatish Balay   if (baij->ht_flag && !baij->ht && mode == MAT_FINAL_ASSEMBLY) {
902bbb85fb3SSatish Balay     ierr = MatCreateHashTable_MPIBAIJ_Private(mat,baij->ht_fact); CHKERRQ(ierr);
903bbb85fb3SSatish Balay     mat->ops->setvalues        = MatSetValues_MPIBAIJ_HT;
904bbb85fb3SSatish Balay     mat->ops->setvaluesblocked = MatSetValuesBlocked_MPIBAIJ_HT;
905bbb85fb3SSatish Balay   }
906bbb85fb3SSatish Balay 
907bbb85fb3SSatish Balay   if (baij->rowvalues) {PetscFree(baij->rowvalues); baij->rowvalues = 0;}
908bbb85fb3SSatish Balay   PetscFunctionReturn(0);
909bbb85fb3SSatish Balay }
91057b952d6SSatish Balay 
9115615d1e5SSatish Balay #undef __FUNC__
9125615d1e5SSatish Balay #define __FUNC__ "MatView_MPIBAIJ_Binary"
91357b952d6SSatish Balay static int MatView_MPIBAIJ_Binary(Mat mat,Viewer viewer)
91457b952d6SSatish Balay {
91557b952d6SSatish Balay   Mat_MPIBAIJ  *baij = (Mat_MPIBAIJ *) mat->data;
91657b952d6SSatish Balay   int          ierr;
91757b952d6SSatish Balay 
918d64ed03dSBarry Smith   PetscFunctionBegin;
91957b952d6SSatish Balay   if (baij->size == 1) {
92057b952d6SSatish Balay     ierr = MatView(baij->A,viewer); CHKERRQ(ierr);
921a8c6a408SBarry Smith   } else SETERRQ(PETSC_ERR_SUP,0,"Only uniprocessor output supported");
9223a40ed3dSBarry Smith   PetscFunctionReturn(0);
92357b952d6SSatish Balay }
92457b952d6SSatish Balay 
9255615d1e5SSatish Balay #undef __FUNC__
9267b2a1423SBarry Smith #define __FUNC__ "MatView_MPIBAIJ_ASCIIorDraworSocket"
9277b2a1423SBarry Smith static int MatView_MPIBAIJ_ASCIIorDraworSocket(Mat mat,Viewer viewer)
92857b952d6SSatish Balay {
92957b952d6SSatish Balay   Mat_MPIBAIJ  *baij = (Mat_MPIBAIJ *) mat->data;
93077ed5343SBarry Smith   int          ierr, format,bs = baij->bs, size = baij->size, rank = baij->rank;
93157b952d6SSatish Balay   FILE         *fd;
93257b952d6SSatish Balay   ViewerType   vtype;
93357b952d6SSatish Balay 
934d64ed03dSBarry Smith   PetscFunctionBegin;
93557b952d6SSatish Balay   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
9363f1db9ecSBarry Smith   if (PetscTypeCompare(vtype,ASCII_VIEWER)) {
937d41123aaSBarry Smith     ierr = ViewerGetFormat(viewer,&format); CHKERRQ(ierr);
938639f9d9dSBarry Smith     if (format == VIEWER_FORMAT_ASCII_INFO_LONG) {
9394e220ebcSLois Curfman McInnes       MatInfo info;
94057b952d6SSatish Balay       MPI_Comm_rank(mat->comm,&rank);
94157b952d6SSatish Balay       ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
942d41123aaSBarry Smith       ierr = MatGetInfo(mat,MAT_LOCAL,&info);CHKERRQ(ierr);
94357b952d6SSatish Balay       PetscSequentialPhaseBegin(mat->comm,1);
94457b952d6SSatish Balay       fprintf(fd,"[%d] Local rows %d nz %d nz alloced %d bs %d mem %d\n",
9454e220ebcSLois Curfman McInnes               rank,baij->m,(int)info.nz_used*bs,(int)info.nz_allocated*bs,
9464e220ebcSLois Curfman McInnes               baij->bs,(int)info.memory);
9474e220ebcSLois Curfman McInnes       ierr = MatGetInfo(baij->A,MAT_LOCAL,&info);
9484e220ebcSLois Curfman McInnes       fprintf(fd,"[%d] on-diagonal part: nz %d \n",rank,(int)info.nz_used*bs);
9494e220ebcSLois Curfman McInnes       ierr = MatGetInfo(baij->B,MAT_LOCAL,&info);
9504e220ebcSLois Curfman McInnes       fprintf(fd,"[%d] off-diagonal part: nz %d \n",rank,(int)info.nz_used*bs);
95157b952d6SSatish Balay       fflush(fd);
95257b952d6SSatish Balay       PetscSequentialPhaseEnd(mat->comm,1);
95357b952d6SSatish Balay       ierr = VecScatterView(baij->Mvctx,viewer); CHKERRQ(ierr);
9543a40ed3dSBarry Smith       PetscFunctionReturn(0);
955d64ed03dSBarry Smith     } else if (format == VIEWER_FORMAT_ASCII_INFO) {
956bcc3fcf6SBarry Smith       PetscPrintf(mat->comm,"  block size is %d\n",bs);
9573a40ed3dSBarry Smith       PetscFunctionReturn(0);
95857b952d6SSatish Balay     }
95957b952d6SSatish Balay   }
96057b952d6SSatish Balay 
9613f1db9ecSBarry Smith   if (PetscTypeCompare(vtype,DRAW_VIEWER)) {
96257b952d6SSatish Balay     Draw       draw;
96357b952d6SSatish Balay     PetscTruth isnull;
96477ed5343SBarry Smith     ierr = ViewerDrawGetDraw(viewer,0,&draw); CHKERRQ(ierr);
9653a40ed3dSBarry Smith     ierr = DrawIsNull(draw,&isnull); CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
96657b952d6SSatish Balay   }
96757b952d6SSatish Balay 
96857b952d6SSatish Balay   if (size == 1) {
96957b952d6SSatish Balay     ierr = MatView(baij->A,viewer); CHKERRQ(ierr);
970d64ed03dSBarry Smith   } else {
97157b952d6SSatish Balay     /* assemble the entire matrix onto first processor. */
97257b952d6SSatish Balay     Mat         A;
97357b952d6SSatish Balay     Mat_SeqBAIJ *Aloc;
97440011551SBarry Smith     int         M = baij->M, N = baij->N,*ai,*aj,col,i,j,k,*rvals;
97557b952d6SSatish Balay     int         mbs = baij->mbs;
97657b952d6SSatish Balay     Scalar      *a;
97757b952d6SSatish Balay 
97857b952d6SSatish Balay     if (!rank) {
97955843e3eSBarry Smith       ierr = MatCreateMPIBAIJ(mat->comm,baij->bs,M,N,M,N,0,PETSC_NULL,0,PETSC_NULL,&A);CHKERRQ(ierr);
980d64ed03dSBarry Smith     } else {
98155843e3eSBarry Smith       ierr = MatCreateMPIBAIJ(mat->comm,baij->bs,0,0,M,N,0,PETSC_NULL,0,PETSC_NULL,&A);CHKERRQ(ierr);
98257b952d6SSatish Balay     }
98357b952d6SSatish Balay     PLogObjectParent(mat,A);
98457b952d6SSatish Balay 
98557b952d6SSatish Balay     /* copy over the A part */
98657b952d6SSatish Balay     Aloc = (Mat_SeqBAIJ*) baij->A->data;
98757b952d6SSatish Balay     ai = Aloc->i; aj = Aloc->j; a = Aloc->a;
98857b952d6SSatish Balay     rvals = (int *) PetscMalloc(bs*sizeof(int)); CHKPTRQ(rvals);
98957b952d6SSatish Balay 
99057b952d6SSatish Balay     for ( i=0; i<mbs; i++ ) {
99157b952d6SSatish Balay       rvals[0] = bs*(baij->rstart + i);
99257b952d6SSatish Balay       for ( j=1; j<bs; j++ ) { rvals[j] = rvals[j-1] + 1; }
99357b952d6SSatish Balay       for ( j=ai[i]; j<ai[i+1]; j++ ) {
99457b952d6SSatish Balay         col = (baij->cstart+aj[j])*bs;
99557b952d6SSatish Balay         for (k=0; k<bs; k++ ) {
996cee3aa6bSSatish Balay           ierr = MatSetValues(A,bs,rvals,1,&col,a,INSERT_VALUES);CHKERRQ(ierr);
997cee3aa6bSSatish Balay           col++; a += bs;
99857b952d6SSatish Balay         }
99957b952d6SSatish Balay       }
100057b952d6SSatish Balay     }
100157b952d6SSatish Balay     /* copy over the B part */
100257b952d6SSatish Balay     Aloc = (Mat_SeqBAIJ*) baij->B->data;
100357b952d6SSatish Balay     ai = Aloc->i; aj = Aloc->j; a = Aloc->a;
100457b952d6SSatish Balay     for ( i=0; i<mbs; i++ ) {
100557b952d6SSatish Balay       rvals[0] = bs*(baij->rstart + i);
100657b952d6SSatish Balay       for ( j=1; j<bs; j++ ) { rvals[j] = rvals[j-1] + 1; }
100757b952d6SSatish Balay       for ( j=ai[i]; j<ai[i+1]; j++ ) {
100857b952d6SSatish Balay         col = baij->garray[aj[j]]*bs;
100957b952d6SSatish Balay         for (k=0; k<bs; k++ ) {
1010cee3aa6bSSatish Balay           ierr = MatSetValues(A,bs,rvals,1,&col,a,INSERT_VALUES);CHKERRQ(ierr);
1011cee3aa6bSSatish Balay           col++; a += bs;
101257b952d6SSatish Balay         }
101357b952d6SSatish Balay       }
101457b952d6SSatish Balay     }
101557b952d6SSatish Balay     PetscFree(rvals);
10166d4a8577SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
10176d4a8577SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
101855843e3eSBarry Smith     /*
101955843e3eSBarry Smith        Everyone has to call to draw the matrix since the graphics waits are
102055843e3eSBarry Smith        synchronized across all processors that share the Draw object
102155843e3eSBarry Smith     */
10223f1db9ecSBarry Smith     if (!rank || PetscTypeCompare(vtype,DRAW_VIEWER)) {
102357b952d6SSatish Balay       ierr = MatView(((Mat_MPIBAIJ*)(A->data))->A,viewer); CHKERRQ(ierr);
102457b952d6SSatish Balay     }
102557b952d6SSatish Balay     ierr = MatDestroy(A); CHKERRQ(ierr);
102657b952d6SSatish Balay   }
10273a40ed3dSBarry Smith   PetscFunctionReturn(0);
102857b952d6SSatish Balay }
102957b952d6SSatish Balay 
103057b952d6SSatish Balay 
103157b952d6SSatish Balay 
10325615d1e5SSatish Balay #undef __FUNC__
10335615d1e5SSatish Balay #define __FUNC__ "MatView_MPIBAIJ"
1034e1311b90SBarry Smith int MatView_MPIBAIJ(Mat mat,Viewer viewer)
103557b952d6SSatish Balay {
103657b952d6SSatish Balay   int         ierr;
103757b952d6SSatish Balay   ViewerType  vtype;
103857b952d6SSatish Balay 
1039d64ed03dSBarry Smith   PetscFunctionBegin;
104057b952d6SSatish Balay   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
10413f1db9ecSBarry Smith   if (PetscTypeCompare(vtype,ASCII_VIEWER) || PetscTypeCompare(vtype,DRAW_VIEWER) ||
10427b2a1423SBarry Smith       PetscTypeCompare(vtype,SOCKET_VIEWER)) {
10437b2a1423SBarry Smith     ierr = MatView_MPIBAIJ_ASCIIorDraworSocket(mat,viewer); CHKERRQ(ierr);
10443f1db9ecSBarry Smith   } else if (PetscTypeCompare(vtype,BINARY_VIEWER)) {
10453a40ed3dSBarry Smith     ierr = MatView_MPIBAIJ_Binary(mat,viewer);CHKERRQ(ierr);
10465cd90555SBarry Smith   } else {
10475cd90555SBarry Smith     SETERRQ(1,1,"Viewer type not supported by PETSc object");
104857b952d6SSatish Balay   }
10493a40ed3dSBarry Smith   PetscFunctionReturn(0);
105057b952d6SSatish Balay }
105157b952d6SSatish Balay 
10525615d1e5SSatish Balay #undef __FUNC__
10535615d1e5SSatish Balay #define __FUNC__ "MatDestroy_MPIBAIJ"
1054e1311b90SBarry Smith int MatDestroy_MPIBAIJ(Mat mat)
105579bdfe76SSatish Balay {
105679bdfe76SSatish Balay   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
105779bdfe76SSatish Balay   int         ierr;
105879bdfe76SSatish Balay 
1059d64ed03dSBarry Smith   PetscFunctionBegin;
106098dd23e9SBarry Smith   if (--mat->refct > 0) PetscFunctionReturn(0);
106198dd23e9SBarry Smith 
106298dd23e9SBarry Smith   if (mat->mapping) {
106398dd23e9SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->mapping); CHKERRQ(ierr);
106498dd23e9SBarry Smith   }
106598dd23e9SBarry Smith   if (mat->bmapping) {
106698dd23e9SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->bmapping); CHKERRQ(ierr);
106798dd23e9SBarry Smith   }
106861b13de0SBarry Smith   if (mat->rmap) {
106961b13de0SBarry Smith     ierr = MapDestroy(mat->rmap);CHKERRQ(ierr);
107061b13de0SBarry Smith   }
107161b13de0SBarry Smith   if (mat->cmap) {
107261b13de0SBarry Smith     ierr = MapDestroy(mat->cmap);CHKERRQ(ierr);
107361b13de0SBarry Smith   }
10743a40ed3dSBarry Smith #if defined(USE_PETSC_LOG)
1075e1311b90SBarry Smith   PLogObjectState((PetscObject)mat,"Rows=%d, Cols=%d",baij->M,baij->N);
107679bdfe76SSatish Balay #endif
107779bdfe76SSatish Balay 
107883e2fdc7SBarry Smith   ierr = StashDestroy_Private(&baij->stash); CHKERRQ(ierr);
1079a2d1c673SSatish Balay   ierr = StashDestroy_Private(&baij->bstash); CHKERRQ(ierr);
108079bdfe76SSatish Balay   PetscFree(baij->rowners);
108179bdfe76SSatish Balay   ierr = MatDestroy(baij->A); CHKERRQ(ierr);
108279bdfe76SSatish Balay   ierr = MatDestroy(baij->B); CHKERRQ(ierr);
108348e59246SSatish Balay #if defined (USE_CTABLE)
108448e59246SSatish Balay   if (baij->colmap) TableDelete(baij->colmap);
108548e59246SSatish Balay #else
108679bdfe76SSatish Balay   if (baij->colmap) PetscFree(baij->colmap);
108748e59246SSatish Balay #endif
108879bdfe76SSatish Balay   if (baij->garray) PetscFree(baij->garray);
108979bdfe76SSatish Balay   if (baij->lvec)   VecDestroy(baij->lvec);
109079bdfe76SSatish Balay   if (baij->Mvctx)  VecScatterDestroy(baij->Mvctx);
109179bdfe76SSatish Balay   if (baij->rowvalues) PetscFree(baij->rowvalues);
109230793edcSSatish Balay   if (baij->barray) PetscFree(baij->barray);
1093b9e4cc15SSatish Balay   if (baij->hd) PetscFree(baij->hd);
109479bdfe76SSatish Balay   PetscFree(baij);
109579bdfe76SSatish Balay   PLogObjectDestroy(mat);
109679bdfe76SSatish Balay   PetscHeaderDestroy(mat);
10973a40ed3dSBarry Smith   PetscFunctionReturn(0);
109879bdfe76SSatish Balay }
109979bdfe76SSatish Balay 
11005615d1e5SSatish Balay #undef __FUNC__
11015615d1e5SSatish Balay #define __FUNC__ "MatMult_MPIBAIJ"
1102ec1ea8d8SLois Curfman McInnes int MatMult_MPIBAIJ(Mat A,Vec xx,Vec yy)
1103cee3aa6bSSatish Balay {
1104cee3aa6bSSatish Balay   Mat_MPIBAIJ *a = (Mat_MPIBAIJ *) A->data;
110547b4a8eaSLois Curfman McInnes   int         ierr, nt;
1106cee3aa6bSSatish Balay 
1107d64ed03dSBarry Smith   PetscFunctionBegin;
1108e1311b90SBarry Smith   ierr = VecGetLocalSize(xx,&nt);CHKERRQ(ierr);
110947b4a8eaSLois Curfman McInnes   if (nt != a->n) {
1110a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_SIZ,0,"Incompatible partition of A and xx");
111147b4a8eaSLois Curfman McInnes   }
1112e1311b90SBarry Smith   ierr = VecGetLocalSize(yy,&nt);CHKERRQ(ierr);
111347b4a8eaSLois Curfman McInnes   if (nt != a->m) {
1114a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_SIZ,0,"Incompatible parition of A and yy");
111547b4a8eaSLois Curfman McInnes   }
111643a90d84SBarry Smith   ierr = VecScatterBegin(xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD,a->Mvctx);CHKERRQ(ierr);
1117f830108cSBarry Smith   ierr = (*a->A->ops->mult)(a->A,xx,yy); CHKERRQ(ierr);
111843a90d84SBarry Smith   ierr = VecScatterEnd(xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD,a->Mvctx);CHKERRQ(ierr);
1119f830108cSBarry Smith   ierr = (*a->B->ops->multadd)(a->B,a->lvec,yy,yy); CHKERRQ(ierr);
112043a90d84SBarry Smith   ierr = VecScatterPostRecvs(xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD,a->Mvctx);CHKERRQ(ierr);
11213a40ed3dSBarry Smith   PetscFunctionReturn(0);
1122cee3aa6bSSatish Balay }
1123cee3aa6bSSatish Balay 
11245615d1e5SSatish Balay #undef __FUNC__
11255615d1e5SSatish Balay #define __FUNC__ "MatMultAdd_MPIBAIJ"
1126ec1ea8d8SLois Curfman McInnes int MatMultAdd_MPIBAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1127cee3aa6bSSatish Balay {
1128cee3aa6bSSatish Balay   Mat_MPIBAIJ *a = (Mat_MPIBAIJ *) A->data;
1129cee3aa6bSSatish Balay   int        ierr;
1130d64ed03dSBarry Smith 
1131d64ed03dSBarry Smith   PetscFunctionBegin;
113243a90d84SBarry Smith   ierr = VecScatterBegin(xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD,a->Mvctx);CHKERRQ(ierr);
1133f830108cSBarry Smith   ierr = (*a->A->ops->multadd)(a->A,xx,yy,zz); CHKERRQ(ierr);
113443a90d84SBarry Smith   ierr = VecScatterEnd(xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD,a->Mvctx);CHKERRQ(ierr);
1135f830108cSBarry Smith   ierr = (*a->B->ops->multadd)(a->B,a->lvec,zz,zz); CHKERRQ(ierr);
11363a40ed3dSBarry Smith   PetscFunctionReturn(0);
1137cee3aa6bSSatish Balay }
1138cee3aa6bSSatish Balay 
11395615d1e5SSatish Balay #undef __FUNC__
11405615d1e5SSatish Balay #define __FUNC__ "MatMultTrans_MPIBAIJ"
1141ec1ea8d8SLois Curfman McInnes int MatMultTrans_MPIBAIJ(Mat A,Vec xx,Vec yy)
1142cee3aa6bSSatish Balay {
1143cee3aa6bSSatish Balay   Mat_MPIBAIJ *a = (Mat_MPIBAIJ *) A->data;
1144cee3aa6bSSatish Balay   int         ierr;
1145cee3aa6bSSatish Balay 
1146d64ed03dSBarry Smith   PetscFunctionBegin;
1147cee3aa6bSSatish Balay   /* do nondiagonal part */
1148f830108cSBarry Smith   ierr = (*a->B->ops->multtrans)(a->B,xx,a->lvec); CHKERRQ(ierr);
1149cee3aa6bSSatish Balay   /* send it on its way */
1150537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx);CHKERRQ(ierr);
1151cee3aa6bSSatish Balay   /* do local part */
1152f830108cSBarry Smith   ierr = (*a->A->ops->multtrans)(a->A,xx,yy); CHKERRQ(ierr);
1153cee3aa6bSSatish Balay   /* receive remote parts: note this assumes the values are not actually */
1154cee3aa6bSSatish Balay   /* inserted in yy until the next line, which is true for my implementation*/
1155cee3aa6bSSatish Balay   /* but is not perhaps always true. */
1156639f9d9dSBarry Smith   ierr = VecScatterEnd(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx);CHKERRQ(ierr);
11573a40ed3dSBarry Smith   PetscFunctionReturn(0);
1158cee3aa6bSSatish Balay }
1159cee3aa6bSSatish Balay 
11605615d1e5SSatish Balay #undef __FUNC__
11615615d1e5SSatish Balay #define __FUNC__ "MatMultTransAdd_MPIBAIJ"
1162ec1ea8d8SLois Curfman McInnes int MatMultTransAdd_MPIBAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1163cee3aa6bSSatish Balay {
1164cee3aa6bSSatish Balay   Mat_MPIBAIJ *a = (Mat_MPIBAIJ *) A->data;
1165cee3aa6bSSatish Balay   int         ierr;
1166cee3aa6bSSatish Balay 
1167d64ed03dSBarry Smith   PetscFunctionBegin;
1168cee3aa6bSSatish Balay   /* do nondiagonal part */
1169f830108cSBarry Smith   ierr = (*a->B->ops->multtrans)(a->B,xx,a->lvec); CHKERRQ(ierr);
1170cee3aa6bSSatish Balay   /* send it on its way */
1171537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
1172cee3aa6bSSatish Balay   /* do local part */
1173f830108cSBarry Smith   ierr = (*a->A->ops->multtransadd)(a->A,xx,yy,zz); CHKERRQ(ierr);
1174cee3aa6bSSatish Balay   /* receive remote parts: note this assumes the values are not actually */
1175cee3aa6bSSatish Balay   /* inserted in yy until the next line, which is true for my implementation*/
1176cee3aa6bSSatish Balay   /* but is not perhaps always true. */
1177537820f0SBarry Smith   ierr = VecScatterEnd(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
11783a40ed3dSBarry Smith   PetscFunctionReturn(0);
1179cee3aa6bSSatish Balay }
1180cee3aa6bSSatish Balay 
1181cee3aa6bSSatish Balay /*
1182cee3aa6bSSatish Balay   This only works correctly for square matrices where the subblock A->A is the
1183cee3aa6bSSatish Balay    diagonal block
1184cee3aa6bSSatish Balay */
11855615d1e5SSatish Balay #undef __FUNC__
11865615d1e5SSatish Balay #define __FUNC__ "MatGetDiagonal_MPIBAIJ"
1187ec1ea8d8SLois Curfman McInnes int MatGetDiagonal_MPIBAIJ(Mat A,Vec v)
1188cee3aa6bSSatish Balay {
1189cee3aa6bSSatish Balay   Mat_MPIBAIJ *a = (Mat_MPIBAIJ *) A->data;
11903a40ed3dSBarry Smith   int         ierr;
1191d64ed03dSBarry Smith 
1192d64ed03dSBarry Smith   PetscFunctionBegin;
1193a8c6a408SBarry Smith   if (a->M != a->N) SETERRQ(PETSC_ERR_SUP,0,"Supports only square matrix where A->A is diag block");
11943a40ed3dSBarry Smith   ierr = MatGetDiagonal(a->A,v);CHKERRQ(ierr);
11953a40ed3dSBarry Smith   PetscFunctionReturn(0);
1196cee3aa6bSSatish Balay }
1197cee3aa6bSSatish Balay 
11985615d1e5SSatish Balay #undef __FUNC__
11995615d1e5SSatish Balay #define __FUNC__ "MatScale_MPIBAIJ"
1200ec1ea8d8SLois Curfman McInnes int MatScale_MPIBAIJ(Scalar *aa,Mat A)
1201cee3aa6bSSatish Balay {
1202cee3aa6bSSatish Balay   Mat_MPIBAIJ *a = (Mat_MPIBAIJ *) A->data;
1203cee3aa6bSSatish Balay   int         ierr;
1204d64ed03dSBarry Smith 
1205d64ed03dSBarry Smith   PetscFunctionBegin;
1206cee3aa6bSSatish Balay   ierr = MatScale(aa,a->A); CHKERRQ(ierr);
1207cee3aa6bSSatish Balay   ierr = MatScale(aa,a->B); CHKERRQ(ierr);
12083a40ed3dSBarry Smith   PetscFunctionReturn(0);
1209cee3aa6bSSatish Balay }
1210026e39d0SSatish Balay 
12115615d1e5SSatish Balay #undef __FUNC__
12125615d1e5SSatish Balay #define __FUNC__ "MatGetSize_MPIBAIJ"
1213ec1ea8d8SLois Curfman McInnes int MatGetSize_MPIBAIJ(Mat matin,int *m,int *n)
121457b952d6SSatish Balay {
121557b952d6SSatish Balay   Mat_MPIBAIJ *mat = (Mat_MPIBAIJ *) matin->data;
1216d64ed03dSBarry Smith 
1217d64ed03dSBarry Smith   PetscFunctionBegin;
1218bd7f49f5SSatish Balay   if (m) *m = mat->M;
1219bd7f49f5SSatish Balay   if (n) *n = mat->N;
12203a40ed3dSBarry Smith   PetscFunctionReturn(0);
122157b952d6SSatish Balay }
122257b952d6SSatish Balay 
12235615d1e5SSatish Balay #undef __FUNC__
12245615d1e5SSatish Balay #define __FUNC__ "MatGetLocalSize_MPIBAIJ"
1225ec1ea8d8SLois Curfman McInnes int MatGetLocalSize_MPIBAIJ(Mat matin,int *m,int *n)
122657b952d6SSatish Balay {
122757b952d6SSatish Balay   Mat_MPIBAIJ *mat = (Mat_MPIBAIJ *) matin->data;
1228d64ed03dSBarry Smith 
1229d64ed03dSBarry Smith   PetscFunctionBegin;
1230f830108cSBarry Smith   *m = mat->m; *n = mat->n;
12313a40ed3dSBarry Smith   PetscFunctionReturn(0);
123257b952d6SSatish Balay }
123357b952d6SSatish Balay 
12345615d1e5SSatish Balay #undef __FUNC__
12355615d1e5SSatish Balay #define __FUNC__ "MatGetOwnershipRange_MPIBAIJ"
1236ec1ea8d8SLois Curfman McInnes int MatGetOwnershipRange_MPIBAIJ(Mat matin,int *m,int *n)
123757b952d6SSatish Balay {
123857b952d6SSatish Balay   Mat_MPIBAIJ *mat = (Mat_MPIBAIJ *) matin->data;
1239d64ed03dSBarry Smith 
1240d64ed03dSBarry Smith   PetscFunctionBegin;
124157b952d6SSatish Balay   *m = mat->rstart*mat->bs; *n = mat->rend*mat->bs;
12423a40ed3dSBarry Smith   PetscFunctionReturn(0);
124357b952d6SSatish Balay }
124457b952d6SSatish Balay 
12455615d1e5SSatish Balay #undef __FUNC__
12465615d1e5SSatish Balay #define __FUNC__ "MatGetRow_MPIBAIJ"
1247acdf5bf4SSatish Balay int MatGetRow_MPIBAIJ(Mat matin,int row,int *nz,int **idx,Scalar **v)
1248acdf5bf4SSatish Balay {
1249acdf5bf4SSatish Balay   Mat_MPIBAIJ *mat = (Mat_MPIBAIJ *) matin->data;
1250acdf5bf4SSatish Balay   Scalar     *vworkA, *vworkB, **pvA, **pvB,*v_p;
1251acdf5bf4SSatish Balay   int        bs = mat->bs, bs2 = mat->bs2, i, ierr, *cworkA, *cworkB, **pcA, **pcB;
1252d9d09a02SSatish Balay   int        nztot, nzA, nzB, lrow, brstart = mat->rstart*bs, brend = mat->rend*bs;
1253d9d09a02SSatish Balay   int        *cmap, *idx_p,cstart = mat->cstart;
1254acdf5bf4SSatish Balay 
1255d64ed03dSBarry Smith   PetscFunctionBegin;
1256a8c6a408SBarry Smith   if (mat->getrowactive == PETSC_TRUE) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"Already active");
1257acdf5bf4SSatish Balay   mat->getrowactive = PETSC_TRUE;
1258acdf5bf4SSatish Balay 
1259acdf5bf4SSatish Balay   if (!mat->rowvalues && (idx || v)) {
1260acdf5bf4SSatish Balay     /*
1261acdf5bf4SSatish Balay         allocate enough space to hold information from the longest row.
1262acdf5bf4SSatish Balay     */
1263acdf5bf4SSatish Balay     Mat_SeqBAIJ *Aa = (Mat_SeqBAIJ *) mat->A->data,*Ba = (Mat_SeqBAIJ *) mat->B->data;
1264bd16c2feSSatish Balay     int     max = 1,mbs = mat->mbs,tmp;
1265bd16c2feSSatish Balay     for ( i=0; i<mbs; i++ ) {
1266acdf5bf4SSatish Balay       tmp = Aa->i[i+1] - Aa->i[i] + Ba->i[i+1] - Ba->i[i];
1267acdf5bf4SSatish Balay       if (max < tmp) { max = tmp; }
1268acdf5bf4SSatish Balay     }
1269acdf5bf4SSatish Balay     mat->rowvalues = (Scalar *) PetscMalloc( max*bs2*(sizeof(int)+sizeof(Scalar)));
1270acdf5bf4SSatish Balay     CHKPTRQ(mat->rowvalues);
1271acdf5bf4SSatish Balay     mat->rowindices = (int *) (mat->rowvalues + max*bs2);
1272acdf5bf4SSatish Balay   }
1273acdf5bf4SSatish Balay 
1274a8c6a408SBarry Smith   if (row < brstart || row >= brend) SETERRQ(PETSC_ERR_SUP,0,"Only local rows")
1275d9d09a02SSatish Balay   lrow = row - brstart;
1276acdf5bf4SSatish Balay 
1277acdf5bf4SSatish Balay   pvA = &vworkA; pcA = &cworkA; pvB = &vworkB; pcB = &cworkB;
1278acdf5bf4SSatish Balay   if (!v)   {pvA = 0; pvB = 0;}
1279acdf5bf4SSatish Balay   if (!idx) {pcA = 0; if (!v) pcB = 0;}
1280f830108cSBarry Smith   ierr = (*mat->A->ops->getrow)(mat->A,lrow,&nzA,pcA,pvA); CHKERRQ(ierr);
1281f830108cSBarry Smith   ierr = (*mat->B->ops->getrow)(mat->B,lrow,&nzB,pcB,pvB); CHKERRQ(ierr);
1282acdf5bf4SSatish Balay   nztot = nzA + nzB;
1283acdf5bf4SSatish Balay 
1284acdf5bf4SSatish Balay   cmap  = mat->garray;
1285acdf5bf4SSatish Balay   if (v  || idx) {
1286acdf5bf4SSatish Balay     if (nztot) {
1287acdf5bf4SSatish Balay       /* Sort by increasing column numbers, assuming A and B already sorted */
1288acdf5bf4SSatish Balay       int imark = -1;
1289acdf5bf4SSatish Balay       if (v) {
1290acdf5bf4SSatish Balay         *v = v_p = mat->rowvalues;
1291acdf5bf4SSatish Balay         for ( i=0; i<nzB; i++ ) {
1292d9d09a02SSatish Balay           if (cmap[cworkB[i]/bs] < cstart)   v_p[i] = vworkB[i];
1293acdf5bf4SSatish Balay           else break;
1294acdf5bf4SSatish Balay         }
1295acdf5bf4SSatish Balay         imark = i;
1296acdf5bf4SSatish Balay         for ( i=0; i<nzA; i++ )     v_p[imark+i] = vworkA[i];
1297acdf5bf4SSatish Balay         for ( i=imark; i<nzB; i++ ) v_p[nzA+i]   = vworkB[i];
1298acdf5bf4SSatish Balay       }
1299acdf5bf4SSatish Balay       if (idx) {
1300acdf5bf4SSatish Balay         *idx = idx_p = mat->rowindices;
1301acdf5bf4SSatish Balay         if (imark > -1) {
1302acdf5bf4SSatish Balay           for ( i=0; i<imark; i++ ) {
1303bd16c2feSSatish Balay             idx_p[i] = cmap[cworkB[i]/bs]*bs + cworkB[i]%bs;
1304acdf5bf4SSatish Balay           }
1305acdf5bf4SSatish Balay         } else {
1306acdf5bf4SSatish Balay           for ( i=0; i<nzB; i++ ) {
1307d9d09a02SSatish Balay             if (cmap[cworkB[i]/bs] < cstart)
1308d9d09a02SSatish Balay               idx_p[i] = cmap[cworkB[i]/bs]*bs + cworkB[i]%bs ;
1309acdf5bf4SSatish Balay             else break;
1310acdf5bf4SSatish Balay           }
1311acdf5bf4SSatish Balay           imark = i;
1312acdf5bf4SSatish Balay         }
1313d9d09a02SSatish Balay         for ( i=0; i<nzA; i++ )     idx_p[imark+i] = cstart*bs + cworkA[i];
1314d9d09a02SSatish Balay         for ( i=imark; i<nzB; i++ ) idx_p[nzA+i]   = cmap[cworkB[i]/bs]*bs + cworkB[i]%bs ;
1315acdf5bf4SSatish Balay       }
1316d64ed03dSBarry Smith     } else {
1317d212a18eSSatish Balay       if (idx) *idx = 0;
1318d212a18eSSatish Balay       if (v)   *v   = 0;
1319d212a18eSSatish Balay     }
1320acdf5bf4SSatish Balay   }
1321acdf5bf4SSatish Balay   *nz = nztot;
1322f830108cSBarry Smith   ierr = (*mat->A->ops->restorerow)(mat->A,lrow,&nzA,pcA,pvA); CHKERRQ(ierr);
1323f830108cSBarry Smith   ierr = (*mat->B->ops->restorerow)(mat->B,lrow,&nzB,pcB,pvB); CHKERRQ(ierr);
13243a40ed3dSBarry Smith   PetscFunctionReturn(0);
1325acdf5bf4SSatish Balay }
1326acdf5bf4SSatish Balay 
13275615d1e5SSatish Balay #undef __FUNC__
13285615d1e5SSatish Balay #define __FUNC__ "MatRestoreRow_MPIBAIJ"
1329acdf5bf4SSatish Balay int MatRestoreRow_MPIBAIJ(Mat mat,int row,int *nz,int **idx,Scalar **v)
1330acdf5bf4SSatish Balay {
1331acdf5bf4SSatish Balay   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
1332d64ed03dSBarry Smith 
1333d64ed03dSBarry Smith   PetscFunctionBegin;
1334acdf5bf4SSatish Balay   if (baij->getrowactive == PETSC_FALSE) {
1335a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"MatGetRow not called");
1336acdf5bf4SSatish Balay   }
1337acdf5bf4SSatish Balay   baij->getrowactive = PETSC_FALSE;
13383a40ed3dSBarry Smith   PetscFunctionReturn(0);
1339acdf5bf4SSatish Balay }
1340acdf5bf4SSatish Balay 
13415615d1e5SSatish Balay #undef __FUNC__
13425615d1e5SSatish Balay #define __FUNC__ "MatGetBlockSize_MPIBAIJ"
1343ec1ea8d8SLois Curfman McInnes int MatGetBlockSize_MPIBAIJ(Mat mat,int *bs)
13445a838052SSatish Balay {
13455a838052SSatish Balay   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) mat->data;
1346d64ed03dSBarry Smith 
1347d64ed03dSBarry Smith   PetscFunctionBegin;
13485a838052SSatish Balay   *bs = baij->bs;
13493a40ed3dSBarry Smith   PetscFunctionReturn(0);
13505a838052SSatish Balay }
13515a838052SSatish Balay 
13525615d1e5SSatish Balay #undef __FUNC__
13535615d1e5SSatish Balay #define __FUNC__ "MatZeroEntries_MPIBAIJ"
1354ec1ea8d8SLois Curfman McInnes int MatZeroEntries_MPIBAIJ(Mat A)
135558667388SSatish Balay {
135658667388SSatish Balay   Mat_MPIBAIJ *l = (Mat_MPIBAIJ *) A->data;
135758667388SSatish Balay   int         ierr;
1358d64ed03dSBarry Smith 
1359d64ed03dSBarry Smith   PetscFunctionBegin;
136058667388SSatish Balay   ierr = MatZeroEntries(l->A); CHKERRQ(ierr);
136158667388SSatish Balay   ierr = MatZeroEntries(l->B); CHKERRQ(ierr);
13623a40ed3dSBarry Smith   PetscFunctionReturn(0);
136358667388SSatish Balay }
13640ac07820SSatish Balay 
13655615d1e5SSatish Balay #undef __FUNC__
13665615d1e5SSatish Balay #define __FUNC__ "MatGetInfo_MPIBAIJ"
1367ec1ea8d8SLois Curfman McInnes int MatGetInfo_MPIBAIJ(Mat matin,MatInfoType flag,MatInfo *info)
13680ac07820SSatish Balay {
13694e220ebcSLois Curfman McInnes   Mat_MPIBAIJ *a = (Mat_MPIBAIJ *) matin->data;
13704e220ebcSLois Curfman McInnes   Mat         A = a->A, B = a->B;
13717d57db60SLois Curfman McInnes   int         ierr;
13727d57db60SLois Curfman McInnes   double      isend[5], irecv[5];
13730ac07820SSatish Balay 
1374d64ed03dSBarry Smith   PetscFunctionBegin;
13754e220ebcSLois Curfman McInnes   info->block_size     = (double)a->bs;
13764e220ebcSLois Curfman McInnes   ierr = MatGetInfo(A,MAT_LOCAL,info); CHKERRQ(ierr);
13770e4b21beSBarry Smith   isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded;
1378de87f314SBarry Smith   isend[3] = info->memory;  isend[4] = info->mallocs;
13794e220ebcSLois Curfman McInnes   ierr = MatGetInfo(B,MAT_LOCAL,info); CHKERRQ(ierr);
13800e4b21beSBarry Smith   isend[0] += info->nz_used; isend[1] += info->nz_allocated; isend[2] += info->nz_unneeded;
1381de87f314SBarry Smith   isend[3] += info->memory;  isend[4] += info->mallocs;
13820ac07820SSatish Balay   if (flag == MAT_LOCAL) {
13834e220ebcSLois Curfman McInnes     info->nz_used      = isend[0];
13844e220ebcSLois Curfman McInnes     info->nz_allocated = isend[1];
13854e220ebcSLois Curfman McInnes     info->nz_unneeded  = isend[2];
13864e220ebcSLois Curfman McInnes     info->memory       = isend[3];
13874e220ebcSLois Curfman McInnes     info->mallocs      = isend[4];
13880ac07820SSatish Balay   } else if (flag == MAT_GLOBAL_MAX) {
1389f7cdd7c9SBarry Smith     ierr = MPI_Allreduce(isend,irecv,5,MPI_DOUBLE,MPI_MAX,matin->comm);CHKERRQ(ierr);
13904e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
13914e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
13924e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
13934e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
13944e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
13950ac07820SSatish Balay   } else if (flag == MAT_GLOBAL_SUM) {
1396f7cdd7c9SBarry Smith     ierr = MPI_Allreduce(isend,irecv,5,MPI_DOUBLE,MPI_SUM,matin->comm);CHKERRQ(ierr);
13974e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
13984e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
13994e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
14004e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
14014e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
1402d41123aaSBarry Smith   } else {
1403d41123aaSBarry Smith     SETERRQ1(1,1,"Unknown MatInfoType argument %d",flag);
14040ac07820SSatish Balay   }
14055a5d4f66SBarry Smith   info->rows_global       = (double)a->M;
14065a5d4f66SBarry Smith   info->columns_global    = (double)a->N;
14075a5d4f66SBarry Smith   info->rows_local        = (double)a->m;
14085a5d4f66SBarry Smith   info->columns_local     = (double)a->N;
14094e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0; /* no parallel LU/ILU/Cholesky */
14104e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
14114e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
14123a40ed3dSBarry Smith   PetscFunctionReturn(0);
14130ac07820SSatish Balay }
14140ac07820SSatish Balay 
14155615d1e5SSatish Balay #undef __FUNC__
14165615d1e5SSatish Balay #define __FUNC__ "MatSetOption_MPIBAIJ"
1417ec1ea8d8SLois Curfman McInnes int MatSetOption_MPIBAIJ(Mat A,MatOption op)
141858667388SSatish Balay {
141958667388SSatish Balay   Mat_MPIBAIJ *a = (Mat_MPIBAIJ *) A->data;
142098305bb5SBarry Smith   int         ierr;
142158667388SSatish Balay 
1422d64ed03dSBarry Smith   PetscFunctionBegin;
142358667388SSatish Balay   if (op == MAT_NO_NEW_NONZERO_LOCATIONS ||
142458667388SSatish Balay       op == MAT_YES_NEW_NONZERO_LOCATIONS ||
14256da5968aSLois Curfman McInnes       op == MAT_COLUMNS_UNSORTED ||
1426c2653b3dSLois Curfman McInnes       op == MAT_COLUMNS_SORTED ||
14274787f768SSatish Balay       op == MAT_NEW_NONZERO_ALLOCATION_ERR ||
14284787f768SSatish Balay       op == MAT_NEW_NONZERO_LOCATION_ERR) {
142998305bb5SBarry Smith         ierr = MatSetOption(a->A,op);CHKERRQ(ierr);
143098305bb5SBarry Smith         ierr = MatSetOption(a->B,op);CHKERRQ(ierr);
1431b1fbbac0SLois Curfman McInnes   } else if (op == MAT_ROW_ORIENTED) {
1432aeafbbfcSLois Curfman McInnes         a->roworiented = 1;
143398305bb5SBarry Smith         ierr = MatSetOption(a->A,op);CHKERRQ(ierr);
143498305bb5SBarry Smith         ierr = MatSetOption(a->B,op);CHKERRQ(ierr);
1435b1fbbac0SLois Curfman McInnes   } else if (op == MAT_ROWS_SORTED ||
14366da5968aSLois Curfman McInnes              op == MAT_ROWS_UNSORTED ||
143758667388SSatish Balay              op == MAT_SYMMETRIC ||
143858667388SSatish Balay              op == MAT_STRUCTURALLY_SYMMETRIC ||
1439b51ba29fSSatish Balay              op == MAT_YES_NEW_DIAGONALS ||
144098305bb5SBarry Smith              op == MAT_USE_HASH_TABLE) {
144158667388SSatish Balay     PLogInfo(A,"Info:MatSetOption_MPIBAIJ:Option ignored\n");
144298305bb5SBarry Smith   } else if (op == MAT_COLUMN_ORIENTED) {
144358667388SSatish Balay     a->roworiented = 0;
144498305bb5SBarry Smith     ierr = MatSetOption(a->A,op);CHKERRQ(ierr);
144598305bb5SBarry Smith     ierr = MatSetOption(a->B,op);CHKERRQ(ierr);
14462b362799SSatish Balay   } else if (op == MAT_IGNORE_OFF_PROC_ENTRIES) {
144790f02eecSBarry Smith     a->donotstash = 1;
1448d64ed03dSBarry Smith   } else if (op == MAT_NO_NEW_DIAGONALS) {
1449d64ed03dSBarry Smith     SETERRQ(PETSC_ERR_SUP,0,"MAT_NO_NEW_DIAGONALS");
1450133cdb44SSatish Balay   } else if (op == MAT_USE_HASH_TABLE) {
1451133cdb44SSatish Balay     a->ht_flag = 1;
1452d64ed03dSBarry Smith   } else {
1453d64ed03dSBarry Smith     SETERRQ(PETSC_ERR_SUP,0,"unknown option");
1454d64ed03dSBarry Smith   }
14553a40ed3dSBarry Smith   PetscFunctionReturn(0);
145658667388SSatish Balay }
145758667388SSatish Balay 
14585615d1e5SSatish Balay #undef __FUNC__
14595615d1e5SSatish Balay #define __FUNC__ "MatTranspose_MPIBAIJ("
1460ec1ea8d8SLois Curfman McInnes int MatTranspose_MPIBAIJ(Mat A,Mat *matout)
14610ac07820SSatish Balay {
14620ac07820SSatish Balay   Mat_MPIBAIJ *baij = (Mat_MPIBAIJ *) A->data;
14630ac07820SSatish Balay   Mat_SeqBAIJ *Aloc;
14640ac07820SSatish Balay   Mat        B;
146540011551SBarry Smith   int        ierr,M=baij->M,N=baij->N,*ai,*aj,i,*rvals,j,k,col;
14660ac07820SSatish Balay   int        bs=baij->bs,mbs=baij->mbs;
14670ac07820SSatish Balay   Scalar     *a;
14680ac07820SSatish Balay 
1469d64ed03dSBarry Smith   PetscFunctionBegin;
1470a8c6a408SBarry Smith   if (matout == PETSC_NULL && M != N) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Square matrix only for in-place");
147128937c7bSBarry Smith   ierr = MatCreateMPIBAIJ(A->comm,baij->bs,baij->n,baij->m,N,M,0,PETSC_NULL,0,PETSC_NULL,&B);
14720ac07820SSatish Balay   CHKERRQ(ierr);
14730ac07820SSatish Balay 
14740ac07820SSatish Balay   /* copy over the A part */
14750ac07820SSatish Balay   Aloc = (Mat_SeqBAIJ*) baij->A->data;
14760ac07820SSatish Balay   ai = Aloc->i; aj = Aloc->j; a = Aloc->a;
14770ac07820SSatish Balay   rvals = (int *) PetscMalloc(bs*sizeof(int)); CHKPTRQ(rvals);
14780ac07820SSatish Balay 
14790ac07820SSatish Balay   for ( i=0; i<mbs; i++ ) {
14800ac07820SSatish Balay     rvals[0] = bs*(baij->rstart + i);
14810ac07820SSatish Balay     for ( j=1; j<bs; j++ ) { rvals[j] = rvals[j-1] + 1; }
14820ac07820SSatish Balay     for ( j=ai[i]; j<ai[i+1]; j++ ) {
14830ac07820SSatish Balay       col = (baij->cstart+aj[j])*bs;
14840ac07820SSatish Balay       for (k=0; k<bs; k++ ) {
14850ac07820SSatish Balay         ierr = MatSetValues(B,1,&col,bs,rvals,a,INSERT_VALUES);CHKERRQ(ierr);
14860ac07820SSatish Balay         col++; a += bs;
14870ac07820SSatish Balay       }
14880ac07820SSatish Balay     }
14890ac07820SSatish Balay   }
14900ac07820SSatish Balay   /* copy over the B part */
14910ac07820SSatish Balay   Aloc = (Mat_SeqBAIJ*) baij->B->data;
14920ac07820SSatish Balay   ai = Aloc->i; aj = Aloc->j; a = Aloc->a;
14930ac07820SSatish Balay   for ( i=0; i<mbs; i++ ) {
14940ac07820SSatish Balay     rvals[0] = bs*(baij->rstart + i);
14950ac07820SSatish Balay     for ( j=1; j<bs; j++ ) { rvals[j] = rvals[j-1] + 1; }
14960ac07820SSatish Balay     for ( j=ai[i]; j<ai[i+1]; j++ ) {
14970ac07820SSatish Balay       col = baij->garray[aj[j]]*bs;
14980ac07820SSatish Balay       for (k=0; k<bs; k++ ) {
14990ac07820SSatish Balay         ierr = MatSetValues(B,1,&col,bs,rvals,a,INSERT_VALUES);CHKERRQ(ierr);
15000ac07820SSatish Balay         col++; a += bs;
15010ac07820SSatish Balay       }
15020ac07820SSatish Balay     }
15030ac07820SSatish Balay   }
15040ac07820SSatish Balay   PetscFree(rvals);
15050ac07820SSatish Balay   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
15060ac07820SSatish Balay   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
15070ac07820SSatish Balay 
15080ac07820SSatish Balay   if (matout != PETSC_NULL) {
15090ac07820SSatish Balay     *matout = B;
15100ac07820SSatish Balay   } else {
1511f830108cSBarry Smith     PetscOps *Abops;
1512cc2dc46cSBarry Smith     MatOps   Aops;
1513f830108cSBarry Smith 
15140ac07820SSatish Balay     /* This isn't really an in-place transpose .... but free data structures from baij */
15150ac07820SSatish Balay     PetscFree(baij->rowners);
15160ac07820SSatish Balay     ierr = MatDestroy(baij->A); CHKERRQ(ierr);
15170ac07820SSatish Balay     ierr = MatDestroy(baij->B); CHKERRQ(ierr);
1518b1fc9764SSatish Balay #if defined (USE_CTABLE)
1519b1fc9764SSatish Balay     if (baij->colmap) TableDelete(baij->colmap);
1520b1fc9764SSatish Balay #else
15210ac07820SSatish Balay     if (baij->colmap) PetscFree(baij->colmap);
1522b1fc9764SSatish Balay #endif
15230ac07820SSatish Balay     if (baij->garray) PetscFree(baij->garray);
15240ac07820SSatish Balay     if (baij->lvec) VecDestroy(baij->lvec);
15250ac07820SSatish Balay     if (baij->Mvctx) VecScatterDestroy(baij->Mvctx);
15260ac07820SSatish Balay     PetscFree(baij);
1527f830108cSBarry Smith 
1528f830108cSBarry Smith     /*
1529f830108cSBarry Smith        This is horrible, horrible code. We need to keep the
1530f830108cSBarry Smith       A pointers for the bops and ops but copy everything
1531f830108cSBarry Smith       else from C.
1532f830108cSBarry Smith     */
1533f830108cSBarry Smith     Abops = A->bops;
1534f830108cSBarry Smith     Aops  = A->ops;
1535f09e8eb9SSatish Balay     PetscMemcpy(A,B,sizeof(struct _p_Mat));
1536f830108cSBarry Smith     A->bops = Abops;
1537f830108cSBarry Smith     A->ops  = Aops;
1538f830108cSBarry Smith 
15390ac07820SSatish Balay     PetscHeaderDestroy(B);
15400ac07820SSatish Balay   }
15413a40ed3dSBarry Smith   PetscFunctionReturn(0);
15420ac07820SSatish Balay }
15430e95ebc0SSatish Balay 
15445615d1e5SSatish Balay #undef __FUNC__
15455615d1e5SSatish Balay #define __FUNC__ "MatDiagonalScale_MPIBAIJ"
15460e95ebc0SSatish Balay int MatDiagonalScale_MPIBAIJ(Mat A,Vec ll,Vec rr)
15470e95ebc0SSatish Balay {
15480e95ebc0SSatish Balay   Mat a = ((Mat_MPIBAIJ *) A->data)->A;
15490e95ebc0SSatish Balay   Mat b = ((Mat_MPIBAIJ *) A->data)->B;
15500e95ebc0SSatish Balay   int ierr,s1,s2,s3;
15510e95ebc0SSatish Balay 
1552d64ed03dSBarry Smith   PetscFunctionBegin;
15530e95ebc0SSatish Balay   if (ll)  {
15540e95ebc0SSatish Balay     ierr = VecGetLocalSize(ll,&s1); CHKERRQ(ierr);
15550e95ebc0SSatish Balay     ierr = MatGetLocalSize(A,&s2,&s3); CHKERRQ(ierr);
1556a8c6a408SBarry Smith     if (s1!=s2) SETERRQ(PETSC_ERR_ARG_SIZ,0,"non-conforming local sizes");
15570e95ebc0SSatish Balay     ierr = MatDiagonalScale(a,ll,0); CHKERRQ(ierr);
15580e95ebc0SSatish Balay     ierr = MatDiagonalScale(b,ll,0); CHKERRQ(ierr);
15590e95ebc0SSatish Balay   }
1560a8c6a408SBarry Smith   if (rr) SETERRQ(PETSC_ERR_SUP,0,"not supported for right vector");
15613a40ed3dSBarry Smith   PetscFunctionReturn(0);
15620e95ebc0SSatish Balay }
15630e95ebc0SSatish Balay 
15645615d1e5SSatish Balay #undef __FUNC__
15655615d1e5SSatish Balay #define __FUNC__ "MatZeroRows_MPIBAIJ"
1566ec1ea8d8SLois Curfman McInnes int MatZeroRows_MPIBAIJ(Mat A,IS is,Scalar *diag)
15670ac07820SSatish Balay {
15680ac07820SSatish Balay   Mat_MPIBAIJ    *l = (Mat_MPIBAIJ *) A->data;
15690ac07820SSatish Balay   int            i,ierr,N, *rows,*owners = l->rowners,size = l->size;
1570a07cd24cSSatish Balay   int            *procs,*nprocs,j,found,idx,nsends,*work,row;
15710ac07820SSatish Balay   int            nmax,*svalues,*starts,*owner,nrecvs,rank = l->rank;
15720ac07820SSatish Balay   int            *rvalues,tag = A->tag,count,base,slen,n,*source;
1573a07cd24cSSatish Balay   int            *lens,imdex,*lrows,*values,bs=l->bs,rstart_bs=l->rstart_bs;
15740ac07820SSatish Balay   MPI_Comm       comm = A->comm;
15750ac07820SSatish Balay   MPI_Request    *send_waits,*recv_waits;
15760ac07820SSatish Balay   MPI_Status     recv_status,*send_status;
15770ac07820SSatish Balay   IS             istmp;
15780ac07820SSatish Balay 
1579d64ed03dSBarry Smith   PetscFunctionBegin;
15800ac07820SSatish Balay   ierr = ISGetSize(is,&N); CHKERRQ(ierr);
15810ac07820SSatish Balay   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
15820ac07820SSatish Balay 
15830ac07820SSatish Balay   /*  first count number of contributors to each processor */
15840ac07820SSatish Balay   nprocs = (int *) PetscMalloc( 2*size*sizeof(int) ); CHKPTRQ(nprocs);
15850ac07820SSatish Balay   PetscMemzero(nprocs,2*size*sizeof(int)); procs = nprocs + size;
15860ac07820SSatish Balay   owner = (int *) PetscMalloc((N+1)*sizeof(int)); CHKPTRQ(owner); /* see note*/
15870ac07820SSatish Balay   for ( i=0; i<N; i++ ) {
15880ac07820SSatish Balay     idx = rows[i];
15890ac07820SSatish Balay     found = 0;
15900ac07820SSatish Balay     for ( j=0; j<size; j++ ) {
15910ac07820SSatish Balay       if (idx >= owners[j]*bs && idx < owners[j+1]*bs) {
15920ac07820SSatish Balay         nprocs[j]++; procs[j] = 1; owner[i] = j; found = 1; break;
15930ac07820SSatish Balay       }
15940ac07820SSatish Balay     }
1595a8c6a408SBarry Smith     if (!found) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Index out of range");
15960ac07820SSatish Balay   }
15970ac07820SSatish Balay   nsends = 0;  for ( i=0; i<size; i++ ) { nsends += procs[i];}
15980ac07820SSatish Balay 
15990ac07820SSatish Balay   /* inform other processors of number of messages and max length*/
16000ac07820SSatish Balay   work   = (int *) PetscMalloc( size*sizeof(int) ); CHKPTRQ(work);
1601ca161407SBarry Smith   ierr   = MPI_Allreduce( procs, work,size,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
16020ac07820SSatish Balay   nrecvs = work[rank];
1603ca161407SBarry Smith   ierr   = MPI_Allreduce( nprocs, work,size,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
16040ac07820SSatish Balay   nmax   = work[rank];
16050ac07820SSatish Balay   PetscFree(work);
16060ac07820SSatish Balay 
16070ac07820SSatish Balay   /* post receives:   */
1608d64ed03dSBarry Smith   rvalues = (int *) PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(int)); CHKPTRQ(rvalues);
1609d64ed03dSBarry Smith   recv_waits = (MPI_Request *) PetscMalloc((nrecvs+1)*sizeof(MPI_Request));CHKPTRQ(recv_waits);
16100ac07820SSatish Balay   for ( i=0; i<nrecvs; i++ ) {
1611ca161407SBarry Smith     ierr = MPI_Irecv(rvalues+nmax*i,nmax,MPI_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr);
16120ac07820SSatish Balay   }
16130ac07820SSatish Balay 
16140ac07820SSatish Balay   /* do sends:
16150ac07820SSatish Balay      1) starts[i] gives the starting index in svalues for stuff going to
16160ac07820SSatish Balay      the ith processor
16170ac07820SSatish Balay   */
16180ac07820SSatish Balay   svalues = (int *) PetscMalloc( (N+1)*sizeof(int) ); CHKPTRQ(svalues);
1619ca161407SBarry Smith   send_waits = (MPI_Request *) PetscMalloc( (nsends+1)*sizeof(MPI_Request));CHKPTRQ(send_waits);
16200ac07820SSatish Balay   starts = (int *) PetscMalloc( (size+1)*sizeof(int) ); CHKPTRQ(starts);
16210ac07820SSatish Balay   starts[0] = 0;
16220ac07820SSatish Balay   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
16230ac07820SSatish Balay   for ( i=0; i<N; i++ ) {
16240ac07820SSatish Balay     svalues[starts[owner[i]]++] = rows[i];
16250ac07820SSatish Balay   }
16260ac07820SSatish Balay   ISRestoreIndices(is,&rows);
16270ac07820SSatish Balay 
16280ac07820SSatish Balay   starts[0] = 0;
16290ac07820SSatish Balay   for ( i=1; i<size+1; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
16300ac07820SSatish Balay   count = 0;
16310ac07820SSatish Balay   for ( i=0; i<size; i++ ) {
16320ac07820SSatish Balay     if (procs[i]) {
1633ca161407SBarry Smith       ierr = MPI_Isend(svalues+starts[i],nprocs[i],MPI_INT,i,tag,comm,send_waits+count++);CHKERRQ(ierr);
16340ac07820SSatish Balay     }
16350ac07820SSatish Balay   }
16360ac07820SSatish Balay   PetscFree(starts);
16370ac07820SSatish Balay 
16380ac07820SSatish Balay   base = owners[rank]*bs;
16390ac07820SSatish Balay 
16400ac07820SSatish Balay   /*  wait on receives */
16410ac07820SSatish Balay   lens   = (int *) PetscMalloc( 2*(nrecvs+1)*sizeof(int) ); CHKPTRQ(lens);
16420ac07820SSatish Balay   source = lens + nrecvs;
16430ac07820SSatish Balay   count  = nrecvs; slen = 0;
16440ac07820SSatish Balay   while (count) {
1645ca161407SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
16460ac07820SSatish Balay     /* unpack receives into our local space */
1647ca161407SBarry Smith     ierr = MPI_Get_count(&recv_status,MPI_INT,&n);CHKERRQ(ierr);
16480ac07820SSatish Balay     source[imdex]  = recv_status.MPI_SOURCE;
16490ac07820SSatish Balay     lens[imdex]  = n;
16500ac07820SSatish Balay     slen += n;
16510ac07820SSatish Balay     count--;
16520ac07820SSatish Balay   }
16530ac07820SSatish Balay   PetscFree(recv_waits);
16540ac07820SSatish Balay 
16550ac07820SSatish Balay   /* move the data into the send scatter */
16560ac07820SSatish Balay   lrows = (int *) PetscMalloc( (slen+1)*sizeof(int) ); CHKPTRQ(lrows);
16570ac07820SSatish Balay   count = 0;
16580ac07820SSatish Balay   for ( i=0; i<nrecvs; i++ ) {
16590ac07820SSatish Balay     values = rvalues + i*nmax;
16600ac07820SSatish Balay     for ( j=0; j<lens[i]; j++ ) {
16610ac07820SSatish Balay       lrows[count++] = values[j] - base;
16620ac07820SSatish Balay     }
16630ac07820SSatish Balay   }
16640ac07820SSatish Balay   PetscFree(rvalues); PetscFree(lens);
16650ac07820SSatish Balay   PetscFree(owner); PetscFree(nprocs);
16660ac07820SSatish Balay 
16670ac07820SSatish Balay   /* actually zap the local rows */
1668029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,slen,lrows,&istmp);CHKERRQ(ierr);
16690ac07820SSatish Balay   PLogObjectParent(A,istmp);
1670a07cd24cSSatish Balay 
167172dacd9aSBarry Smith   /*
167272dacd9aSBarry Smith         Zero the required rows. If the "diagonal block" of the matrix
167372dacd9aSBarry Smith      is square and the user wishes to set the diagonal we use seperate
167472dacd9aSBarry Smith      code so that MatSetValues() is not called for each diagonal allocating
167572dacd9aSBarry Smith      new memory, thus calling lots of mallocs and slowing things down.
167672dacd9aSBarry Smith 
167772dacd9aSBarry Smith        Contributed by: Mathew Knepley
167872dacd9aSBarry Smith   */
16799c957beeSSatish Balay   /* must zero l->B before l->A because the (diag) case below may put values into l->B*/
16800ac07820SSatish Balay   ierr = MatZeroRows(l->B,istmp,0); CHKERRQ(ierr);
16819c957beeSSatish Balay   if (diag && (l->A->M == l->A->N)) {
16829c957beeSSatish Balay     ierr      = MatZeroRows(l->A,istmp,diag); CHKERRQ(ierr);
16839c957beeSSatish Balay   } else if (diag) {
16849c957beeSSatish Balay     ierr = MatZeroRows(l->A,istmp,0); CHKERRQ(ierr);
1685fa46199cSSatish Balay     if (((Mat_SeqBAIJ*)l->A->data)->nonew) {
1686fa46199cSSatish Balay       SETERRQ(PETSC_ERR_SUP,0,"MatZeroRows() on rectangular matrices cannot be used with the Mat options \n\
1687fa46199cSSatish Balay MAT_NO_NEW_NONZERO_LOCATIONS,MAT_NEW_NONZERO_LOCATION_ERR,MAT_NEW_NONZERO_ALLOCATION_ERR");
16886525c446SSatish Balay     }
1689a07cd24cSSatish Balay     for ( i = 0; i < slen; i++ ) {
1690a07cd24cSSatish Balay       row  = lrows[i] + rstart_bs;
1691a07cd24cSSatish Balay       ierr = MatSetValues(A,1,&row,1,&row,diag,INSERT_VALUES);CHKERRQ(ierr);
1692a07cd24cSSatish Balay     }
1693a07cd24cSSatish Balay     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1694a07cd24cSSatish Balay     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16959c957beeSSatish Balay   } else {
16969c957beeSSatish Balay     ierr = MatZeroRows(l->A,istmp,0); CHKERRQ(ierr);
1697a07cd24cSSatish Balay   }
16989c957beeSSatish Balay 
16999c957beeSSatish Balay   ierr = ISDestroy(istmp); CHKERRQ(ierr);
1700a07cd24cSSatish Balay   PetscFree(lrows);
1701a07cd24cSSatish Balay 
17020ac07820SSatish Balay   /* wait on sends */
17030ac07820SSatish Balay   if (nsends) {
1704d64ed03dSBarry Smith     send_status = (MPI_Status *) PetscMalloc(nsends*sizeof(MPI_Status));CHKPTRQ(send_status);
1705ca161407SBarry Smith     ierr        = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
17060ac07820SSatish Balay     PetscFree(send_status);
17070ac07820SSatish Balay   }
17080ac07820SSatish Balay   PetscFree(send_waits); PetscFree(svalues);
17090ac07820SSatish Balay 
17103a40ed3dSBarry Smith   PetscFunctionReturn(0);
17110ac07820SSatish Balay }
171272dacd9aSBarry Smith 
17135615d1e5SSatish Balay #undef __FUNC__
17145615d1e5SSatish Balay #define __FUNC__ "MatPrintHelp_MPIBAIJ"
1715ec1ea8d8SLois Curfman McInnes int MatPrintHelp_MPIBAIJ(Mat A)
1716ba4ca20aSSatish Balay {
1717ba4ca20aSSatish Balay   Mat_MPIBAIJ *a   = (Mat_MPIBAIJ*) A->data;
171825fdafccSSatish Balay   MPI_Comm    comm = A->comm;
1719133cdb44SSatish Balay   static int  called = 0;
17203a40ed3dSBarry Smith   int         ierr;
1721ba4ca20aSSatish Balay 
1722d64ed03dSBarry Smith   PetscFunctionBegin;
17233a40ed3dSBarry Smith   if (!a->rank) {
17243a40ed3dSBarry Smith     ierr = MatPrintHelp_SeqBAIJ(a->A);CHKERRQ(ierr);
172525fdafccSSatish Balay   }
172625fdafccSSatish Balay   if (called) {PetscFunctionReturn(0);} else called = 1;
1727133cdb44SSatish Balay   (*PetscHelpPrintf)(comm," Options for MATMPIBAIJ matrix format (the defaults):\n");
1728133cdb44SSatish Balay   (*PetscHelpPrintf)(comm,"  -mat_use_hash_table <factor>: Use hashtable for efficient matrix assembly\n");
17293a40ed3dSBarry Smith   PetscFunctionReturn(0);
1730ba4ca20aSSatish Balay }
17310ac07820SSatish Balay 
17325615d1e5SSatish Balay #undef __FUNC__
17335615d1e5SSatish Balay #define __FUNC__ "MatSetUnfactored_MPIBAIJ"
1734ec1ea8d8SLois Curfman McInnes int MatSetUnfactored_MPIBAIJ(Mat A)
1735bb5a7306SBarry Smith {
1736bb5a7306SBarry Smith   Mat_MPIBAIJ *a   = (Mat_MPIBAIJ*) A->data;
1737bb5a7306SBarry Smith   int         ierr;
1738d64ed03dSBarry Smith 
1739d64ed03dSBarry Smith   PetscFunctionBegin;
1740bb5a7306SBarry Smith   ierr = MatSetUnfactored(a->A); CHKERRQ(ierr);
17413a40ed3dSBarry Smith   PetscFunctionReturn(0);
1742bb5a7306SBarry Smith }
1743bb5a7306SBarry Smith 
17442e8a6d31SBarry Smith static int MatDuplicate_MPIBAIJ(Mat,MatDuplicateOption,Mat *);
17450ac07820SSatish Balay 
174679bdfe76SSatish Balay /* -------------------------------------------------------------------*/
1747cc2dc46cSBarry Smith static struct _MatOps MatOps_Values = {
1748cc2dc46cSBarry Smith   MatSetValues_MPIBAIJ,
1749cc2dc46cSBarry Smith   MatGetRow_MPIBAIJ,
1750cc2dc46cSBarry Smith   MatRestoreRow_MPIBAIJ,
1751cc2dc46cSBarry Smith   MatMult_MPIBAIJ,
1752cc2dc46cSBarry Smith   MatMultAdd_MPIBAIJ,
1753cc2dc46cSBarry Smith   MatMultTrans_MPIBAIJ,
1754cc2dc46cSBarry Smith   MatMultTransAdd_MPIBAIJ,
1755cc2dc46cSBarry Smith   0,
1756cc2dc46cSBarry Smith   0,
1757cc2dc46cSBarry Smith   0,
1758cc2dc46cSBarry Smith   0,
1759cc2dc46cSBarry Smith   0,
1760cc2dc46cSBarry Smith   0,
1761cc2dc46cSBarry Smith   0,
1762cc2dc46cSBarry Smith   MatTranspose_MPIBAIJ,
1763cc2dc46cSBarry Smith   MatGetInfo_MPIBAIJ,
1764cc2dc46cSBarry Smith   0,
1765cc2dc46cSBarry Smith   MatGetDiagonal_MPIBAIJ,
1766cc2dc46cSBarry Smith   MatDiagonalScale_MPIBAIJ,
1767cc2dc46cSBarry Smith   MatNorm_MPIBAIJ,
1768cc2dc46cSBarry Smith   MatAssemblyBegin_MPIBAIJ,
1769cc2dc46cSBarry Smith   MatAssemblyEnd_MPIBAIJ,
1770cc2dc46cSBarry Smith   0,
1771cc2dc46cSBarry Smith   MatSetOption_MPIBAIJ,
1772cc2dc46cSBarry Smith   MatZeroEntries_MPIBAIJ,
1773cc2dc46cSBarry Smith   MatZeroRows_MPIBAIJ,
1774cc2dc46cSBarry Smith   0,
1775cc2dc46cSBarry Smith   0,
1776cc2dc46cSBarry Smith   0,
1777cc2dc46cSBarry Smith   0,
1778cc2dc46cSBarry Smith   MatGetSize_MPIBAIJ,
1779cc2dc46cSBarry Smith   MatGetLocalSize_MPIBAIJ,
1780cc2dc46cSBarry Smith   MatGetOwnershipRange_MPIBAIJ,
1781cc2dc46cSBarry Smith   0,
1782cc2dc46cSBarry Smith   0,
1783cc2dc46cSBarry Smith   0,
1784cc2dc46cSBarry Smith   0,
17852e8a6d31SBarry Smith   MatDuplicate_MPIBAIJ,
1786cc2dc46cSBarry Smith   0,
1787cc2dc46cSBarry Smith   0,
1788cc2dc46cSBarry Smith   0,
1789cc2dc46cSBarry Smith   0,
1790cc2dc46cSBarry Smith   0,
1791cc2dc46cSBarry Smith   MatGetSubMatrices_MPIBAIJ,
1792cc2dc46cSBarry Smith   MatIncreaseOverlap_MPIBAIJ,
1793cc2dc46cSBarry Smith   MatGetValues_MPIBAIJ,
1794cc2dc46cSBarry Smith   0,
1795cc2dc46cSBarry Smith   MatPrintHelp_MPIBAIJ,
1796cc2dc46cSBarry Smith   MatScale_MPIBAIJ,
1797cc2dc46cSBarry Smith   0,
1798cc2dc46cSBarry Smith   0,
1799cc2dc46cSBarry Smith   0,
1800cc2dc46cSBarry Smith   MatGetBlockSize_MPIBAIJ,
1801cc2dc46cSBarry Smith   0,
1802cc2dc46cSBarry Smith   0,
1803cc2dc46cSBarry Smith   0,
1804cc2dc46cSBarry Smith   0,
1805cc2dc46cSBarry Smith   0,
1806cc2dc46cSBarry Smith   0,
1807cc2dc46cSBarry Smith   MatSetUnfactored_MPIBAIJ,
1808cc2dc46cSBarry Smith   0,
1809cc2dc46cSBarry Smith   MatSetValuesBlocked_MPIBAIJ,
1810cc2dc46cSBarry Smith   0,
1811cc2dc46cSBarry Smith   0,
1812cc2dc46cSBarry Smith   0,
1813cc2dc46cSBarry Smith   MatGetMaps_Petsc};
181479bdfe76SSatish Balay 
18155ef9f2a5SBarry Smith 
1816e18c124aSSatish Balay EXTERN_C_BEGIN
18175ef9f2a5SBarry Smith #undef __FUNC__
18185ef9f2a5SBarry Smith #define __FUNC__ "MatGetDiagonalBlock_MPIBAIJ"
18195ef9f2a5SBarry Smith int MatGetDiagonalBlock_MPIBAIJ(Mat A,PetscTruth *iscopy,MatReuse reuse,Mat *a)
18205ef9f2a5SBarry Smith {
18215ef9f2a5SBarry Smith   PetscFunctionBegin;
18225ef9f2a5SBarry Smith   *a      = ((Mat_MPIBAIJ *)A->data)->A;
18235ef9f2a5SBarry Smith   *iscopy = PETSC_FALSE;
18245ef9f2a5SBarry Smith   PetscFunctionReturn(0);
18255ef9f2a5SBarry Smith }
1826e18c124aSSatish Balay EXTERN_C_END
182779bdfe76SSatish Balay 
18285615d1e5SSatish Balay #undef __FUNC__
18295615d1e5SSatish Balay #define __FUNC__ "MatCreateMPIBAIJ"
183079bdfe76SSatish Balay /*@C
183179bdfe76SSatish Balay    MatCreateMPIBAIJ - Creates a sparse parallel matrix in block AIJ format
183279bdfe76SSatish Balay    (block compressed row).  For good matrix assembly performance
183379bdfe76SSatish Balay    the user should preallocate the matrix storage by setting the parameters
183479bdfe76SSatish Balay    d_nz (or d_nnz) and o_nz (or o_nnz).  By setting these parameters accurately,
183579bdfe76SSatish Balay    performance can be increased by more than a factor of 50.
183679bdfe76SSatish Balay 
1837db81eaa0SLois Curfman McInnes    Collective on MPI_Comm
1838db81eaa0SLois Curfman McInnes 
183979bdfe76SSatish Balay    Input Parameters:
1840db81eaa0SLois Curfman McInnes +  comm - MPI communicator
184179bdfe76SSatish Balay .  bs   - size of blockk
184279bdfe76SSatish Balay .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
184392e8d321SLois Curfman McInnes            This value should be the same as the local size used in creating the
184492e8d321SLois Curfman McInnes            y vector for the matrix-vector product y = Ax.
184592e8d321SLois Curfman McInnes .  n - number of local columns (or PETSC_DECIDE to have calculated if N is given)
184692e8d321SLois Curfman McInnes            This value should be the same as the local size used in creating the
184792e8d321SLois Curfman McInnes            x vector for the matrix-vector product y = Ax.
1848be79a94dSBarry Smith .  M - number of global rows (or PETSC_DETERMINE to have calculated if m is given)
1849be79a94dSBarry Smith .  N - number of global columns (or PETSC_DETERMINE to have calculated if n is given)
185079bdfe76SSatish Balay .  d_nz  - number of block nonzeros per block row in diagonal portion of local
185179bdfe76SSatish Balay            submatrix  (same for all local rows)
185292e8d321SLois Curfman McInnes .  d_nzz - array containing the number of block nonzeros in the various block rows
185392e8d321SLois Curfman McInnes            of the in diagonal portion of the local (possibly different for each block
1854db81eaa0SLois Curfman McInnes            row) or PETSC_NULL.  You must leave room for the diagonal entry even if it is zero.
185592e8d321SLois Curfman McInnes .  o_nz  - number of block nonzeros per block row in the off-diagonal portion of local
185679bdfe76SSatish Balay            submatrix (same for all local rows).
1857db81eaa0SLois Curfman McInnes -  o_nzz - array containing the number of nonzeros in the various block rows of the
185892e8d321SLois Curfman McInnes            off-diagonal portion of the local submatrix (possibly different for
185992e8d321SLois Curfman McInnes            each block row) or PETSC_NULL.
186079bdfe76SSatish Balay 
186179bdfe76SSatish Balay    Output Parameter:
186279bdfe76SSatish Balay .  A - the matrix
186379bdfe76SSatish Balay 
1864db81eaa0SLois Curfman McInnes    Options Database Keys:
1865db81eaa0SLois Curfman McInnes .   -mat_no_unroll - uses code that does not unroll the loops in the
1866db81eaa0SLois Curfman McInnes                      block calculations (much slower)
1867db81eaa0SLois Curfman McInnes .   -mat_block_size - size of the blocks to use
1868494eafd4SBarry Smith .   -mat_mpi - use the parallel matrix data structures even on one processor
1869494eafd4SBarry Smith                (defaults to using SeqBAIJ format on one processor)
18703ffaccefSLois Curfman McInnes 
1871b259b22eSLois Curfman McInnes    Notes:
187279bdfe76SSatish Balay    The user MUST specify either the local or global matrix dimensions
187379bdfe76SSatish Balay    (possibly both).
187479bdfe76SSatish Balay 
1875be79a94dSBarry Smith    If PETSC_DECIDE or  PETSC_DETERMINE is used for a particular argument on one processor
1876be79a94dSBarry Smith    than it must be used on all processors that share the object for that argument.
1877be79a94dSBarry Smith 
187879bdfe76SSatish Balay    Storage Information:
187979bdfe76SSatish Balay    For a square global matrix we define each processor's diagonal portion
188079bdfe76SSatish Balay    to be its local rows and the corresponding columns (a square submatrix);
188179bdfe76SSatish Balay    each processor's off-diagonal portion encompasses the remainder of the
188279bdfe76SSatish Balay    local matrix (a rectangular submatrix).
188379bdfe76SSatish Balay 
188479bdfe76SSatish Balay    The user can specify preallocated storage for the diagonal part of
188579bdfe76SSatish Balay    the local submatrix with either d_nz or d_nnz (not both).  Set
188679bdfe76SSatish Balay    d_nz=PETSC_DEFAULT and d_nnz=PETSC_NULL for PETSc to control dynamic
188779bdfe76SSatish Balay    memory allocation.  Likewise, specify preallocated storage for the
188879bdfe76SSatish Balay    off-diagonal part of the local submatrix with o_nz or o_nnz (not both).
188979bdfe76SSatish Balay 
189079bdfe76SSatish Balay    Consider a processor that owns rows 3, 4 and 5 of a parallel matrix. In
189179bdfe76SSatish Balay    the figure below we depict these three local rows and all columns (0-11).
189279bdfe76SSatish Balay 
1893db81eaa0SLois Curfman McInnes .vb
1894db81eaa0SLois Curfman McInnes            0 1 2 3 4 5 6 7 8 9 10 11
1895db81eaa0SLois Curfman McInnes           -------------------
1896db81eaa0SLois Curfman McInnes    row 3  |  o o o d d d o o o o o o
1897db81eaa0SLois Curfman McInnes    row 4  |  o o o d d d o o o o o o
1898db81eaa0SLois Curfman McInnes    row 5  |  o o o d d d o o o o o o
1899db81eaa0SLois Curfman McInnes           -------------------
1900db81eaa0SLois Curfman McInnes .ve
190179bdfe76SSatish Balay 
190279bdfe76SSatish Balay    Thus, any entries in the d locations are stored in the d (diagonal)
190379bdfe76SSatish Balay    submatrix, and any entries in the o locations are stored in the
190479bdfe76SSatish Balay    o (off-diagonal) submatrix.  Note that the d and the o submatrices are
190557b952d6SSatish Balay    stored simply in the MATSEQBAIJ format for compressed row storage.
190679bdfe76SSatish Balay 
1907d64ed03dSBarry Smith    Now d_nz should indicate the number of block nonzeros per row in the d matrix,
1908d64ed03dSBarry Smith    and o_nz should indicate the number of block nonzeros per row in the o matrix.
190979bdfe76SSatish Balay    In general, for PDE problems in which most nonzeros are near the diagonal,
191092e8d321SLois Curfman McInnes    one expects d_nz >> o_nz.   For large problems you MUST preallocate memory
191192e8d321SLois Curfman McInnes    or you will get TERRIBLE performance; see the users' manual chapter on
19126da5968aSLois Curfman McInnes    matrices.
191379bdfe76SSatish Balay 
1914027ccd11SLois Curfman McInnes    Level: intermediate
1915027ccd11SLois Curfman McInnes 
191692e8d321SLois Curfman McInnes .keywords: matrix, block, aij, compressed row, sparse, parallel
191779bdfe76SSatish Balay 
1918db81eaa0SLois Curfman McInnes .seealso: MatCreate(), MatCreateSeqBAIJ(), MatSetValues(), MatCreateMPIAIJ()
191979bdfe76SSatish Balay @*/
192079bdfe76SSatish Balay int MatCreateMPIBAIJ(MPI_Comm comm,int bs,int m,int n,int M,int N,
192179bdfe76SSatish Balay                     int d_nz,int *d_nnz,int o_nz,int *o_nnz,Mat *A)
192279bdfe76SSatish Balay {
192379bdfe76SSatish Balay   Mat          B;
192479bdfe76SSatish Balay   Mat_MPIBAIJ  *b;
1925133cdb44SSatish Balay   int          ierr, i,sum[2],work[2],mbs,nbs,Mbs=PETSC_DECIDE,Nbs=PETSC_DECIDE,size,flg;
1926a2ab621fSBarry Smith   int          flag1 = 0,flag2 = 0;
192779bdfe76SSatish Balay 
1928d64ed03dSBarry Smith   PetscFunctionBegin;
1929a8c6a408SBarry Smith   if (bs < 1) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Invalid block size specified, must be positive");
19303914022bSBarry Smith 
19313914022bSBarry Smith   MPI_Comm_size(comm,&size);
1932494eafd4SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_mpibaij",&flag1); CHKERRQ(ierr);
1933494eafd4SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_mpi",&flag2); CHKERRQ(ierr);
1934494eafd4SBarry Smith   if (!flag1 && !flag2 && size == 1) {
19353914022bSBarry Smith     if (M == PETSC_DECIDE) M = m;
19363914022bSBarry Smith     if (N == PETSC_DECIDE) N = n;
19373914022bSBarry Smith     ierr = MatCreateSeqBAIJ(comm,bs,M,N,d_nz,d_nnz,A); CHKERRQ(ierr);
19383a40ed3dSBarry Smith     PetscFunctionReturn(0);
19393914022bSBarry Smith   }
19403914022bSBarry Smith 
194179bdfe76SSatish Balay   *A = 0;
19423f1db9ecSBarry Smith   PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_COOKIE,MATMPIBAIJ,"Mat",comm,MatDestroy,MatView);
194379bdfe76SSatish Balay   PLogObjectCreate(B);
194479bdfe76SSatish Balay   B->data       = (void *) (b = PetscNew(Mat_MPIBAIJ)); CHKPTRQ(b);
194579bdfe76SSatish Balay   PetscMemzero(b,sizeof(Mat_MPIBAIJ));
1946cc2dc46cSBarry Smith   PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
19474c50302cSBarry Smith 
1948e1311b90SBarry Smith   B->ops->destroy    = MatDestroy_MPIBAIJ;
1949e1311b90SBarry Smith   B->ops->view       = MatView_MPIBAIJ;
195090f02eecSBarry Smith   B->mapping    = 0;
195179bdfe76SSatish Balay   B->factor     = 0;
195279bdfe76SSatish Balay   B->assembled  = PETSC_FALSE;
195379bdfe76SSatish Balay 
1954e0fa3b82SLois Curfman McInnes   B->insertmode = NOT_SET_VALUES;
195579bdfe76SSatish Balay   MPI_Comm_rank(comm,&b->rank);
195679bdfe76SSatish Balay   MPI_Comm_size(comm,&b->size);
195779bdfe76SSatish Balay 
1958d64ed03dSBarry Smith   if ( m == PETSC_DECIDE && (d_nnz != PETSC_NULL || o_nnz != PETSC_NULL)) {
1959a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Cannot have PETSC_DECIDE rows but set d_nnz or o_nnz");
1960d64ed03dSBarry Smith   }
1961a8c6a408SBarry Smith   if ( M == PETSC_DECIDE && m == PETSC_DECIDE) {
1962a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"either M or m should be specified");
1963a8c6a408SBarry Smith   }
1964a8c6a408SBarry Smith   if ( N == PETSC_DECIDE && n == PETSC_DECIDE) {
1965a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"either N or n should be specified");
1966a8c6a408SBarry Smith   }
1967cee3aa6bSSatish Balay   if ( M != PETSC_DECIDE && m != PETSC_DECIDE) M = PETSC_DECIDE;
1968cee3aa6bSSatish Balay   if ( N != PETSC_DECIDE && n != PETSC_DECIDE) N = PETSC_DECIDE;
196979bdfe76SSatish Balay 
197079bdfe76SSatish Balay   if (M == PETSC_DECIDE || N == PETSC_DECIDE) {
197179bdfe76SSatish Balay     work[0] = m; work[1] = n;
197279bdfe76SSatish Balay     mbs = m/bs; nbs = n/bs;
1973ca161407SBarry Smith     ierr = MPI_Allreduce( work, sum,2,MPI_INT,MPI_SUM,comm );CHKERRQ(ierr);
197479bdfe76SSatish Balay     if (M == PETSC_DECIDE) {M = sum[0]; Mbs = M/bs;}
197579bdfe76SSatish Balay     if (N == PETSC_DECIDE) {N = sum[1]; Nbs = N/bs;}
197679bdfe76SSatish Balay   }
197779bdfe76SSatish Balay   if (m == PETSC_DECIDE) {
197879bdfe76SSatish Balay     Mbs = M/bs;
1979a8c6a408SBarry Smith     if (Mbs*bs != M) SETERRQ(PETSC_ERR_ARG_SIZ,0,"No of global rows must be divisible by blocksize");
198079bdfe76SSatish Balay     mbs = Mbs/b->size + ((Mbs % b->size) > b->rank);
198179bdfe76SSatish Balay     m   = mbs*bs;
198279bdfe76SSatish Balay   }
198379bdfe76SSatish Balay   if (n == PETSC_DECIDE) {
198479bdfe76SSatish Balay     Nbs = N/bs;
1985a8c6a408SBarry Smith     if (Nbs*bs != N) SETERRQ(PETSC_ERR_ARG_SIZ,0,"No of global cols must be divisible by blocksize");
198679bdfe76SSatish Balay     nbs = Nbs/b->size + ((Nbs % b->size) > b->rank);
198779bdfe76SSatish Balay     n   = nbs*bs;
198879bdfe76SSatish Balay   }
1989a8c6a408SBarry Smith   if (mbs*bs != m || nbs*bs != n) {
1990a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_SIZ,0,"No of local rows, cols must be divisible by blocksize");
1991a8c6a408SBarry Smith   }
199279bdfe76SSatish Balay 
199379bdfe76SSatish Balay   b->m = m; B->m = m;
199479bdfe76SSatish Balay   b->n = n; B->n = n;
199579bdfe76SSatish Balay   b->N = N; B->N = N;
199679bdfe76SSatish Balay   b->M = M; B->M = M;
199779bdfe76SSatish Balay   b->bs  = bs;
199879bdfe76SSatish Balay   b->bs2 = bs*bs;
199979bdfe76SSatish Balay   b->mbs = mbs;
200079bdfe76SSatish Balay   b->nbs = nbs;
200179bdfe76SSatish Balay   b->Mbs = Mbs;
200279bdfe76SSatish Balay   b->Nbs = Nbs;
200379bdfe76SSatish Balay 
2004c7fcc2eaSBarry Smith   /* the information in the maps duplicates the information computed below, eventually
2005c7fcc2eaSBarry Smith      we should remove the duplicate information that is not contained in the maps */
2006488ecbafSBarry Smith   ierr = MapCreateMPI(comm,m,M,&B->rmap);CHKERRQ(ierr);
2007488ecbafSBarry Smith   ierr = MapCreateMPI(comm,n,N,&B->cmap);CHKERRQ(ierr);
2008c7fcc2eaSBarry Smith 
200979bdfe76SSatish Balay   /* build local table of row and column ownerships */
201079bdfe76SSatish Balay   b->rowners = (int *) PetscMalloc(2*(b->size+2)*sizeof(int)); CHKPTRQ(b->rowners);
2011f09e8eb9SSatish Balay   PLogObjectMemory(B,2*(b->size+2)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_MPIBAIJ));
20120ac07820SSatish Balay   b->cowners = b->rowners + b->size + 2;
2013ca161407SBarry Smith   ierr = MPI_Allgather(&mbs,1,MPI_INT,b->rowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
201479bdfe76SSatish Balay   b->rowners[0] = 0;
201579bdfe76SSatish Balay   for ( i=2; i<=b->size; i++ ) {
201679bdfe76SSatish Balay     b->rowners[i] += b->rowners[i-1];
201779bdfe76SSatish Balay   }
201879bdfe76SSatish Balay   b->rstart    = b->rowners[b->rank];
201979bdfe76SSatish Balay   b->rend      = b->rowners[b->rank+1];
20204fa0d573SSatish Balay   b->rstart_bs = b->rstart * bs;
20214fa0d573SSatish Balay   b->rend_bs   = b->rend * bs;
20224fa0d573SSatish Balay 
2023ca161407SBarry Smith   ierr = MPI_Allgather(&nbs,1,MPI_INT,b->cowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
202479bdfe76SSatish Balay   b->cowners[0] = 0;
202579bdfe76SSatish Balay   for ( i=2; i<=b->size; i++ ) {
202679bdfe76SSatish Balay     b->cowners[i] += b->cowners[i-1];
202779bdfe76SSatish Balay   }
202879bdfe76SSatish Balay   b->cstart    = b->cowners[b->rank];
202979bdfe76SSatish Balay   b->cend      = b->cowners[b->rank+1];
20304fa0d573SSatish Balay   b->cstart_bs = b->cstart * bs;
20314fa0d573SSatish Balay   b->cend_bs   = b->cend * bs;
203279bdfe76SSatish Balay 
2033a07cd24cSSatish Balay 
203479bdfe76SSatish Balay   if (d_nz == PETSC_DEFAULT) d_nz = 5;
2035029af93fSBarry Smith   ierr = MatCreateSeqBAIJ(PETSC_COMM_SELF,bs,m,n,d_nz,d_nnz,&b->A); CHKERRQ(ierr);
203679bdfe76SSatish Balay   PLogObjectParent(B,b->A);
203779bdfe76SSatish Balay   if (o_nz == PETSC_DEFAULT) o_nz = 0;
2038029af93fSBarry Smith   ierr = MatCreateSeqBAIJ(PETSC_COMM_SELF,bs,m,N,o_nz,o_nnz,&b->B); CHKERRQ(ierr);
203979bdfe76SSatish Balay   PLogObjectParent(B,b->B);
204079bdfe76SSatish Balay 
204179bdfe76SSatish Balay   /* build cache for off array entries formed */
2042a2d1c673SSatish Balay   ierr = StashCreate_Private(comm,1,bs,&b->stash); CHKERRQ(ierr);
2043a2d1c673SSatish Balay   ierr = StashCreate_Private(comm,bs,bs,&b->bstash); CHKERRQ(ierr);
204490f02eecSBarry Smith   b->donotstash  = 0;
204579bdfe76SSatish Balay   b->colmap      = 0;
204679bdfe76SSatish Balay   b->garray      = 0;
204779bdfe76SSatish Balay   b->roworiented = 1;
204879bdfe76SSatish Balay 
204930793edcSSatish Balay   /* stuff used in block assembly */
205030793edcSSatish Balay   b->barray       = 0;
205130793edcSSatish Balay 
205279bdfe76SSatish Balay   /* stuff used for matrix vector multiply */
205379bdfe76SSatish Balay   b->lvec         = 0;
205479bdfe76SSatish Balay   b->Mvctx        = 0;
205579bdfe76SSatish Balay 
205679bdfe76SSatish Balay   /* stuff for MatGetRow() */
205779bdfe76SSatish Balay   b->rowindices   = 0;
205879bdfe76SSatish Balay   b->rowvalues    = 0;
205979bdfe76SSatish Balay   b->getrowactive = PETSC_FALSE;
206079bdfe76SSatish Balay 
2061a07cd24cSSatish Balay   /* hash table stuff */
2062a07cd24cSSatish Balay   b->ht           = 0;
2063187ce0cbSSatish Balay   b->hd           = 0;
20640bdbc534SSatish Balay   b->ht_size      = 0;
2065133cdb44SSatish Balay   b->ht_flag      = 0;
206625fdafccSSatish Balay   b->ht_fact      = 0;
2067187ce0cbSSatish Balay   b->ht_total_ct  = 0;
2068187ce0cbSSatish Balay   b->ht_insert_ct = 0;
2069a07cd24cSSatish Balay 
207079bdfe76SSatish Balay   *A = B;
2071133cdb44SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-mat_use_hash_table",&flg); CHKERRQ(ierr);
2072133cdb44SSatish Balay   if (flg) {
2073133cdb44SSatish Balay     double fact = 1.39;
2074133cdb44SSatish Balay     ierr = MatSetOption(B,MAT_USE_HASH_TABLE); CHKERRQ(ierr);
2075133cdb44SSatish Balay     ierr = OptionsGetDouble(PETSC_NULL,"-mat_use_hash_table",&fact,&flg); CHKERRQ(ierr);
2076133cdb44SSatish Balay     if (fact <= 1.0) fact = 1.39;
2077133cdb44SSatish Balay     ierr = MatMPIBAIJSetHashTableFactor(B,fact); CHKERRQ(ierr);
2078133cdb44SSatish Balay     PLogInfo(0,"MatCreateMPIBAIJ:Hash table Factor used %5.2f\n",fact);
2079133cdb44SSatish Balay   }
20805ef9f2a5SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatGetDiagonalBlock_C",
20815ef9f2a5SBarry Smith                                      "MatGetDiagonalBlock_MPIBAIJ",
20825ef9f2a5SBarry Smith                                      (void*)MatGetDiagonalBlock_MPIBAIJ);CHKERRQ(ierr);
20833a40ed3dSBarry Smith   PetscFunctionReturn(0);
208479bdfe76SSatish Balay }
2085026e39d0SSatish Balay 
20865615d1e5SSatish Balay #undef __FUNC__
20872e8a6d31SBarry Smith #define __FUNC__ "MatDuplicate_MPIBAIJ"
20882e8a6d31SBarry Smith static int MatDuplicate_MPIBAIJ(Mat matin,MatDuplicateOption cpvalues,Mat *newmat)
20890ac07820SSatish Balay {
20900ac07820SSatish Balay   Mat         mat;
20910ac07820SSatish Balay   Mat_MPIBAIJ *a,*oldmat = (Mat_MPIBAIJ *) matin->data;
20920ac07820SSatish Balay   int         ierr, len=0, flg;
20930ac07820SSatish Balay 
2094d64ed03dSBarry Smith   PetscFunctionBegin;
20950ac07820SSatish Balay   *newmat       = 0;
20963f1db9ecSBarry Smith   PetscHeaderCreate(mat,_p_Mat,struct _MatOps,MAT_COOKIE,MATMPIBAIJ,"Mat",matin->comm,MatDestroy,MatView);
20970ac07820SSatish Balay   PLogObjectCreate(mat);
20980ac07820SSatish Balay   mat->data       = (void *) (a = PetscNew(Mat_MPIBAIJ)); CHKPTRQ(a);
2099cc2dc46cSBarry Smith   PetscMemcpy(mat->ops,&MatOps_Values,sizeof(struct _MatOps));
2100e1311b90SBarry Smith   mat->ops->destroy    = MatDestroy_MPIBAIJ;
2101e1311b90SBarry Smith   mat->ops->view       = MatView_MPIBAIJ;
21020ac07820SSatish Balay   mat->factor          = matin->factor;
21030ac07820SSatish Balay   mat->assembled       = PETSC_TRUE;
2104aef5e8e0SSatish Balay   mat->insertmode      = NOT_SET_VALUES;
21050ac07820SSatish Balay 
21060ac07820SSatish Balay   a->m = mat->m   = oldmat->m;
21070ac07820SSatish Balay   a->n = mat->n   = oldmat->n;
21080ac07820SSatish Balay   a->M = mat->M   = oldmat->M;
21090ac07820SSatish Balay   a->N = mat->N   = oldmat->N;
21100ac07820SSatish Balay 
21110ac07820SSatish Balay   a->bs  = oldmat->bs;
21120ac07820SSatish Balay   a->bs2 = oldmat->bs2;
21130ac07820SSatish Balay   a->mbs = oldmat->mbs;
21140ac07820SSatish Balay   a->nbs = oldmat->nbs;
21150ac07820SSatish Balay   a->Mbs = oldmat->Mbs;
21160ac07820SSatish Balay   a->Nbs = oldmat->Nbs;
21170ac07820SSatish Balay 
21180ac07820SSatish Balay   a->rstart       = oldmat->rstart;
21190ac07820SSatish Balay   a->rend         = oldmat->rend;
21200ac07820SSatish Balay   a->cstart       = oldmat->cstart;
21210ac07820SSatish Balay   a->cend         = oldmat->cend;
21220ac07820SSatish Balay   a->size         = oldmat->size;
21230ac07820SSatish Balay   a->rank         = oldmat->rank;
2124aef5e8e0SSatish Balay   a->donotstash   = oldmat->donotstash;
2125aef5e8e0SSatish Balay   a->roworiented  = oldmat->roworiented;
2126aef5e8e0SSatish Balay   a->rowindices   = 0;
21270ac07820SSatish Balay   a->rowvalues    = 0;
21280ac07820SSatish Balay   a->getrowactive = PETSC_FALSE;
212930793edcSSatish Balay   a->barray       = 0;
21303123a43fSSatish Balay   a->rstart_bs    = oldmat->rstart_bs;
21313123a43fSSatish Balay   a->rend_bs      = oldmat->rend_bs;
21323123a43fSSatish Balay   a->cstart_bs    = oldmat->cstart_bs;
21333123a43fSSatish Balay   a->cend_bs      = oldmat->cend_bs;
21340ac07820SSatish Balay 
2135133cdb44SSatish Balay   /* hash table stuff */
2136133cdb44SSatish Balay   a->ht           = 0;
2137133cdb44SSatish Balay   a->hd           = 0;
2138133cdb44SSatish Balay   a->ht_size      = 0;
2139133cdb44SSatish Balay   a->ht_flag      = oldmat->ht_flag;
214025fdafccSSatish Balay   a->ht_fact      = oldmat->ht_fact;
2141133cdb44SSatish Balay   a->ht_total_ct  = 0;
2142133cdb44SSatish Balay   a->ht_insert_ct = 0;
2143133cdb44SSatish Balay 
2144133cdb44SSatish Balay 
21450ac07820SSatish Balay   a->rowners = (int *) PetscMalloc(2*(a->size+2)*sizeof(int)); CHKPTRQ(a->rowners);
2146f09e8eb9SSatish Balay   PLogObjectMemory(mat,2*(a->size+2)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_MPIBAIJ));
21470ac07820SSatish Balay   a->cowners = a->rowners + a->size + 2;
21480ac07820SSatish Balay   PetscMemcpy(a->rowners,oldmat->rowners,2*(a->size+2)*sizeof(int));
2149a2d1c673SSatish Balay   ierr = StashCreate_Private(matin->comm,1,oldmat->bs,&a->stash); CHKERRQ(ierr);
2150a2d1c673SSatish Balay   ierr = StashCreate_Private(matin->comm,oldmat->bs,oldmat->bs,&a->bstash); CHKERRQ(ierr);
21510ac07820SSatish Balay   if (oldmat->colmap) {
215248e59246SSatish Balay #if defined (USE_CTABLE)
2153fa46199cSSatish Balay   ierr = TableCreateCopy(oldmat->colmap,&a->colmap); CHKERRQ(ierr);
215448e59246SSatish Balay #else
21550ac07820SSatish Balay     a->colmap = (int *) PetscMalloc((a->Nbs)*sizeof(int));CHKPTRQ(a->colmap);
21560ac07820SSatish Balay     PLogObjectMemory(mat,(a->Nbs)*sizeof(int));
21570ac07820SSatish Balay     PetscMemcpy(a->colmap,oldmat->colmap,(a->Nbs)*sizeof(int));
215848e59246SSatish Balay #endif
21590ac07820SSatish Balay   } else a->colmap = 0;
21600ac07820SSatish Balay   if (oldmat->garray && (len = ((Mat_SeqBAIJ *) (oldmat->B->data))->nbs)) {
21610ac07820SSatish Balay     a->garray = (int *) PetscMalloc(len*sizeof(int)); CHKPTRQ(a->garray);
21620ac07820SSatish Balay     PLogObjectMemory(mat,len*sizeof(int));
21630ac07820SSatish Balay     PetscMemcpy(a->garray,oldmat->garray,len*sizeof(int));
21640ac07820SSatish Balay   } else a->garray = 0;
21650ac07820SSatish Balay 
21660ac07820SSatish Balay   ierr =  VecDuplicate(oldmat->lvec,&a->lvec); CHKERRQ(ierr);
21670ac07820SSatish Balay   PLogObjectParent(mat,a->lvec);
21680ac07820SSatish Balay   ierr =  VecScatterCopy(oldmat->Mvctx,&a->Mvctx); CHKERRQ(ierr);
2169e18c124aSSatish Balay 
21700ac07820SSatish Balay   PLogObjectParent(mat,a->Mvctx);
21712e8a6d31SBarry Smith   ierr =  MatDuplicate(oldmat->A,cpvalues,&a->A); CHKERRQ(ierr);
21720ac07820SSatish Balay   PLogObjectParent(mat,a->A);
21732e8a6d31SBarry Smith   ierr =  MatDuplicate(oldmat->B,cpvalues,&a->B); CHKERRQ(ierr);
21740ac07820SSatish Balay   PLogObjectParent(mat,a->B);
21750ac07820SSatish Balay   ierr = OptionsHasName(PETSC_NULL,"-help",&flg); CHKERRQ(ierr);
2176e18c124aSSatish Balay   ierr = FListDuplicate(mat->qlist,&matin->qlist);CHKERRQ(ierr);
21770ac07820SSatish Balay   if (flg) {
21780ac07820SSatish Balay     ierr = MatPrintHelp(mat); CHKERRQ(ierr);
21790ac07820SSatish Balay   }
21800ac07820SSatish Balay   *newmat = mat;
21813a40ed3dSBarry Smith   PetscFunctionReturn(0);
21820ac07820SSatish Balay }
218357b952d6SSatish Balay 
218457b952d6SSatish Balay #include "sys.h"
218557b952d6SSatish Balay 
21865615d1e5SSatish Balay #undef __FUNC__
21875615d1e5SSatish Balay #define __FUNC__ "MatLoad_MPIBAIJ"
218857b952d6SSatish Balay int MatLoad_MPIBAIJ(Viewer viewer,MatType type,Mat *newmat)
218957b952d6SSatish Balay {
219057b952d6SSatish Balay   Mat          A;
219157b952d6SSatish Balay   int          i, nz, ierr, j,rstart, rend, fd;
219257b952d6SSatish Balay   Scalar       *vals,*buf;
219357b952d6SSatish Balay   MPI_Comm     comm = ((PetscObject)viewer)->comm;
219457b952d6SSatish Balay   MPI_Status   status;
2195cee3aa6bSSatish Balay   int          header[4],rank,size,*rowlengths = 0,M,N,m,*rowners,*browners,maxnz,*cols;
219657b952d6SSatish Balay   int          *locrowlens,*sndcounts = 0,*procsnz = 0, jj,*mycols,*ibuf;
219740011551SBarry Smith   int          flg,tag = ((PetscObject)viewer)->tag,bs=1,Mbs,mbs,extra_rows;
219857b952d6SSatish Balay   int          *dlens,*odlens,*mask,*masked1,*masked2,rowcount,odcount;
219957b952d6SSatish Balay   int          dcount,kmax,k,nzcount,tmp;
220057b952d6SSatish Balay 
2201d64ed03dSBarry Smith   PetscFunctionBegin;
220257b952d6SSatish Balay   ierr = OptionsGetInt(PETSC_NULL,"-matload_block_size",&bs,&flg);CHKERRQ(ierr);
220357b952d6SSatish Balay 
220457b952d6SSatish Balay   MPI_Comm_size(comm,&size); MPI_Comm_rank(comm,&rank);
220557b952d6SSatish Balay   if (!rank) {
220657b952d6SSatish Balay     ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
2207e5638eb3SBarry Smith     ierr = PetscBinaryRead(fd,(char *)header,4,PETSC_INT); CHKERRQ(ierr);
2208a8c6a408SBarry Smith     if (header[0] != MAT_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"not matrix object");
2209d64ed03dSBarry Smith     if (header[3] < 0) {
2210a8c6a408SBarry Smith       SETERRQ(PETSC_ERR_FILE_UNEXPECTED,1,"Matrix stored in special format, cannot load as MPIBAIJ");
2211d64ed03dSBarry Smith     }
22126c5fab8fSBarry Smith   }
2213d64ed03dSBarry Smith 
2214ca161407SBarry Smith   ierr = MPI_Bcast(header+1,3,MPI_INT,0,comm);CHKERRQ(ierr);
221557b952d6SSatish Balay   M = header[1]; N = header[2];
221657b952d6SSatish Balay 
2217a8c6a408SBarry Smith   if (M != N) SETERRQ(PETSC_ERR_SUP,0,"Can only do square matrices");
221857b952d6SSatish Balay 
221957b952d6SSatish Balay   /*
222057b952d6SSatish Balay      This code adds extra rows to make sure the number of rows is
222157b952d6SSatish Balay      divisible by the blocksize
222257b952d6SSatish Balay   */
222357b952d6SSatish Balay   Mbs        = M/bs;
222457b952d6SSatish Balay   extra_rows = bs - M + bs*(Mbs);
222557b952d6SSatish Balay   if (extra_rows == bs) extra_rows = 0;
222657b952d6SSatish Balay   else                  Mbs++;
222757b952d6SSatish Balay   if (extra_rows &&!rank) {
2228b0267e0aSLois Curfman McInnes     PLogInfo(0,"MatLoad_MPIBAIJ:Padding loaded matrix to match blocksize\n");
222957b952d6SSatish Balay   }
2230537820f0SBarry Smith 
223157b952d6SSatish Balay   /* determine ownership of all rows */
223257b952d6SSatish Balay   mbs = Mbs/size + ((Mbs % size) > rank);
223357b952d6SSatish Balay   m   = mbs * bs;
2234cee3aa6bSSatish Balay   rowners = (int *) PetscMalloc(2*(size+2)*sizeof(int)); CHKPTRQ(rowners);
2235cee3aa6bSSatish Balay   browners = rowners + size + 1;
2236ca161407SBarry Smith   ierr = MPI_Allgather(&mbs,1,MPI_INT,rowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
223757b952d6SSatish Balay   rowners[0] = 0;
2238cee3aa6bSSatish Balay   for ( i=2; i<=size; i++ ) rowners[i] += rowners[i-1];
2239cee3aa6bSSatish Balay   for ( i=0; i<=size;  i++ ) browners[i] = rowners[i]*bs;
224057b952d6SSatish Balay   rstart = rowners[rank];
224157b952d6SSatish Balay   rend   = rowners[rank+1];
224257b952d6SSatish Balay 
224357b952d6SSatish Balay   /* distribute row lengths to all processors */
224457b952d6SSatish Balay   locrowlens = (int*) PetscMalloc( (rend-rstart)*bs*sizeof(int) ); CHKPTRQ(locrowlens);
224557b952d6SSatish Balay   if (!rank) {
224657b952d6SSatish Balay     rowlengths = (int*) PetscMalloc( (M+extra_rows)*sizeof(int) ); CHKPTRQ(rowlengths);
2247e5638eb3SBarry Smith     ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT); CHKERRQ(ierr);
224857b952d6SSatish Balay     for ( i=0; i<extra_rows; i++ ) rowlengths[M+i] = 1;
224957b952d6SSatish Balay     sndcounts = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(sndcounts);
2250cee3aa6bSSatish Balay     for ( i=0; i<size; i++ ) sndcounts[i] = browners[i+1] - browners[i];
2251ca161407SBarry Smith     ierr = MPI_Scatterv(rowlengths,sndcounts,browners,MPI_INT,locrowlens,(rend-rstart)*bs,MPI_INT,0,comm);CHKERRQ(ierr);
225257b952d6SSatish Balay     PetscFree(sndcounts);
2253d64ed03dSBarry Smith   } else {
2254ca161407SBarry Smith     ierr = MPI_Scatterv(0,0,0,MPI_INT,locrowlens,(rend-rstart)*bs,MPI_INT, 0,comm);CHKERRQ(ierr);
225557b952d6SSatish Balay   }
225657b952d6SSatish Balay 
225757b952d6SSatish Balay   if (!rank) {
225857b952d6SSatish Balay     /* calculate the number of nonzeros on each processor */
225957b952d6SSatish Balay     procsnz = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(procsnz);
226057b952d6SSatish Balay     PetscMemzero(procsnz,size*sizeof(int));
226157b952d6SSatish Balay     for ( i=0; i<size; i++ ) {
226257b952d6SSatish Balay       for ( j=rowners[i]*bs; j< rowners[i+1]*bs; j++ ) {
226357b952d6SSatish Balay         procsnz[i] += rowlengths[j];
226457b952d6SSatish Balay       }
226557b952d6SSatish Balay     }
226657b952d6SSatish Balay     PetscFree(rowlengths);
226757b952d6SSatish Balay 
226857b952d6SSatish Balay     /* determine max buffer needed and allocate it */
226957b952d6SSatish Balay     maxnz = 0;
227057b952d6SSatish Balay     for ( i=0; i<size; i++ ) {
227157b952d6SSatish Balay       maxnz = PetscMax(maxnz,procsnz[i]);
227257b952d6SSatish Balay     }
227357b952d6SSatish Balay     cols = (int *) PetscMalloc( maxnz*sizeof(int) ); CHKPTRQ(cols);
227457b952d6SSatish Balay 
227557b952d6SSatish Balay     /* read in my part of the matrix column indices  */
227657b952d6SSatish Balay     nz = procsnz[0];
227757b952d6SSatish Balay     ibuf = (int *) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(ibuf);
227857b952d6SSatish Balay     mycols = ibuf;
2279cee3aa6bSSatish Balay     if (size == 1)  nz -= extra_rows;
2280e5638eb3SBarry Smith     ierr = PetscBinaryRead(fd,mycols,nz,PETSC_INT); CHKERRQ(ierr);
2281cee3aa6bSSatish Balay     if (size == 1)  for (i=0; i< extra_rows; i++) { mycols[nz+i] = M+i; }
2282cee3aa6bSSatish Balay 
228357b952d6SSatish Balay     /* read in every ones (except the last) and ship off */
228457b952d6SSatish Balay     for ( i=1; i<size-1; i++ ) {
228557b952d6SSatish Balay       nz   = procsnz[i];
2286e5638eb3SBarry Smith       ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT); CHKERRQ(ierr);
2287ca161407SBarry Smith       ierr = MPI_Send(cols,nz,MPI_INT,i,tag,comm);CHKERRQ(ierr);
228857b952d6SSatish Balay     }
228957b952d6SSatish Balay     /* read in the stuff for the last proc */
229057b952d6SSatish Balay     if ( size != 1 ) {
229157b952d6SSatish Balay       nz   = procsnz[size-1] - extra_rows;  /* the extra rows are not on the disk */
2292e5638eb3SBarry Smith       ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT); CHKERRQ(ierr);
229357b952d6SSatish Balay       for ( i=0; i<extra_rows; i++ ) cols[nz+i] = M+i;
2294ca161407SBarry Smith       ierr = MPI_Send(cols,nz+extra_rows,MPI_INT,size-1,tag,comm);CHKERRQ(ierr);
229557b952d6SSatish Balay     }
229657b952d6SSatish Balay     PetscFree(cols);
2297d64ed03dSBarry Smith   } else {
229857b952d6SSatish Balay     /* determine buffer space needed for message */
229957b952d6SSatish Balay     nz = 0;
230057b952d6SSatish Balay     for ( i=0; i<m; i++ ) {
230157b952d6SSatish Balay       nz += locrowlens[i];
230257b952d6SSatish Balay     }
230357b952d6SSatish Balay     ibuf   = (int*) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(ibuf);
230457b952d6SSatish Balay     mycols = ibuf;
230557b952d6SSatish Balay     /* receive message of column indices*/
2306ca161407SBarry Smith     ierr = MPI_Recv(mycols,nz,MPI_INT,0,tag,comm,&status);CHKERRQ(ierr);
2307ca161407SBarry Smith     ierr = MPI_Get_count(&status,MPI_INT,&maxnz);CHKERRQ(ierr);
2308a8c6a408SBarry Smith     if (maxnz != nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"something is wrong with file");
230957b952d6SSatish Balay   }
231057b952d6SSatish Balay 
231157b952d6SSatish Balay   /* loop over local rows, determining number of off diagonal entries */
2312cee3aa6bSSatish Balay   dlens  = (int *) PetscMalloc( 2*(rend-rstart+1)*sizeof(int) ); CHKPTRQ(dlens);
2313cee3aa6bSSatish Balay   odlens = dlens + (rend-rstart);
231457b952d6SSatish Balay   mask   = (int *) PetscMalloc( 3*Mbs*sizeof(int) ); CHKPTRQ(mask);
2315cee3aa6bSSatish Balay   PetscMemzero(mask,3*Mbs*sizeof(int));
231657b952d6SSatish Balay   masked1 = mask    + Mbs;
231757b952d6SSatish Balay   masked2 = masked1 + Mbs;
231857b952d6SSatish Balay   rowcount = 0; nzcount = 0;
231957b952d6SSatish Balay   for ( i=0; i<mbs; i++ ) {
232057b952d6SSatish Balay     dcount  = 0;
232157b952d6SSatish Balay     odcount = 0;
232257b952d6SSatish Balay     for ( j=0; j<bs; j++ ) {
232357b952d6SSatish Balay       kmax = locrowlens[rowcount];
232457b952d6SSatish Balay       for ( k=0; k<kmax; k++ ) {
232557b952d6SSatish Balay         tmp = mycols[nzcount++]/bs;
232657b952d6SSatish Balay         if (!mask[tmp]) {
232757b952d6SSatish Balay           mask[tmp] = 1;
232857b952d6SSatish Balay           if (tmp < rstart || tmp >= rend ) masked2[odcount++] = tmp;
232957b952d6SSatish Balay           else masked1[dcount++] = tmp;
233057b952d6SSatish Balay         }
233157b952d6SSatish Balay       }
233257b952d6SSatish Balay       rowcount++;
233357b952d6SSatish Balay     }
2334cee3aa6bSSatish Balay 
233557b952d6SSatish Balay     dlens[i]  = dcount;
233657b952d6SSatish Balay     odlens[i] = odcount;
2337cee3aa6bSSatish Balay 
233857b952d6SSatish Balay     /* zero out the mask elements we set */
233957b952d6SSatish Balay     for ( j=0; j<dcount; j++ ) mask[masked1[j]] = 0;
234057b952d6SSatish Balay     for ( j=0; j<odcount; j++ ) mask[masked2[j]] = 0;
234157b952d6SSatish Balay   }
2342cee3aa6bSSatish Balay 
234357b952d6SSatish Balay   /* create our matrix */
2344537820f0SBarry Smith   ierr = MatCreateMPIBAIJ(comm,bs,m,PETSC_DECIDE,M+extra_rows,N+extra_rows,0,dlens,0,odlens,newmat);
2345537820f0SBarry Smith          CHKERRQ(ierr);
234657b952d6SSatish Balay   A = *newmat;
23476d4a8577SBarry Smith   MatSetOption(A,MAT_COLUMNS_SORTED);
234857b952d6SSatish Balay 
234957b952d6SSatish Balay   if (!rank) {
235057b952d6SSatish Balay     buf = (Scalar *) PetscMalloc( maxnz*sizeof(Scalar) ); CHKPTRQ(buf);
235157b952d6SSatish Balay     /* read in my part of the matrix numerical values  */
235257b952d6SSatish Balay     nz = procsnz[0];
235357b952d6SSatish Balay     vals = buf;
2354cee3aa6bSSatish Balay     mycols = ibuf;
2355cee3aa6bSSatish Balay     if (size == 1)  nz -= extra_rows;
2356e5638eb3SBarry Smith     ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR); CHKERRQ(ierr);
2357cee3aa6bSSatish Balay     if (size == 1)  for (i=0; i< extra_rows; i++) { vals[nz+i] = 1.0; }
2358537820f0SBarry Smith 
235957b952d6SSatish Balay     /* insert into matrix */
236057b952d6SSatish Balay     jj      = rstart*bs;
236157b952d6SSatish Balay     for ( i=0; i<m; i++ ) {
236257b952d6SSatish Balay       ierr = MatSetValues(A,1,&jj,locrowlens[i],mycols,vals,INSERT_VALUES);CHKERRQ(ierr);
236357b952d6SSatish Balay       mycols += locrowlens[i];
236457b952d6SSatish Balay       vals   += locrowlens[i];
236557b952d6SSatish Balay       jj++;
236657b952d6SSatish Balay     }
236757b952d6SSatish Balay     /* read in other processors (except the last one) and ship out */
236857b952d6SSatish Balay     for ( i=1; i<size-1; i++ ) {
236957b952d6SSatish Balay       nz   = procsnz[i];
237057b952d6SSatish Balay       vals = buf;
2371e5638eb3SBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR); CHKERRQ(ierr);
2372ca161407SBarry Smith       ierr = MPI_Send(vals,nz,MPIU_SCALAR,i,A->tag,comm);CHKERRQ(ierr);
237357b952d6SSatish Balay     }
237457b952d6SSatish Balay     /* the last proc */
237557b952d6SSatish Balay     if ( size != 1 ){
237657b952d6SSatish Balay       nz   = procsnz[i] - extra_rows;
2377cee3aa6bSSatish Balay       vals = buf;
2378e5638eb3SBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR); CHKERRQ(ierr);
237957b952d6SSatish Balay       for ( i=0; i<extra_rows; i++ ) vals[nz+i] = 1.0;
2380ca161407SBarry Smith       ierr = MPI_Send(vals,nz+extra_rows,MPIU_SCALAR,size-1,A->tag,comm);CHKERRQ(ierr);
238157b952d6SSatish Balay     }
238257b952d6SSatish Balay     PetscFree(procsnz);
2383d64ed03dSBarry Smith   } else {
238457b952d6SSatish Balay     /* receive numeric values */
238557b952d6SSatish Balay     buf = (Scalar*) PetscMalloc( nz*sizeof(Scalar) ); CHKPTRQ(buf);
238657b952d6SSatish Balay 
238757b952d6SSatish Balay     /* receive message of values*/
238857b952d6SSatish Balay     vals   = buf;
2389cee3aa6bSSatish Balay     mycols = ibuf;
2390ca161407SBarry Smith     ierr   = MPI_Recv(vals,nz,MPIU_SCALAR,0,A->tag,comm,&status);CHKERRQ(ierr);
2391ca161407SBarry Smith     ierr   = MPI_Get_count(&status,MPIU_SCALAR,&maxnz);CHKERRQ(ierr);
2392a8c6a408SBarry Smith     if (maxnz != nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"something is wrong with file");
239357b952d6SSatish Balay 
239457b952d6SSatish Balay     /* insert into matrix */
239557b952d6SSatish Balay     jj      = rstart*bs;
2396cee3aa6bSSatish Balay     for ( i=0; i<m; i++ ) {
239757b952d6SSatish Balay       ierr    = MatSetValues(A,1,&jj,locrowlens[i],mycols,vals,INSERT_VALUES);CHKERRQ(ierr);
239857b952d6SSatish Balay       mycols += locrowlens[i];
239957b952d6SSatish Balay       vals   += locrowlens[i];
240057b952d6SSatish Balay       jj++;
240157b952d6SSatish Balay     }
240257b952d6SSatish Balay   }
240357b952d6SSatish Balay   PetscFree(locrowlens);
240457b952d6SSatish Balay   PetscFree(buf);
240557b952d6SSatish Balay   PetscFree(ibuf);
240657b952d6SSatish Balay   PetscFree(rowners);
240757b952d6SSatish Balay   PetscFree(dlens);
2408cee3aa6bSSatish Balay   PetscFree(mask);
24096d4a8577SBarry Smith   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
24106d4a8577SBarry Smith   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
24113a40ed3dSBarry Smith   PetscFunctionReturn(0);
241257b952d6SSatish Balay }
241357b952d6SSatish Balay 
241457b952d6SSatish Balay 
2415133cdb44SSatish Balay 
2416133cdb44SSatish Balay #undef __FUNC__
2417133cdb44SSatish Balay #define __FUNC__ "MatMPIBAIJSetHashTableFactor"
2418133cdb44SSatish Balay /*@
2419133cdb44SSatish Balay    MatMPIBAIJSetHashTableFactor - Sets the factor required to compute the size of the HashTable.
2420133cdb44SSatish Balay 
2421133cdb44SSatish Balay    Input Parameters:
2422133cdb44SSatish Balay .  mat  - the matrix
2423133cdb44SSatish Balay .  fact - factor
2424133cdb44SSatish Balay 
2425fee21e36SBarry Smith    Collective on Mat
2426fee21e36SBarry Smith 
2427133cdb44SSatish Balay   Notes:
2428133cdb44SSatish Balay    This can also be set by the command line option: -mat_use_hash_table fact
2429133cdb44SSatish Balay 
2430133cdb44SSatish Balay .keywords: matrix, hashtable, factor, HT
2431133cdb44SSatish Balay 
2432133cdb44SSatish Balay .seealso: MatSetOption()
2433133cdb44SSatish Balay @*/
2434133cdb44SSatish Balay int MatMPIBAIJSetHashTableFactor(Mat mat,double fact)
2435133cdb44SSatish Balay {
243625fdafccSSatish Balay   Mat_MPIBAIJ *baij;
2437133cdb44SSatish Balay 
2438133cdb44SSatish Balay   PetscFunctionBegin;
2439133cdb44SSatish Balay   PetscValidHeaderSpecific(mat,MAT_COOKIE);
244025fdafccSSatish Balay   if (mat->type != MATMPIBAIJ) {
2441133cdb44SSatish Balay       SETERRQ(PETSC_ERR_ARG_WRONG,1,"Incorrect matrix type. Use MPIBAIJ only.");
2442133cdb44SSatish Balay   }
2443133cdb44SSatish Balay   baij = (Mat_MPIBAIJ*) mat->data;
2444133cdb44SSatish Balay   baij->ht_fact = fact;
2445133cdb44SSatish Balay   PetscFunctionReturn(0);
2446133cdb44SSatish Balay }
2447