xref: /petsc/src/mat/impls/dense/mpi/mpidense.c (revision 44cd7ae7fed5c695df79898b8d65e4c9e6fe6909)
18965ea79SLois Curfman McInnes #ifndef lint
2*44cd7ae7SLois Curfman McInnes static char vcid[] = "$Id: mpidense.c,v 1.36 1996/03/23 20:42:28 bsmith Exp curfman $";
38965ea79SLois Curfman McInnes #endif
48965ea79SLois Curfman McInnes 
5ed3cc1f0SBarry Smith /*
6ed3cc1f0SBarry Smith    Basic functions for basic parallel dense matrices.
7ed3cc1f0SBarry Smith */
8ed3cc1f0SBarry Smith 
98965ea79SLois Curfman McInnes #include "mpidense.h"
108965ea79SLois Curfman McInnes #include "vec/vecimpl.h"
118965ea79SLois Curfman McInnes 
1239ddd567SLois Curfman McInnes static int MatSetValues_MPIDense(Mat mat,int m,int *idxm,int n,
138965ea79SLois Curfman McInnes                                int *idxn,Scalar *v,InsertMode addv)
148965ea79SLois Curfman McInnes {
1539b7565bSBarry Smith   Mat_MPIDense *A = (Mat_MPIDense *) mat->data;
1639b7565bSBarry Smith   int          ierr, i, j, rstart = A->rstart, rend = A->rend, row;
1739b7565bSBarry Smith   int          roworiented = A->roworiented;
188965ea79SLois Curfman McInnes 
1939b7565bSBarry Smith   if (A->insertmode != NOT_SET_VALUES && A->insertmode != addv) {
2039ddd567SLois Curfman McInnes     SETERRQ(1,"MatSetValues_MPIDense:Cannot mix inserts and adds");
218965ea79SLois Curfman McInnes   }
2239b7565bSBarry Smith   A->insertmode = addv;
238965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
2439ddd567SLois Curfman McInnes     if (idxm[i] < 0) SETERRQ(1,"MatSetValues_MPIDense:Negative row");
2539b7565bSBarry Smith     if (idxm[i] >= A->M) SETERRQ(1,"MatSetValues_MPIDense:Row too large");
268965ea79SLois Curfman McInnes     if (idxm[i] >= rstart && idxm[i] < rend) {
278965ea79SLois Curfman McInnes       row = idxm[i] - rstart;
2839b7565bSBarry Smith       if (roworiented) {
2939b7565bSBarry Smith         ierr = MatSetValues(A->A,1,&row,n,idxn,v+i*n,addv); CHKERRQ(ierr);
3039b7565bSBarry Smith       }
3139b7565bSBarry Smith       else {
328965ea79SLois Curfman McInnes         for ( j=0; j<n; j++ ) {
3339ddd567SLois Curfman McInnes           if (idxn[j] < 0) SETERRQ(1,"MatSetValues_MPIDense:Negative column");
3439b7565bSBarry Smith           if (idxn[j] >= A->N) SETERRQ(1,"MatSetValues_MPIDense:Column too large");
3539b7565bSBarry Smith           ierr = MatSetValues(A->A,1,&row,1,&idxn[j],v+i+j*m,addv); CHKERRQ(ierr);
3639b7565bSBarry Smith         }
378965ea79SLois Curfman McInnes       }
388965ea79SLois Curfman McInnes     }
398965ea79SLois Curfman McInnes     else {
4039b7565bSBarry Smith       if (roworiented) {
4139b7565bSBarry Smith         ierr = StashValues_Private(&A->stash,idxm[i],n,idxn,v+i*n,addv); CHKERRQ(ierr);
4239b7565bSBarry Smith       }
4339b7565bSBarry Smith       else { /* must stash each seperately */
4439b7565bSBarry Smith         row = idxm[i];
4539b7565bSBarry Smith         for ( j=0; j<n; j++ ) {
4639b7565bSBarry Smith           ierr = StashValues_Private(&A->stash,row,1,&idxn[j],v+i+j*m,addv);
4739b7565bSBarry Smith                  CHKERRQ(ierr);
4839b7565bSBarry Smith         }
4939b7565bSBarry Smith       }
50b49de8d1SLois Curfman McInnes     }
51b49de8d1SLois Curfman McInnes   }
52b49de8d1SLois Curfman McInnes   return 0;
53b49de8d1SLois Curfman McInnes }
54b49de8d1SLois Curfman McInnes 
55b49de8d1SLois Curfman McInnes static int MatGetValues_MPIDense(Mat mat,int m,int *idxm,int n,int *idxn,Scalar *v)
56b49de8d1SLois Curfman McInnes {
57b49de8d1SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
58b49de8d1SLois Curfman McInnes   int          ierr, i, j, rstart = mdn->rstart, rend = mdn->rend, row;
59b49de8d1SLois Curfman McInnes 
60b49de8d1SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
61b49de8d1SLois Curfman McInnes     if (idxm[i] < 0) SETERRQ(1,"MatGetValues_MPIDense:Negative row");
62b49de8d1SLois Curfman McInnes     if (idxm[i] >= mdn->M) SETERRQ(1,"MatGetValues_MPIDense:Row too large");
63b49de8d1SLois Curfman McInnes     if (idxm[i] >= rstart && idxm[i] < rend) {
64b49de8d1SLois Curfman McInnes       row = idxm[i] - rstart;
65b49de8d1SLois Curfman McInnes       for ( j=0; j<n; j++ ) {
66b49de8d1SLois Curfman McInnes         if (idxn[j] < 0) SETERRQ(1,"MatGetValues_MPIDense:Negative column");
67b49de8d1SLois Curfman McInnes         if (idxn[j] >= mdn->N)
68b49de8d1SLois Curfman McInnes           SETERRQ(1,"MatGetValues_MPIDense:Column too large");
69b49de8d1SLois Curfman McInnes         ierr = MatGetValues(mdn->A,1,&row,1,&idxn[j],v+i*n+j); CHKERRQ(ierr);
70b49de8d1SLois Curfman McInnes       }
71b49de8d1SLois Curfman McInnes     }
72b49de8d1SLois Curfman McInnes     else {
73b49de8d1SLois Curfman McInnes       SETERRQ(1,"MatGetValues_MPIDense:Only local values currently supported");
748965ea79SLois Curfman McInnes     }
758965ea79SLois Curfman McInnes   }
768965ea79SLois Curfman McInnes   return 0;
778965ea79SLois Curfman McInnes }
788965ea79SLois Curfman McInnes 
79ff14e315SSatish Balay static int MatGetArray_MPIDense(Mat A,Scalar **array)
80ff14e315SSatish Balay {
81ff14e315SSatish Balay   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
82ff14e315SSatish Balay   int ierr;
83ff14e315SSatish Balay 
84ff14e315SSatish Balay   ierr = MatGetArray(a->A,array); CHKERRQ(ierr);
85ff14e315SSatish Balay   return 0;
86ff14e315SSatish Balay }
87ff14e315SSatish Balay 
88ff14e315SSatish Balay static int MatRestoreArray_MPIDense(Mat A,Scalar **array)
89ff14e315SSatish Balay {
90ff14e315SSatish Balay   return 0;
91ff14e315SSatish Balay }
92ff14e315SSatish Balay 
9339ddd567SLois Curfman McInnes static int MatAssemblyBegin_MPIDense(Mat mat,MatAssemblyType mode)
948965ea79SLois Curfman McInnes {
9539ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
968965ea79SLois Curfman McInnes   MPI_Comm     comm = mat->comm;
9739ddd567SLois Curfman McInnes   int          size = mdn->size, *owners = mdn->rowners, rank = mdn->rank;
988965ea79SLois Curfman McInnes   int          *nprocs,i,j,idx,*procs,nsends,nreceives,nmax,*work;
9939ddd567SLois Curfman McInnes   int          tag = mat->tag, *owner,*starts,count,ierr;
1008965ea79SLois Curfman McInnes   InsertMode   addv;
10139ddd567SLois Curfman McInnes   MPI_Request  *send_waits,*recv_waits;
1028965ea79SLois Curfman McInnes   Scalar       *rvalues,*svalues;
1038965ea79SLois Curfman McInnes 
1048965ea79SLois Curfman McInnes   /* make sure all processors are either in INSERTMODE or ADDMODE */
1056d84be18SBarry Smith   MPI_Allreduce(&mdn->insertmode,&addv,1,MPI_INT,MPI_BOR,comm);
10639ddd567SLois Curfman McInnes   if (addv == (ADD_VALUES|INSERT_VALUES)) { SETERRQ(1,
10739ddd567SLois Curfman McInnes     "MatAssemblyBegin_MPIDense:Cannot mix adds/inserts on different procs");
1088965ea79SLois Curfman McInnes     }
10939ddd567SLois Curfman McInnes   mdn->insertmode = addv; /* in case this processor had no cache */
1108965ea79SLois Curfman McInnes 
1118965ea79SLois Curfman McInnes   /*  first count number of contributors to each processor */
1120452661fSBarry Smith   nprocs = (int *) PetscMalloc( 2*size*sizeof(int) ); CHKPTRQ(nprocs);
113cddf8d76SBarry Smith   PetscMemzero(nprocs,2*size*sizeof(int)); procs = nprocs + size;
1140452661fSBarry Smith   owner = (int *) PetscMalloc( (mdn->stash.n+1)*sizeof(int) ); CHKPTRQ(owner);
11539ddd567SLois Curfman McInnes   for ( i=0; i<mdn->stash.n; i++ ) {
11639ddd567SLois Curfman McInnes     idx = mdn->stash.idx[i];
1178965ea79SLois Curfman McInnes     for ( j=0; j<size; j++ ) {
1188965ea79SLois Curfman McInnes       if (idx >= owners[j] && idx < owners[j+1]) {
1198965ea79SLois Curfman McInnes         nprocs[j]++; procs[j] = 1; owner[i] = j; break;
1208965ea79SLois Curfman McInnes       }
1218965ea79SLois Curfman McInnes     }
1228965ea79SLois Curfman McInnes   }
1238965ea79SLois Curfman McInnes   nsends = 0;  for ( i=0; i<size; i++ ) { nsends += procs[i];}
1248965ea79SLois Curfman McInnes 
1258965ea79SLois Curfman McInnes   /* inform other processors of number of messages and max length*/
1260452661fSBarry Smith   work = (int *) PetscMalloc( size*sizeof(int) ); CHKPTRQ(work);
1276d84be18SBarry Smith   MPI_Allreduce(procs,work,size,MPI_INT,MPI_SUM,comm);
1288965ea79SLois Curfman McInnes   nreceives = work[rank];
1296d84be18SBarry Smith   MPI_Allreduce(nprocs,work,size,MPI_INT,MPI_MAX,comm);
1308965ea79SLois Curfman McInnes   nmax = work[rank];
1310452661fSBarry Smith   PetscFree(work);
1328965ea79SLois Curfman McInnes 
1338965ea79SLois Curfman McInnes   /* post receives:
1348965ea79SLois Curfman McInnes        1) each message will consist of ordered pairs
1358965ea79SLois Curfman McInnes      (global index,value) we store the global index as a double
1368965ea79SLois Curfman McInnes      to simplify the message passing.
1378965ea79SLois Curfman McInnes        2) since we don't know how long each individual message is we
1388965ea79SLois Curfman McInnes      allocate the largest needed buffer for each receive. Potentially
1398965ea79SLois Curfman McInnes      this is a lot of wasted space.
1408965ea79SLois Curfman McInnes 
1418965ea79SLois Curfman McInnes        This could be done better.
1428965ea79SLois Curfman McInnes   */
1430452661fSBarry Smith   rvalues = (Scalar *) PetscMalloc(3*(nreceives+1)*(nmax+1)*sizeof(Scalar));
1448965ea79SLois Curfman McInnes   CHKPTRQ(rvalues);
1450452661fSBarry Smith   recv_waits = (MPI_Request *) PetscMalloc((nreceives+1)*sizeof(MPI_Request));
1468965ea79SLois Curfman McInnes   CHKPTRQ(recv_waits);
1478965ea79SLois Curfman McInnes   for ( i=0; i<nreceives; i++ ) {
1486d84be18SBarry Smith     MPI_Irecv(rvalues+3*nmax*i,3*nmax,MPIU_SCALAR,MPI_ANY_SOURCE,tag,
1498965ea79SLois Curfman McInnes               comm,recv_waits+i);
1508965ea79SLois Curfman McInnes   }
1518965ea79SLois Curfman McInnes 
1528965ea79SLois Curfman McInnes   /* do sends:
1538965ea79SLois Curfman McInnes       1) starts[i] gives the starting index in svalues for stuff going to
1548965ea79SLois Curfman McInnes          the ith processor
1558965ea79SLois Curfman McInnes   */
1560452661fSBarry Smith   svalues = (Scalar *) PetscMalloc( 3*(mdn->stash.n+1)*sizeof(Scalar) );
15739ddd567SLois Curfman McInnes   CHKPTRQ(svalues);
1580452661fSBarry Smith   send_waits = (MPI_Request *) PetscMalloc( (nsends+1)*sizeof(MPI_Request));
1598965ea79SLois Curfman McInnes   CHKPTRQ(send_waits);
1600452661fSBarry Smith   starts = (int *) PetscMalloc( size*sizeof(int) ); CHKPTRQ(starts);
1618965ea79SLois Curfman McInnes   starts[0] = 0;
1628965ea79SLois Curfman McInnes   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
16339ddd567SLois Curfman McInnes   for ( i=0; i<mdn->stash.n; i++ ) {
16439ddd567SLois Curfman McInnes     svalues[3*starts[owner[i]]]       = (Scalar)  mdn->stash.idx[i];
16539ddd567SLois Curfman McInnes     svalues[3*starts[owner[i]]+1]     = (Scalar)  mdn->stash.idy[i];
16639ddd567SLois Curfman McInnes     svalues[3*(starts[owner[i]]++)+2] =  mdn->stash.array[i];
1678965ea79SLois Curfman McInnes   }
1680452661fSBarry Smith   PetscFree(owner);
1698965ea79SLois Curfman McInnes   starts[0] = 0;
1708965ea79SLois Curfman McInnes   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
1718965ea79SLois Curfman McInnes   count = 0;
1728965ea79SLois Curfman McInnes   for ( i=0; i<size; i++ ) {
1738965ea79SLois Curfman McInnes     if (procs[i]) {
1746d84be18SBarry Smith       MPI_Isend(svalues+3*starts[i],3*nprocs[i],MPIU_SCALAR,i,tag,
1758965ea79SLois Curfman McInnes                 comm,send_waits+count++);
1768965ea79SLois Curfman McInnes     }
1778965ea79SLois Curfman McInnes   }
1780452661fSBarry Smith   PetscFree(starts); PetscFree(nprocs);
1798965ea79SLois Curfman McInnes 
1808965ea79SLois Curfman McInnes   /* Free cache space */
18139ddd567SLois Curfman McInnes   ierr = StashDestroy_Private(&mdn->stash); CHKERRQ(ierr);
1828965ea79SLois Curfman McInnes 
18339ddd567SLois Curfman McInnes   mdn->svalues    = svalues;    mdn->rvalues = rvalues;
18439ddd567SLois Curfman McInnes   mdn->nsends     = nsends;     mdn->nrecvs = nreceives;
18539ddd567SLois Curfman McInnes   mdn->send_waits = send_waits; mdn->recv_waits = recv_waits;
18639ddd567SLois Curfman McInnes   mdn->rmax       = nmax;
1878965ea79SLois Curfman McInnes 
1888965ea79SLois Curfman McInnes   return 0;
1898965ea79SLois Curfman McInnes }
19039ddd567SLois Curfman McInnes extern int MatSetUpMultiply_MPIDense(Mat);
1918965ea79SLois Curfman McInnes 
19239ddd567SLois Curfman McInnes static int MatAssemblyEnd_MPIDense(Mat mat,MatAssemblyType mode)
1938965ea79SLois Curfman McInnes {
19439ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
1958965ea79SLois Curfman McInnes   MPI_Status   *send_status,recv_status;
19639ddd567SLois Curfman McInnes   int          imdex, nrecvs=mdn->nrecvs, count=nrecvs, i, n, ierr, row, col;
1978965ea79SLois Curfman McInnes   Scalar       *values,val;
19839ddd567SLois Curfman McInnes   InsertMode   addv = mdn->insertmode;
1998965ea79SLois Curfman McInnes 
2008965ea79SLois Curfman McInnes   /*  wait on receives */
2018965ea79SLois Curfman McInnes   while (count) {
20239ddd567SLois Curfman McInnes     MPI_Waitany(nrecvs,mdn->recv_waits,&imdex,&recv_status);
2038965ea79SLois Curfman McInnes     /* unpack receives into our local space */
20439ddd567SLois Curfman McInnes     values = mdn->rvalues + 3*imdex*mdn->rmax;
2058965ea79SLois Curfman McInnes     MPI_Get_count(&recv_status,MPIU_SCALAR,&n);
2068965ea79SLois Curfman McInnes     n = n/3;
2078965ea79SLois Curfman McInnes     for ( i=0; i<n; i++ ) {
208227d817aSBarry Smith       row = (int) PetscReal(values[3*i]) - mdn->rstart;
209227d817aSBarry Smith       col = (int) PetscReal(values[3*i+1]);
2108965ea79SLois Curfman McInnes       val = values[3*i+2];
21139ddd567SLois Curfman McInnes       if (col >= 0 && col < mdn->N) {
21239ddd567SLois Curfman McInnes         MatSetValues(mdn->A,1,&row,1,&col,&val,addv);
2138965ea79SLois Curfman McInnes       }
21439ddd567SLois Curfman McInnes       else {SETERRQ(1,"MatAssemblyEnd_MPIDense:Invalid column");}
2158965ea79SLois Curfman McInnes     }
2168965ea79SLois Curfman McInnes     count--;
2178965ea79SLois Curfman McInnes   }
2180452661fSBarry Smith   PetscFree(mdn->recv_waits); PetscFree(mdn->rvalues);
2198965ea79SLois Curfman McInnes 
2208965ea79SLois Curfman McInnes   /* wait on sends */
22139ddd567SLois Curfman McInnes   if (mdn->nsends) {
2220452661fSBarry Smith     send_status = (MPI_Status *) PetscMalloc( mdn->nsends*sizeof(MPI_Status) );
2238965ea79SLois Curfman McInnes     CHKPTRQ(send_status);
22439ddd567SLois Curfman McInnes     MPI_Waitall(mdn->nsends,mdn->send_waits,send_status);
2250452661fSBarry Smith     PetscFree(send_status);
2268965ea79SLois Curfman McInnes   }
2270452661fSBarry Smith   PetscFree(mdn->send_waits); PetscFree(mdn->svalues);
2288965ea79SLois Curfman McInnes 
22939ddd567SLois Curfman McInnes   mdn->insertmode = NOT_SET_VALUES;
23039ddd567SLois Curfman McInnes   ierr = MatAssemblyBegin(mdn->A,mode); CHKERRQ(ierr);
23139ddd567SLois Curfman McInnes   ierr = MatAssemblyEnd(mdn->A,mode); CHKERRQ(ierr);
2328965ea79SLois Curfman McInnes 
233227d817aSBarry Smith   if (!mat->was_assembled && mode == FINAL_ASSEMBLY) {
23439ddd567SLois Curfman McInnes     ierr = MatSetUpMultiply_MPIDense(mat); CHKERRQ(ierr);
2358965ea79SLois Curfman McInnes   }
2368965ea79SLois Curfman McInnes   return 0;
2378965ea79SLois Curfman McInnes }
2388965ea79SLois Curfman McInnes 
23939ddd567SLois Curfman McInnes static int MatZeroEntries_MPIDense(Mat A)
2408965ea79SLois Curfman McInnes {
24139ddd567SLois Curfman McInnes   Mat_MPIDense *l = (Mat_MPIDense *) A->data;
24239ddd567SLois Curfman McInnes   return MatZeroEntries(l->A);
2438965ea79SLois Curfman McInnes }
2448965ea79SLois Curfman McInnes 
2458965ea79SLois Curfman McInnes /* the code does not do the diagonal entries correctly unless the
2468965ea79SLois Curfman McInnes    matrix is square and the column and row owerships are identical.
2478965ea79SLois Curfman McInnes    This is a BUG. The only way to fix it seems to be to access
2483501a2bdSLois Curfman McInnes    mdn->A and mdn->B directly and not through the MatZeroRows()
2498965ea79SLois Curfman McInnes    routine.
2508965ea79SLois Curfman McInnes */
25139ddd567SLois Curfman McInnes static int MatZeroRows_MPIDense(Mat A,IS is,Scalar *diag)
2528965ea79SLois Curfman McInnes {
25339ddd567SLois Curfman McInnes   Mat_MPIDense   *l = (Mat_MPIDense *) A->data;
2548965ea79SLois Curfman McInnes   int            i,ierr,N, *rows,*owners = l->rowners,size = l->size;
2558965ea79SLois Curfman McInnes   int            *procs,*nprocs,j,found,idx,nsends,*work;
2568965ea79SLois Curfman McInnes   int            nmax,*svalues,*starts,*owner,nrecvs,rank = l->rank;
2578965ea79SLois Curfman McInnes   int            *rvalues,tag = A->tag,count,base,slen,n,*source;
2588965ea79SLois Curfman McInnes   int            *lens,imdex,*lrows,*values;
2598965ea79SLois Curfman McInnes   MPI_Comm       comm = A->comm;
2608965ea79SLois Curfman McInnes   MPI_Request    *send_waits,*recv_waits;
2618965ea79SLois Curfman McInnes   MPI_Status     recv_status,*send_status;
2628965ea79SLois Curfman McInnes   IS             istmp;
2638965ea79SLois Curfman McInnes 
26477c4ece6SBarry Smith   ierr = ISGetSize(is,&N); CHKERRQ(ierr);
2658965ea79SLois Curfman McInnes   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
2668965ea79SLois Curfman McInnes 
2678965ea79SLois Curfman McInnes   /*  first count number of contributors to each processor */
2680452661fSBarry Smith   nprocs = (int *) PetscMalloc( 2*size*sizeof(int) ); CHKPTRQ(nprocs);
269cddf8d76SBarry Smith   PetscMemzero(nprocs,2*size*sizeof(int)); procs = nprocs + size;
2700452661fSBarry Smith   owner = (int *) PetscMalloc((N+1)*sizeof(int)); CHKPTRQ(owner); /* see note*/
2718965ea79SLois Curfman McInnes   for ( i=0; i<N; i++ ) {
2728965ea79SLois Curfman McInnes     idx = rows[i];
2738965ea79SLois Curfman McInnes     found = 0;
2748965ea79SLois Curfman McInnes     for ( j=0; j<size; j++ ) {
2758965ea79SLois Curfman McInnes       if (idx >= owners[j] && idx < owners[j+1]) {
2768965ea79SLois Curfman McInnes         nprocs[j]++; procs[j] = 1; owner[i] = j; found = 1; break;
2778965ea79SLois Curfman McInnes       }
2788965ea79SLois Curfman McInnes     }
27939ddd567SLois Curfman McInnes     if (!found) SETERRQ(1,"MatZeroRows_MPIDense:Index out of range");
2808965ea79SLois Curfman McInnes   }
2818965ea79SLois Curfman McInnes   nsends = 0;  for ( i=0; i<size; i++ ) { nsends += procs[i];}
2828965ea79SLois Curfman McInnes 
2838965ea79SLois Curfman McInnes   /* inform other processors of number of messages and max length*/
2840452661fSBarry Smith   work = (int *) PetscMalloc( size*sizeof(int) ); CHKPTRQ(work);
2858965ea79SLois Curfman McInnes   MPI_Allreduce( procs, work,size,MPI_INT,MPI_SUM,comm);
2868965ea79SLois Curfman McInnes   nrecvs = work[rank];
2878965ea79SLois Curfman McInnes   MPI_Allreduce( nprocs, work,size,MPI_INT,MPI_MAX,comm);
2888965ea79SLois Curfman McInnes   nmax = work[rank];
2890452661fSBarry Smith   PetscFree(work);
2908965ea79SLois Curfman McInnes 
2918965ea79SLois Curfman McInnes   /* post receives:   */
2920452661fSBarry Smith   rvalues = (int *) PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(int)); /*see note */
2938965ea79SLois Curfman McInnes   CHKPTRQ(rvalues);
2940452661fSBarry Smith   recv_waits = (MPI_Request *) PetscMalloc((nrecvs+1)*sizeof(MPI_Request));
2958965ea79SLois Curfman McInnes   CHKPTRQ(recv_waits);
2968965ea79SLois Curfman McInnes   for ( i=0; i<nrecvs; i++ ) {
2978965ea79SLois Curfman McInnes     MPI_Irecv(rvalues+nmax*i,nmax,MPI_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);
2988965ea79SLois Curfman McInnes   }
2998965ea79SLois Curfman McInnes 
3008965ea79SLois Curfman McInnes   /* do sends:
3018965ea79SLois Curfman McInnes       1) starts[i] gives the starting index in svalues for stuff going to
3028965ea79SLois Curfman McInnes          the ith processor
3038965ea79SLois Curfman McInnes   */
3040452661fSBarry Smith   svalues = (int *) PetscMalloc( (N+1)*sizeof(int) ); CHKPTRQ(svalues);
3050452661fSBarry Smith   send_waits = (MPI_Request *) PetscMalloc( (nsends+1)*sizeof(MPI_Request));
3068965ea79SLois Curfman McInnes   CHKPTRQ(send_waits);
3070452661fSBarry Smith   starts = (int *) PetscMalloc( (size+1)*sizeof(int) ); CHKPTRQ(starts);
3088965ea79SLois Curfman McInnes   starts[0] = 0;
3098965ea79SLois Curfman McInnes   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
3108965ea79SLois Curfman McInnes   for ( i=0; i<N; i++ ) {
3118965ea79SLois Curfman McInnes     svalues[starts[owner[i]]++] = rows[i];
3128965ea79SLois Curfman McInnes   }
3138965ea79SLois Curfman McInnes   ISRestoreIndices(is,&rows);
3148965ea79SLois Curfman McInnes 
3158965ea79SLois Curfman McInnes   starts[0] = 0;
3168965ea79SLois Curfman McInnes   for ( i=1; i<size+1; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
3178965ea79SLois Curfman McInnes   count = 0;
3188965ea79SLois Curfman McInnes   for ( i=0; i<size; i++ ) {
3198965ea79SLois Curfman McInnes     if (procs[i]) {
3208965ea79SLois Curfman McInnes       MPI_Isend(svalues+starts[i],nprocs[i],MPI_INT,i,tag,comm,send_waits+count++);
3218965ea79SLois Curfman McInnes     }
3228965ea79SLois Curfman McInnes   }
3230452661fSBarry Smith   PetscFree(starts);
3248965ea79SLois Curfman McInnes 
3258965ea79SLois Curfman McInnes   base = owners[rank];
3268965ea79SLois Curfman McInnes 
3278965ea79SLois Curfman McInnes   /*  wait on receives */
3280452661fSBarry Smith   lens   = (int *) PetscMalloc( 2*(nrecvs+1)*sizeof(int) ); CHKPTRQ(lens);
3298965ea79SLois Curfman McInnes   source = lens + nrecvs;
3308965ea79SLois Curfman McInnes   count  = nrecvs; slen = 0;
3318965ea79SLois Curfman McInnes   while (count) {
3328965ea79SLois Curfman McInnes     MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);
3338965ea79SLois Curfman McInnes     /* unpack receives into our local space */
3348965ea79SLois Curfman McInnes     MPI_Get_count(&recv_status,MPI_INT,&n);
3358965ea79SLois Curfman McInnes     source[imdex]  = recv_status.MPI_SOURCE;
3368965ea79SLois Curfman McInnes     lens[imdex]  = n;
3378965ea79SLois Curfman McInnes     slen += n;
3388965ea79SLois Curfman McInnes     count--;
3398965ea79SLois Curfman McInnes   }
3400452661fSBarry Smith   PetscFree(recv_waits);
3418965ea79SLois Curfman McInnes 
3428965ea79SLois Curfman McInnes   /* move the data into the send scatter */
3430452661fSBarry Smith   lrows = (int *) PetscMalloc( (slen+1)*sizeof(int) ); CHKPTRQ(lrows);
3448965ea79SLois Curfman McInnes   count = 0;
3458965ea79SLois Curfman McInnes   for ( i=0; i<nrecvs; i++ ) {
3468965ea79SLois Curfman McInnes     values = rvalues + i*nmax;
3478965ea79SLois Curfman McInnes     for ( j=0; j<lens[i]; j++ ) {
3488965ea79SLois Curfman McInnes       lrows[count++] = values[j] - base;
3498965ea79SLois Curfman McInnes     }
3508965ea79SLois Curfman McInnes   }
3510452661fSBarry Smith   PetscFree(rvalues); PetscFree(lens);
3520452661fSBarry Smith   PetscFree(owner); PetscFree(nprocs);
3538965ea79SLois Curfman McInnes 
3548965ea79SLois Curfman McInnes   /* actually zap the local rows */
3558965ea79SLois Curfman McInnes   ierr = ISCreateSeq(MPI_COMM_SELF,slen,lrows,&istmp);CHKERRQ(ierr);
3568965ea79SLois Curfman McInnes   PLogObjectParent(A,istmp);
3570452661fSBarry Smith   PetscFree(lrows);
3588965ea79SLois Curfman McInnes   ierr = MatZeroRows(l->A,istmp,diag); CHKERRQ(ierr);
3598965ea79SLois Curfman McInnes   ierr = ISDestroy(istmp); CHKERRQ(ierr);
3608965ea79SLois Curfman McInnes 
3618965ea79SLois Curfman McInnes   /* wait on sends */
3628965ea79SLois Curfman McInnes   if (nsends) {
3630452661fSBarry Smith     send_status = (MPI_Status *) PetscMalloc(nsends*sizeof(MPI_Status));
3648965ea79SLois Curfman McInnes     CHKPTRQ(send_status);
3658965ea79SLois Curfman McInnes     MPI_Waitall(nsends,send_waits,send_status);
3660452661fSBarry Smith     PetscFree(send_status);
3678965ea79SLois Curfman McInnes   }
3680452661fSBarry Smith   PetscFree(send_waits); PetscFree(svalues);
3698965ea79SLois Curfman McInnes 
3708965ea79SLois Curfman McInnes   return 0;
3718965ea79SLois Curfman McInnes }
3728965ea79SLois Curfman McInnes 
373*44cd7ae7SLois Curfman McInnes extern int MatMult_SeqDense(Mat A,Vec,Vec);
374*44cd7ae7SLois Curfman McInnes extern int MatMultAdd_SeqDense(Mat A,Vec,Vec,Vec);
375*44cd7ae7SLois Curfman McInnes extern int MatMultTrans_SeqDense(Mat A,Vec,Vec);
376*44cd7ae7SLois Curfman McInnes extern int MatMultTransAdd_SeqDense(Mat A,Vec,Vec,Vec);
37739ddd567SLois Curfman McInnes static int MatMult_MPIDense(Mat mat,Vec xx,Vec yy)
3788965ea79SLois Curfman McInnes {
37939ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3808965ea79SLois Curfman McInnes   int          ierr;
381c456f294SBarry Smith 
38239ddd567SLois Curfman McInnes   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_ALL,mdn->Mvctx);
38339ddd567SLois Curfman McInnes   CHKERRQ(ierr);
38439ddd567SLois Curfman McInnes   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_ALL,mdn->Mvctx);
38539ddd567SLois Curfman McInnes   CHKERRQ(ierr);
386*44cd7ae7SLois Curfman McInnes   ierr = MatMult_SeqDense(mdn->A,mdn->lvec,yy); CHKERRQ(ierr);
3878965ea79SLois Curfman McInnes   return 0;
3888965ea79SLois Curfman McInnes }
3898965ea79SLois Curfman McInnes 
39039ddd567SLois Curfman McInnes static int MatMultAdd_MPIDense(Mat mat,Vec xx,Vec yy,Vec zz)
3918965ea79SLois Curfman McInnes {
39239ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3938965ea79SLois Curfman McInnes   int          ierr;
394c456f294SBarry Smith 
395c456f294SBarry Smith   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_ALL,mdn->Mvctx);CHKERRQ(ierr);
396c456f294SBarry Smith   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_ALL,mdn->Mvctx);CHKERRQ(ierr);
397*44cd7ae7SLois Curfman McInnes   ierr = MatMultAdd_SeqDense(mdn->A,mdn->lvec,yy,zz); CHKERRQ(ierr);
3988965ea79SLois Curfman McInnes   return 0;
3998965ea79SLois Curfman McInnes }
4008965ea79SLois Curfman McInnes 
401096963f5SLois Curfman McInnes static int MatMultTrans_MPIDense(Mat A,Vec xx,Vec yy)
402096963f5SLois Curfman McInnes {
403096963f5SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
404096963f5SLois Curfman McInnes   int          ierr;
4053501a2bdSLois Curfman McInnes   Scalar       zero = 0.0;
406096963f5SLois Curfman McInnes 
4073501a2bdSLois Curfman McInnes   ierr = VecSet(&zero,yy); CHKERRQ(ierr);
408*44cd7ae7SLois Curfman McInnes   ierr = MatMultTrans_SeqDense(a->A,xx,a->lvec); CHKERRQ(ierr);
409096963f5SLois Curfman McInnes   ierr = VecScatterBegin(a->lvec,yy,ADD_VALUES,
410096963f5SLois Curfman McInnes          (ScatterMode)(SCATTER_ALL|SCATTER_REVERSE),a->Mvctx); CHKERRQ(ierr);
411096963f5SLois Curfman McInnes   ierr = VecScatterEnd(a->lvec,yy,ADD_VALUES,
412096963f5SLois Curfman McInnes          (ScatterMode)(SCATTER_ALL|SCATTER_REVERSE),a->Mvctx); CHKERRQ(ierr);
413096963f5SLois Curfman McInnes   return 0;
414096963f5SLois Curfman McInnes }
415096963f5SLois Curfman McInnes 
416096963f5SLois Curfman McInnes static int MatMultTransAdd_MPIDense(Mat A,Vec xx,Vec yy,Vec zz)
417096963f5SLois Curfman McInnes {
418096963f5SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
419096963f5SLois Curfman McInnes   int          ierr;
420096963f5SLois Curfman McInnes 
4213501a2bdSLois Curfman McInnes   ierr = VecCopy(yy,zz); CHKERRQ(ierr);
422*44cd7ae7SLois Curfman McInnes   ierr = MatMultTrans_SeqDense(a->A,xx,a->lvec); CHKERRQ(ierr);
423096963f5SLois Curfman McInnes   ierr = VecScatterBegin(a->lvec,zz,ADD_VALUES,
424096963f5SLois Curfman McInnes          (ScatterMode)(SCATTER_ALL|SCATTER_REVERSE),a->Mvctx); CHKERRQ(ierr);
425096963f5SLois Curfman McInnes   ierr = VecScatterEnd(a->lvec,zz,ADD_VALUES,
426096963f5SLois Curfman McInnes          (ScatterMode)(SCATTER_ALL|SCATTER_REVERSE),a->Mvctx); CHKERRQ(ierr);
427096963f5SLois Curfman McInnes   return 0;
428096963f5SLois Curfman McInnes }
429096963f5SLois Curfman McInnes 
43039ddd567SLois Curfman McInnes static int MatGetDiagonal_MPIDense(Mat A,Vec v)
4318965ea79SLois Curfman McInnes {
43239ddd567SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
433096963f5SLois Curfman McInnes   Mat_SeqDense *aloc = (Mat_SeqDense *) a->A->data;
434*44cd7ae7SLois Curfman McInnes   int          ierr, len, i, n, m = a->m, radd;
435*44cd7ae7SLois Curfman McInnes   Scalar       *x, zero = 0.0;
436ed3cc1f0SBarry Smith 
437*44cd7ae7SLois Curfman McInnes   VecSet(&zero,v);
438096963f5SLois Curfman McInnes   ierr = VecGetArray(v,&x); CHKERRQ(ierr);
439096963f5SLois Curfman McInnes   ierr = VecGetSize(v,&n); CHKERRQ(ierr);
440096963f5SLois Curfman McInnes   if (n != a->M) SETERRQ(1,"MatGetDiagonal_SeqDense:Nonconforming mat and vec");
441*44cd7ae7SLois Curfman McInnes   len = PetscMin(aloc->m,aloc->n);
442096963f5SLois Curfman McInnes   radd = a->rstart*m*m;
443*44cd7ae7SLois Curfman McInnes   for ( i=0; i<len; i++ ) {
444096963f5SLois Curfman McInnes     x[i] = aloc->v[radd + i*m + i];
445096963f5SLois Curfman McInnes   }
446096963f5SLois Curfman McInnes   return 0;
4478965ea79SLois Curfman McInnes }
4488965ea79SLois Curfman McInnes 
44939ddd567SLois Curfman McInnes static int MatDestroy_MPIDense(PetscObject obj)
4508965ea79SLois Curfman McInnes {
4518965ea79SLois Curfman McInnes   Mat          mat = (Mat) obj;
4523501a2bdSLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
4538965ea79SLois Curfman McInnes   int          ierr;
454ed3cc1f0SBarry Smith 
4558965ea79SLois Curfman McInnes #if defined(PETSC_LOG)
4563501a2bdSLois Curfman McInnes   PLogObjectState(obj,"Rows=%d, Cols=%d",mdn->M,mdn->N);
4578965ea79SLois Curfman McInnes #endif
4580452661fSBarry Smith   PetscFree(mdn->rowners);
4593501a2bdSLois Curfman McInnes   ierr = MatDestroy(mdn->A); CHKERRQ(ierr);
4603501a2bdSLois Curfman McInnes   if (mdn->lvec)   VecDestroy(mdn->lvec);
4613501a2bdSLois Curfman McInnes   if (mdn->Mvctx)  VecScatterDestroy(mdn->Mvctx);
462622d7880SLois Curfman McInnes   if (mdn->factor) {
463622d7880SLois Curfman McInnes     if (mdn->factor->temp)   PetscFree(mdn->factor->temp);
464622d7880SLois Curfman McInnes     if (mdn->factor->tag)    PetscFree(mdn->factor->tag);
465622d7880SLois Curfman McInnes     if (mdn->factor->pivots) PetscFree(mdn->factor->pivots);
466622d7880SLois Curfman McInnes     PetscFree(mdn->factor);
467622d7880SLois Curfman McInnes   }
4680452661fSBarry Smith   PetscFree(mdn);
4698965ea79SLois Curfman McInnes   PLogObjectDestroy(mat);
4700452661fSBarry Smith   PetscHeaderDestroy(mat);
4718965ea79SLois Curfman McInnes   return 0;
4728965ea79SLois Curfman McInnes }
47339ddd567SLois Curfman McInnes 
4748965ea79SLois Curfman McInnes #include "pinclude/pviewer.h"
4758965ea79SLois Curfman McInnes 
47639ddd567SLois Curfman McInnes static int MatView_MPIDense_Binary(Mat mat,Viewer viewer)
4778965ea79SLois Curfman McInnes {
47839ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
4798965ea79SLois Curfman McInnes   int          ierr;
48039ddd567SLois Curfman McInnes   if (mdn->size == 1) {
48139ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
4828965ea79SLois Curfman McInnes   }
48339ddd567SLois Curfman McInnes   else SETERRQ(1,"MatView_MPIDense_Binary:Only uniprocessor output supported");
4848965ea79SLois Curfman McInnes   return 0;
4858965ea79SLois Curfman McInnes }
4868965ea79SLois Curfman McInnes 
48739ddd567SLois Curfman McInnes static int MatView_MPIDense_ASCII(Mat mat,Viewer viewer)
4888965ea79SLois Curfman McInnes {
48939ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
49039ddd567SLois Curfman McInnes   int          ierr, format;
4918965ea79SLois Curfman McInnes   FILE         *fd;
49219bcc07fSBarry Smith   ViewerType   vtype;
4938965ea79SLois Curfman McInnes 
49419bcc07fSBarry Smith   ViewerGetType(viewer,&vtype);
49590ace30eSBarry Smith   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
49690ace30eSBarry Smith   ierr = ViewerGetFormat(viewer,&format);
49790ace30eSBarry Smith   if (format == ASCII_FORMAT_INFO_DETAILED) {
498096963f5SLois Curfman McInnes     int nz, nzalloc, mem, rank;
499096963f5SLois Curfman McInnes     MPI_Comm_rank(mat->comm,&rank);
500096963f5SLois Curfman McInnes     ierr = MatGetInfo(mat,MAT_LOCAL,&nz,&nzalloc,&mem);
50177c4ece6SBarry Smith     PetscSequentialPhaseBegin(mat->comm,1);
5023501a2bdSLois Curfman McInnes       fprintf(fd,"  [%d] local rows %d nz %d nz alloced %d mem %d \n",
503096963f5SLois Curfman McInnes           rank,mdn->m,nz,nzalloc,mem);
504096963f5SLois Curfman McInnes       fflush(fd);
50577c4ece6SBarry Smith     PetscSequentialPhaseEnd(mat->comm,1);
5063501a2bdSLois Curfman McInnes     ierr = VecScatterView(mdn->Mvctx,viewer); CHKERRQ(ierr);
5073501a2bdSLois Curfman McInnes     return 0;
5083501a2bdSLois Curfman McInnes   }
50990ace30eSBarry Smith   else if (format == ASCII_FORMAT_INFO) {
510096963f5SLois Curfman McInnes     return 0;
5118965ea79SLois Curfman McInnes   }
51219bcc07fSBarry Smith   if (vtype == ASCII_FILE_VIEWER) {
51377c4ece6SBarry Smith     PetscSequentialPhaseBegin(mat->comm,1);
51439ddd567SLois Curfman McInnes     fprintf(fd,"[%d] rows %d starts %d ends %d cols %d\n",
51539ddd567SLois Curfman McInnes              mdn->rank,mdn->m,mdn->rstart,mdn->rend,mdn->n);
51639ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
5178965ea79SLois Curfman McInnes     fflush(fd);
51877c4ece6SBarry Smith     PetscSequentialPhaseEnd(mat->comm,1);
5198965ea79SLois Curfman McInnes   }
5208965ea79SLois Curfman McInnes   else {
52139ddd567SLois Curfman McInnes     int size = mdn->size, rank = mdn->rank;
5228965ea79SLois Curfman McInnes     if (size == 1) {
52339ddd567SLois Curfman McInnes       ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
5248965ea79SLois Curfman McInnes     }
5258965ea79SLois Curfman McInnes     else {
5268965ea79SLois Curfman McInnes       /* assemble the entire matrix onto first processor. */
5278965ea79SLois Curfman McInnes       Mat          A;
52839ddd567SLois Curfman McInnes       int          M = mdn->M, N = mdn->N,m,row,i, nz, *cols;
52939ddd567SLois Curfman McInnes       Scalar       *vals;
53039ddd567SLois Curfman McInnes       Mat_SeqDense *Amdn = (Mat_SeqDense*) mdn->A->data;
5318965ea79SLois Curfman McInnes 
5328965ea79SLois Curfman McInnes       if (!rank) {
533b4fd4287SBarry Smith         ierr = MatCreateMPIDense(mat->comm,M,M,N,N,PETSC_NULL,&A); CHKERRQ(ierr);
5348965ea79SLois Curfman McInnes       }
5358965ea79SLois Curfman McInnes       else {
536b4fd4287SBarry Smith         ierr = MatCreateMPIDense(mat->comm,0,M,N,N,PETSC_NULL,&A); CHKERRQ(ierr);
5378965ea79SLois Curfman McInnes       }
5388965ea79SLois Curfman McInnes       PLogObjectParent(mat,A);
5398965ea79SLois Curfman McInnes 
54039ddd567SLois Curfman McInnes       /* Copy the matrix ... This isn't the most efficient means,
54139ddd567SLois Curfman McInnes          but it's quick for now */
54239ddd567SLois Curfman McInnes       row = mdn->rstart; m = Amdn->m;
5438965ea79SLois Curfman McInnes       for ( i=0; i<m; i++ ) {
54439ddd567SLois Curfman McInnes         ierr = MatGetRow(mat,row,&nz,&cols,&vals); CHKERRQ(ierr);
54539ddd567SLois Curfman McInnes         ierr = MatSetValues(A,1,&row,nz,cols,vals,INSERT_VALUES); CHKERRQ(ierr);
54639ddd567SLois Curfman McInnes         ierr = MatRestoreRow(mat,row,&nz,&cols,&vals); CHKERRQ(ierr);
54739ddd567SLois Curfman McInnes         row++;
5488965ea79SLois Curfman McInnes       }
5498965ea79SLois Curfman McInnes 
5508965ea79SLois Curfman McInnes       ierr = MatAssemblyBegin(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
5518965ea79SLois Curfman McInnes       ierr = MatAssemblyEnd(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
5528965ea79SLois Curfman McInnes       if (!rank) {
55339ddd567SLois Curfman McInnes         ierr = MatView(((Mat_MPIDense*)(A->data))->A,viewer); CHKERRQ(ierr);
5548965ea79SLois Curfman McInnes       }
5558965ea79SLois Curfman McInnes       ierr = MatDestroy(A); CHKERRQ(ierr);
5568965ea79SLois Curfman McInnes     }
5578965ea79SLois Curfman McInnes   }
5588965ea79SLois Curfman McInnes   return 0;
5598965ea79SLois Curfman McInnes }
5608965ea79SLois Curfman McInnes 
56139ddd567SLois Curfman McInnes static int MatView_MPIDense(PetscObject obj,Viewer viewer)
5628965ea79SLois Curfman McInnes {
5638965ea79SLois Curfman McInnes   Mat          mat = (Mat) obj;
56439ddd567SLois Curfman McInnes   int          ierr;
565bcd2baecSBarry Smith   ViewerType   vtype;
5668965ea79SLois Curfman McInnes 
5678965ea79SLois Curfman McInnes   if (!viewer) {
56819bcc07fSBarry Smith     viewer = STDOUT_VIEWER_SELF;
5698965ea79SLois Curfman McInnes   }
570bcd2baecSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
571bcd2baecSBarry Smith   if (vtype == ASCII_FILE_VIEWER) {
57239ddd567SLois Curfman McInnes     ierr = MatView_MPIDense_ASCII(mat,viewer); CHKERRQ(ierr);
5738965ea79SLois Curfman McInnes   }
574bcd2baecSBarry Smith   else if (vtype == ASCII_FILES_VIEWER) {
57539ddd567SLois Curfman McInnes     ierr = MatView_MPIDense_ASCII(mat,viewer); CHKERRQ(ierr);
5768965ea79SLois Curfman McInnes   }
577bcd2baecSBarry Smith   else if (vtype == BINARY_FILE_VIEWER) {
57839ddd567SLois Curfman McInnes     return MatView_MPIDense_Binary(mat,viewer);
5798965ea79SLois Curfman McInnes   }
5808965ea79SLois Curfman McInnes   return 0;
5818965ea79SLois Curfman McInnes }
5828965ea79SLois Curfman McInnes 
5833501a2bdSLois Curfman McInnes static int MatGetInfo_MPIDense(Mat A,MatInfoType flag,int *nz,
5848965ea79SLois Curfman McInnes                              int *nzalloc,int *mem)
5858965ea79SLois Curfman McInnes {
5863501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
5873501a2bdSLois Curfman McInnes   Mat          mdn = mat->A;
58839ddd567SLois Curfman McInnes   int          ierr, isend[3], irecv[3];
5898965ea79SLois Curfman McInnes 
5903501a2bdSLois Curfman McInnes   ierr = MatGetInfo(mdn,MAT_LOCAL,&isend[0],&isend[1],&isend[2]); CHKERRQ(ierr);
5918965ea79SLois Curfman McInnes   if (flag == MAT_LOCAL) {
592bcd2baecSBarry Smith     if (nz)      *nz      = isend[0];
593bcd2baecSBarry Smith     if (nzalloc) *nzalloc = isend[1];
594bcd2baecSBarry Smith     if (mem)     *mem     = isend[2];
5958965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_MAX) {
5963501a2bdSLois Curfman McInnes     MPI_Allreduce(isend,irecv,3,MPI_INT,MPI_MAX,A->comm);
597bcd2baecSBarry Smith     if (nz)      *nz      = irecv[0];
598bcd2baecSBarry Smith     if (nzalloc) *nzalloc = irecv[1];
599bcd2baecSBarry Smith     if (mem)     *mem     = irecv[2];
6008965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_SUM) {
6013501a2bdSLois Curfman McInnes     MPI_Allreduce(isend,irecv,3,MPI_INT,MPI_SUM,A->comm);
602bcd2baecSBarry Smith     if (nz)      *nz      = irecv[0];
603bcd2baecSBarry Smith     if (nzalloc) *nzalloc = irecv[1];
604bcd2baecSBarry Smith     if (mem)     *mem     = irecv[2];
6058965ea79SLois Curfman McInnes   }
6068965ea79SLois Curfman McInnes   return 0;
6078965ea79SLois Curfman McInnes }
6088965ea79SLois Curfman McInnes 
6098c469469SLois Curfman McInnes /* extern int MatLUFactorSymbolic_MPIDense(Mat,IS,IS,double,Mat*);
6108aaee692SLois Curfman McInnes    extern int MatLUFactorNumeric_MPIDense(Mat,Mat*);
6118aaee692SLois Curfman McInnes    extern int MatLUFactor_MPIDense(Mat,IS,IS,double);
6128aaee692SLois Curfman McInnes    extern int MatSolve_MPIDense(Mat,Vec,Vec);
6138c469469SLois Curfman McInnes    extern int MatSolveAdd_MPIDense(Mat,Vec,Vec,Vec);
6148aaee692SLois Curfman McInnes    extern int MatSolveTrans_MPIDense(Mat,Vec,Vec);
6158aaee692SLois Curfman McInnes    extern int MatSolveTransAdd_MPIDense(Mat,Vec,Vec,Vec); */
6168aaee692SLois Curfman McInnes 
61739ddd567SLois Curfman McInnes static int MatSetOption_MPIDense(Mat A,MatOption op)
6188965ea79SLois Curfman McInnes {
61939ddd567SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
6208965ea79SLois Curfman McInnes 
6218965ea79SLois Curfman McInnes   if (op == NO_NEW_NONZERO_LOCATIONS ||
6228965ea79SLois Curfman McInnes       op == YES_NEW_NONZERO_LOCATIONS ||
6238965ea79SLois Curfman McInnes       op == COLUMNS_SORTED ||
6248965ea79SLois Curfman McInnes       op == ROW_ORIENTED) {
6258965ea79SLois Curfman McInnes         MatSetOption(a->A,op);
6268965ea79SLois Curfman McInnes   }
6278965ea79SLois Curfman McInnes   else if (op == ROWS_SORTED ||
6288965ea79SLois Curfman McInnes            op == SYMMETRIC_MATRIX ||
6298965ea79SLois Curfman McInnes            op == STRUCTURALLY_SYMMETRIC_MATRIX ||
6308965ea79SLois Curfman McInnes            op == YES_NEW_DIAGONALS)
63194a424c1SBarry Smith     PLogInfo(A,"Info:MatSetOption_MPIDense:Option ignored\n");
6328965ea79SLois Curfman McInnes   else if (op == COLUMN_ORIENTED)
63339b7565bSBarry Smith     { a->roworiented = 0; MatSetOption(a->A,op);}
6348965ea79SLois Curfman McInnes   else if (op == NO_NEW_DIAGONALS)
63539ddd567SLois Curfman McInnes     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_MPIDense:NO_NEW_DIAGONALS");}
6368965ea79SLois Curfman McInnes   else
63739ddd567SLois Curfman McInnes     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_MPIDense:unknown option");}
6388965ea79SLois Curfman McInnes   return 0;
6398965ea79SLois Curfman McInnes }
6408965ea79SLois Curfman McInnes 
6413501a2bdSLois Curfman McInnes static int MatGetSize_MPIDense(Mat A,int *m,int *n)
6428965ea79SLois Curfman McInnes {
6433501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6448965ea79SLois Curfman McInnes   *m = mat->M; *n = mat->N;
6458965ea79SLois Curfman McInnes   return 0;
6468965ea79SLois Curfman McInnes }
6478965ea79SLois Curfman McInnes 
6483501a2bdSLois Curfman McInnes static int MatGetLocalSize_MPIDense(Mat A,int *m,int *n)
6498965ea79SLois Curfman McInnes {
6503501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6518965ea79SLois Curfman McInnes   *m = mat->m; *n = mat->N;
6528965ea79SLois Curfman McInnes   return 0;
6538965ea79SLois Curfman McInnes }
6548965ea79SLois Curfman McInnes 
6553501a2bdSLois Curfman McInnes static int MatGetOwnershipRange_MPIDense(Mat A,int *m,int *n)
6568965ea79SLois Curfman McInnes {
6573501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6588965ea79SLois Curfman McInnes   *m = mat->rstart; *n = mat->rend;
6598965ea79SLois Curfman McInnes   return 0;
6608965ea79SLois Curfman McInnes }
6618965ea79SLois Curfman McInnes 
6623501a2bdSLois Curfman McInnes static int MatGetRow_MPIDense(Mat A,int row,int *nz,int **idx,Scalar **v)
6638965ea79SLois Curfman McInnes {
6643501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
66539ddd567SLois Curfman McInnes   int          lrow, rstart = mat->rstart, rend = mat->rend;
6668965ea79SLois Curfman McInnes 
66739ddd567SLois Curfman McInnes   if (row < rstart || row >= rend) SETERRQ(1,"MatGetRow_MPIDense:only local rows")
6688965ea79SLois Curfman McInnes   lrow = row - rstart;
66939ddd567SLois Curfman McInnes   return MatGetRow(mat->A,lrow,nz,idx,v);
6708965ea79SLois Curfman McInnes }
6718965ea79SLois Curfman McInnes 
67239ddd567SLois Curfman McInnes static int MatRestoreRow_MPIDense(Mat mat,int row,int *nz,int **idx,Scalar **v)
6738965ea79SLois Curfman McInnes {
6740452661fSBarry Smith   if (idx) PetscFree(*idx);
6750452661fSBarry Smith   if (v) PetscFree(*v);
6768965ea79SLois Curfman McInnes   return 0;
6778965ea79SLois Curfman McInnes }
6788965ea79SLois Curfman McInnes 
679cddf8d76SBarry Smith static int MatNorm_MPIDense(Mat A,NormType type,double *norm)
680096963f5SLois Curfman McInnes {
6813501a2bdSLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) A->data;
6823501a2bdSLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense*) mdn->A->data;
6833501a2bdSLois Curfman McInnes   int          ierr, i, j;
6843501a2bdSLois Curfman McInnes   double       sum = 0.0;
6853501a2bdSLois Curfman McInnes   Scalar       *v = mat->v;
6863501a2bdSLois Curfman McInnes 
6873501a2bdSLois Curfman McInnes   if (mdn->size == 1) {
6883501a2bdSLois Curfman McInnes     ierr =  MatNorm(mdn->A,type,norm); CHKERRQ(ierr);
6893501a2bdSLois Curfman McInnes   } else {
6903501a2bdSLois Curfman McInnes     if (type == NORM_FROBENIUS) {
6913501a2bdSLois Curfman McInnes       for (i=0; i<mat->n*mat->m; i++ ) {
6923501a2bdSLois Curfman McInnes #if defined(PETSC_COMPLEX)
6933501a2bdSLois Curfman McInnes         sum += real(conj(*v)*(*v)); v++;
6943501a2bdSLois Curfman McInnes #else
6953501a2bdSLois Curfman McInnes         sum += (*v)*(*v); v++;
6963501a2bdSLois Curfman McInnes #endif
6973501a2bdSLois Curfman McInnes       }
6986d84be18SBarry Smith       MPI_Allreduce(&sum,norm,1,MPI_DOUBLE,MPI_SUM,A->comm);
6993501a2bdSLois Curfman McInnes       *norm = sqrt(*norm);
7003501a2bdSLois Curfman McInnes       PLogFlops(2*mat->n*mat->m);
7013501a2bdSLois Curfman McInnes     }
7023501a2bdSLois Curfman McInnes     else if (type == NORM_1) {
7033501a2bdSLois Curfman McInnes       double *tmp, *tmp2;
7040452661fSBarry Smith       tmp  = (double *) PetscMalloc( 2*mdn->N*sizeof(double) ); CHKPTRQ(tmp);
7053501a2bdSLois Curfman McInnes       tmp2 = tmp + mdn->N;
706cddf8d76SBarry Smith       PetscMemzero(tmp,2*mdn->N*sizeof(double));
707096963f5SLois Curfman McInnes       *norm = 0.0;
7083501a2bdSLois Curfman McInnes       v = mat->v;
7093501a2bdSLois Curfman McInnes       for ( j=0; j<mat->n; j++ ) {
7103501a2bdSLois Curfman McInnes         for ( i=0; i<mat->m; i++ ) {
71167e560aaSBarry Smith           tmp[j] += PetscAbsScalar(*v);  v++;
7123501a2bdSLois Curfman McInnes         }
7133501a2bdSLois Curfman McInnes       }
7146d84be18SBarry Smith       MPI_Allreduce(tmp,tmp2,mdn->N,MPI_DOUBLE,MPI_SUM,A->comm);
7153501a2bdSLois Curfman McInnes       for ( j=0; j<mdn->N; j++ ) {
7163501a2bdSLois Curfman McInnes         if (tmp2[j] > *norm) *norm = tmp2[j];
7173501a2bdSLois Curfman McInnes       }
7180452661fSBarry Smith       PetscFree(tmp);
7193501a2bdSLois Curfman McInnes       PLogFlops(mat->n*mat->m);
7203501a2bdSLois Curfman McInnes     }
7213501a2bdSLois Curfman McInnes     else if (type == NORM_INFINITY) { /* max row norm */
7223501a2bdSLois Curfman McInnes       double ntemp;
7233501a2bdSLois Curfman McInnes       ierr = MatNorm(mdn->A,type,&ntemp); CHKERRQ(ierr);
7246d84be18SBarry Smith       MPI_Allreduce(&ntemp,norm,1,MPI_DOUBLE,MPI_MAX,A->comm);
7253501a2bdSLois Curfman McInnes     }
7263501a2bdSLois Curfman McInnes     else {
7273501a2bdSLois Curfman McInnes       SETERRQ(1,"MatNorm_MPIDense:No support for two norm");
7283501a2bdSLois Curfman McInnes     }
7293501a2bdSLois Curfman McInnes   }
7303501a2bdSLois Curfman McInnes   return 0;
7313501a2bdSLois Curfman McInnes }
7323501a2bdSLois Curfman McInnes 
7333501a2bdSLois Curfman McInnes static int MatTranspose_MPIDense(Mat A,Mat *matout)
7343501a2bdSLois Curfman McInnes {
7353501a2bdSLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
7363501a2bdSLois Curfman McInnes   Mat_SeqDense *Aloc = (Mat_SeqDense *) a->A->data;
7373501a2bdSLois Curfman McInnes   Mat          B;
7383501a2bdSLois Curfman McInnes   int          M = a->M, N = a->N, m, n, *rwork, rstart = a->rstart;
7393501a2bdSLois Curfman McInnes   int          j, i, ierr;
7403501a2bdSLois Curfman McInnes   Scalar       *v;
7413501a2bdSLois Curfman McInnes 
7423638b69dSLois Curfman McInnes   if (matout == PETSC_NULL && M != N)
7433501a2bdSLois Curfman McInnes     SETERRQ(1,"MatTranspose_MPIDense:Supports square matrix only in-place");
744b4fd4287SBarry Smith   ierr = MatCreateMPIDense(A->comm,PETSC_DECIDE,PETSC_DECIDE,N,M,PETSC_NULL,&B);
745ed2daf61SLois Curfman McInnes          CHKERRQ(ierr);
7463501a2bdSLois Curfman McInnes 
7473501a2bdSLois Curfman McInnes   m = Aloc->m; n = Aloc->n; v = Aloc->v;
7480452661fSBarry Smith   rwork = (int *) PetscMalloc(n*sizeof(int)); CHKPTRQ(rwork);
7493501a2bdSLois Curfman McInnes   for ( j=0; j<n; j++ ) {
7503501a2bdSLois Curfman McInnes     for (i=0; i<m; i++) rwork[i] = rstart + i;
7513501a2bdSLois Curfman McInnes     ierr = MatSetValues(B,1,&j,m,rwork,v,INSERT_VALUES); CHKERRQ(ierr);
7523501a2bdSLois Curfman McInnes     v += m;
7533501a2bdSLois Curfman McInnes   }
7540452661fSBarry Smith   PetscFree(rwork);
7553501a2bdSLois Curfman McInnes   ierr = MatAssemblyBegin(B,FINAL_ASSEMBLY); CHKERRQ(ierr);
7563501a2bdSLois Curfman McInnes   ierr = MatAssemblyEnd(B,FINAL_ASSEMBLY); CHKERRQ(ierr);
7573638b69dSLois Curfman McInnes   if (matout != PETSC_NULL) {
7583501a2bdSLois Curfman McInnes     *matout = B;
7593501a2bdSLois Curfman McInnes   } else {
7603501a2bdSLois Curfman McInnes     /* This isn't really an in-place transpose, but free data struct from a */
7610452661fSBarry Smith     PetscFree(a->rowners);
7623501a2bdSLois Curfman McInnes     ierr = MatDestroy(a->A); CHKERRQ(ierr);
7633501a2bdSLois Curfman McInnes     if (a->lvec) VecDestroy(a->lvec);
7643501a2bdSLois Curfman McInnes     if (a->Mvctx) VecScatterDestroy(a->Mvctx);
7650452661fSBarry Smith     PetscFree(a);
7663501a2bdSLois Curfman McInnes     PetscMemcpy(A,B,sizeof(struct _Mat));
7670452661fSBarry Smith     PetscHeaderDestroy(B);
7683501a2bdSLois Curfman McInnes   }
769096963f5SLois Curfman McInnes   return 0;
770096963f5SLois Curfman McInnes }
771096963f5SLois Curfman McInnes 
772*44cd7ae7SLois Curfman McInnes #include "pinclude/plapack.h"
773*44cd7ae7SLois Curfman McInnes static int MatScale_MPIDense(Scalar *alpha,Mat inA)
774*44cd7ae7SLois Curfman McInnes {
775*44cd7ae7SLois Curfman McInnes   Mat_MPIDense *A = (Mat_MPIDense *) inA->data;
776*44cd7ae7SLois Curfman McInnes   Mat_SeqDense *a = (Mat_SeqDense *) A->A->data;
777*44cd7ae7SLois Curfman McInnes   int          one = 1, nz;
778*44cd7ae7SLois Curfman McInnes 
779*44cd7ae7SLois Curfman McInnes   nz = a->m*a->n;
780*44cd7ae7SLois Curfman McInnes   BLscal_( &nz, alpha, a->v, &one );
781*44cd7ae7SLois Curfman McInnes   PLogFlops(nz);
782*44cd7ae7SLois Curfman McInnes   return 0;
783*44cd7ae7SLois Curfman McInnes }
784*44cd7ae7SLois Curfman McInnes 
7853d1612f7SBarry Smith static int MatConvertSameType_MPIDense(Mat,Mat *,int);
7868965ea79SLois Curfman McInnes 
7878965ea79SLois Curfman McInnes /* -------------------------------------------------------------------*/
78839ddd567SLois Curfman McInnes static struct _MatOps MatOps = {MatSetValues_MPIDense,
78939ddd567SLois Curfman McInnes        MatGetRow_MPIDense,MatRestoreRow_MPIDense,
79039ddd567SLois Curfman McInnes        MatMult_MPIDense,MatMultAdd_MPIDense,
791096963f5SLois Curfman McInnes        MatMultTrans_MPIDense,MatMultTransAdd_MPIDense,
792e7ca0642SLois Curfman McInnes /*       MatSolve_MPIDense,0, */
793e7ca0642SLois Curfman McInnes        0,0,
79439ddd567SLois Curfman McInnes        0,0,
7958c469469SLois Curfman McInnes        0,0,
7968c469469SLois Curfman McInnes /*       MatLUFactor_MPIDense,0, */
7978aaee692SLois Curfman McInnes        0,MatTranspose_MPIDense,
79839ddd567SLois Curfman McInnes        MatGetInfo_MPIDense,0,
799096963f5SLois Curfman McInnes        MatGetDiagonal_MPIDense,0,MatNorm_MPIDense,
80039ddd567SLois Curfman McInnes        MatAssemblyBegin_MPIDense,MatAssemblyEnd_MPIDense,
8018965ea79SLois Curfman McInnes        0,
80239ddd567SLois Curfman McInnes        MatSetOption_MPIDense,MatZeroEntries_MPIDense,MatZeroRows_MPIDense,
8038c469469SLois Curfman McInnes        0,0,0,
8048c469469SLois Curfman McInnes /*       0,MatLUFactorSymbolic_MPIDense,MatLUFactorNumeric_MPIDense, */
8058aaee692SLois Curfman McInnes        0,0,
80639ddd567SLois Curfman McInnes        MatGetSize_MPIDense,MatGetLocalSize_MPIDense,
80739ddd567SLois Curfman McInnes        MatGetOwnershipRange_MPIDense,
808ff14e315SSatish Balay        0,0, MatGetArray_MPIDense, MatRestoreArray_MPIDense,
809ff14e315SSatish Balay        0,0,0,MatConvertSameType_MPIDense,
810b49de8d1SLois Curfman McInnes        0,0,0,0,0,
811*44cd7ae7SLois Curfman McInnes        0,0,MatGetValues_MPIDense,0,0,MatScale_MPIDense};
8128965ea79SLois Curfman McInnes 
8138965ea79SLois Curfman McInnes /*@C
81439ddd567SLois Curfman McInnes    MatCreateMPIDense - Creates a sparse parallel matrix in dense format.
8158965ea79SLois Curfman McInnes 
8168965ea79SLois Curfman McInnes    Input Parameters:
8178965ea79SLois Curfman McInnes .  comm - MPI communicator
8188965ea79SLois Curfman McInnes .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
8198965ea79SLois Curfman McInnes .  n - number of local columns (or PETSC_DECIDE to have calculated
8208965ea79SLois Curfman McInnes            if N is given)
8218965ea79SLois Curfman McInnes .  M - number of global rows (or PETSC_DECIDE to have calculated if m is given)
8228965ea79SLois Curfman McInnes .  N - number of global columns (or PETSC_DECIDE to have calculated
8238965ea79SLois Curfman McInnes            if n is given)
824b4fd4287SBarry Smith .  data - optional location of matrix data.  Set data=PETSC_NULL for PETSc
825dfc5480cSLois Curfman McInnes    to control all matrix memory allocation.
8268965ea79SLois Curfman McInnes 
8278965ea79SLois Curfman McInnes    Output Parameter:
8288965ea79SLois Curfman McInnes .  newmat - the matrix
8298965ea79SLois Curfman McInnes 
8308965ea79SLois Curfman McInnes    Notes:
83139ddd567SLois Curfman McInnes    The dense format is fully compatible with standard Fortran 77
83239ddd567SLois Curfman McInnes    storage by columns.
8338965ea79SLois Curfman McInnes 
83418f449edSLois Curfman McInnes    The data input variable is intended primarily for Fortran programmers
83518f449edSLois Curfman McInnes    who wish to allocate their own matrix memory space.  Most users should
836b4fd4287SBarry Smith    set data=PETSC_NULL.
83718f449edSLois Curfman McInnes 
8388965ea79SLois Curfman McInnes    The user MUST specify either the local or global matrix dimensions
8398965ea79SLois Curfman McInnes    (possibly both).
8408965ea79SLois Curfman McInnes 
8413501a2bdSLois Curfman McInnes    Currently, the only parallel dense matrix decomposition is by rows,
8423501a2bdSLois Curfman McInnes    so that n=N and each submatrix owns all of the global columns.
8433501a2bdSLois Curfman McInnes 
84439ddd567SLois Curfman McInnes .keywords: matrix, dense, parallel
8458965ea79SLois Curfman McInnes 
84639ddd567SLois Curfman McInnes .seealso: MatCreate(), MatCreateSeqDense(), MatSetValues()
8478965ea79SLois Curfman McInnes @*/
84818f449edSLois Curfman McInnes int MatCreateMPIDense(MPI_Comm comm,int m,int n,int M,int N,Scalar *data,Mat *newmat)
8498965ea79SLois Curfman McInnes {
8508965ea79SLois Curfman McInnes   Mat          mat;
85139ddd567SLois Curfman McInnes   Mat_MPIDense *a;
85225cdf11fSBarry Smith   int          ierr, i,flg;
8538965ea79SLois Curfman McInnes 
854ed2daf61SLois Curfman McInnes /* Note:  For now, when data is specified above, this assumes the user correctly
855ed2daf61SLois Curfman McInnes    allocates the local dense storage space.  We should add error checking. */
85618f449edSLois Curfman McInnes 
8578965ea79SLois Curfman McInnes   *newmat         = 0;
8580452661fSBarry Smith   PetscHeaderCreate(mat,_Mat,MAT_COOKIE,MATMPIDENSE,comm);
8598965ea79SLois Curfman McInnes   PLogObjectCreate(mat);
8600452661fSBarry Smith   mat->data       = (void *) (a = PetscNew(Mat_MPIDense)); CHKPTRQ(a);
8618965ea79SLois Curfman McInnes   PetscMemcpy(&mat->ops,&MatOps,sizeof(struct _MatOps));
86239ddd567SLois Curfman McInnes   mat->destroy    = MatDestroy_MPIDense;
86339ddd567SLois Curfman McInnes   mat->view       = MatView_MPIDense;
8648965ea79SLois Curfman McInnes   mat->factor     = 0;
8658965ea79SLois Curfman McInnes 
866622d7880SLois Curfman McInnes   a->factor = 0;
8678965ea79SLois Curfman McInnes   a->insertmode = NOT_SET_VALUES;
8688965ea79SLois Curfman McInnes   MPI_Comm_rank(comm,&a->rank);
8698965ea79SLois Curfman McInnes   MPI_Comm_size(comm,&a->size);
8708965ea79SLois Curfman McInnes 
87139ddd567SLois Curfman McInnes   if (M == PETSC_DECIDE) MPI_Allreduce(&m,&M,1,MPI_INT,MPI_SUM,comm);
8728965ea79SLois Curfman McInnes   if (m == PETSC_DECIDE) {m = M/a->size + ((M % a->size) > a->rank);}
87339ddd567SLois Curfman McInnes 
87439ddd567SLois Curfman McInnes   /* each row stores all columns */
87539ddd567SLois Curfman McInnes   if (N == PETSC_DECIDE) N = n;
876d7e8b826SBarry Smith   if (n == PETSC_DECIDE) {n = N/a->size + ((N % a->size) > a->rank);}
877d7e8b826SBarry Smith   /*  if (n != N) SETERRQ(1,"MatCreateMPIDense:For now, only n=N is supported"); */
8788965ea79SLois Curfman McInnes   a->N = N;
8798965ea79SLois Curfman McInnes   a->M = M;
88039ddd567SLois Curfman McInnes   a->m = m;
88139ddd567SLois Curfman McInnes   a->n = n;
8828965ea79SLois Curfman McInnes 
8838965ea79SLois Curfman McInnes   /* build local table of row and column ownerships */
884d7e8b826SBarry Smith   a->rowners = (int *) PetscMalloc(2*(a->size+2)*sizeof(int)); CHKPTRQ(a->rowners);
885d7e8b826SBarry Smith   a->cowners = a->rowners + a->size + 1;
886d7e8b826SBarry Smith   PLogObjectMemory(mat,2*(a->size+2)*sizeof(int)+sizeof(struct _Mat)+
88739ddd567SLois Curfman McInnes                        sizeof(Mat_MPIDense));
8888965ea79SLois Curfman McInnes   MPI_Allgather(&m,1,MPI_INT,a->rowners+1,1,MPI_INT,comm);
8898965ea79SLois Curfman McInnes   a->rowners[0] = 0;
8908965ea79SLois Curfman McInnes   for ( i=2; i<=a->size; i++ ) {
8918965ea79SLois Curfman McInnes     a->rowners[i] += a->rowners[i-1];
8928965ea79SLois Curfman McInnes   }
8938965ea79SLois Curfman McInnes   a->rstart = a->rowners[a->rank];
8948965ea79SLois Curfman McInnes   a->rend   = a->rowners[a->rank+1];
895d7e8b826SBarry Smith   MPI_Allgather(&n,1,MPI_INT,a->cowners+1,1,MPI_INT,comm);
896d7e8b826SBarry Smith   a->cowners[0] = 0;
897d7e8b826SBarry Smith   for ( i=2; i<=a->size; i++ ) {
898d7e8b826SBarry Smith     a->cowners[i] += a->cowners[i-1];
899d7e8b826SBarry Smith   }
9008965ea79SLois Curfman McInnes 
90118f449edSLois Curfman McInnes   ierr = MatCreateSeqDense(MPI_COMM_SELF,m,N,data,&a->A); CHKERRQ(ierr);
9028965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->A);
9038965ea79SLois Curfman McInnes 
9048965ea79SLois Curfman McInnes   /* build cache for off array entries formed */
9058965ea79SLois Curfman McInnes   ierr = StashBuild_Private(&a->stash); CHKERRQ(ierr);
9068965ea79SLois Curfman McInnes 
9078965ea79SLois Curfman McInnes   /* stuff used for matrix vector multiply */
9088965ea79SLois Curfman McInnes   a->lvec        = 0;
9098965ea79SLois Curfman McInnes   a->Mvctx       = 0;
91039b7565bSBarry Smith   a->roworiented = 1;
9118965ea79SLois Curfman McInnes 
9128965ea79SLois Curfman McInnes   *newmat = mat;
91325cdf11fSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-help",&flg); CHKERRQ(ierr);
91425cdf11fSBarry Smith   if (flg) {
9158c469469SLois Curfman McInnes     ierr = MatPrintHelp(mat); CHKERRQ(ierr);
9168c469469SLois Curfman McInnes   }
9178965ea79SLois Curfman McInnes   return 0;
9188965ea79SLois Curfman McInnes }
9198965ea79SLois Curfman McInnes 
9203d1612f7SBarry Smith static int MatConvertSameType_MPIDense(Mat A,Mat *newmat,int cpvalues)
9218965ea79SLois Curfman McInnes {
9228965ea79SLois Curfman McInnes   Mat          mat;
9233501a2bdSLois Curfman McInnes   Mat_MPIDense *a,*oldmat = (Mat_MPIDense *) A->data;
92439ddd567SLois Curfman McInnes   int          ierr;
9252ba99913SLois Curfman McInnes   FactorCtx    *factor;
9268965ea79SLois Curfman McInnes 
9278965ea79SLois Curfman McInnes   *newmat       = 0;
9280452661fSBarry Smith   PetscHeaderCreate(mat,_Mat,MAT_COOKIE,MATMPIDENSE,A->comm);
9298965ea79SLois Curfman McInnes   PLogObjectCreate(mat);
9300452661fSBarry Smith   mat->data     = (void *) (a = PetscNew(Mat_MPIDense)); CHKPTRQ(a);
9318965ea79SLois Curfman McInnes   PetscMemcpy(&mat->ops,&MatOps,sizeof(struct _MatOps));
93239ddd567SLois Curfman McInnes   mat->destroy  = MatDestroy_MPIDense;
93339ddd567SLois Curfman McInnes   mat->view     = MatView_MPIDense;
9343501a2bdSLois Curfman McInnes   mat->factor   = A->factor;
935c456f294SBarry Smith   mat->assembled  = PETSC_TRUE;
9368965ea79SLois Curfman McInnes 
937*44cd7ae7SLois Curfman McInnes   a->m = mat->m = oldmat->m;
938*44cd7ae7SLois Curfman McInnes   a->n = mat->n = oldmat->n;
939*44cd7ae7SLois Curfman McInnes   a->M = mat->M = oldmat->M;
940*44cd7ae7SLois Curfman McInnes   a->N = mat->N = oldmat->N;
9412ba99913SLois Curfman McInnes   if (oldmat->factor) {
9422ba99913SLois Curfman McInnes     a->factor = (FactorCtx *) (factor = PetscNew(FactorCtx)); CHKPTRQ(factor);
9432ba99913SLois Curfman McInnes     /* copy factor contents ... add this code! */
9442ba99913SLois Curfman McInnes   } else a->factor = 0;
9458965ea79SLois Curfman McInnes 
9468965ea79SLois Curfman McInnes   a->rstart     = oldmat->rstart;
9478965ea79SLois Curfman McInnes   a->rend       = oldmat->rend;
9488965ea79SLois Curfman McInnes   a->size       = oldmat->size;
9498965ea79SLois Curfman McInnes   a->rank       = oldmat->rank;
9508965ea79SLois Curfman McInnes   a->insertmode = NOT_SET_VALUES;
9518965ea79SLois Curfman McInnes 
9520452661fSBarry Smith   a->rowners = (int *) PetscMalloc((a->size+1)*sizeof(int)); CHKPTRQ(a->rowners);
95339ddd567SLois Curfman McInnes   PLogObjectMemory(mat,(a->size+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_MPIDense));
9548965ea79SLois Curfman McInnes   PetscMemcpy(a->rowners,oldmat->rowners,(a->size+1)*sizeof(int));
9558965ea79SLois Curfman McInnes   ierr = StashInitialize_Private(&a->stash); CHKERRQ(ierr);
9568965ea79SLois Curfman McInnes 
9578965ea79SLois Curfman McInnes   ierr =  VecDuplicate(oldmat->lvec,&a->lvec); CHKERRQ(ierr);
9588965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->lvec);
95955659b69SBarry Smith   ierr =  VecScatterCopy(oldmat->Mvctx,&a->Mvctx); CHKERRQ(ierr);
9608965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->Mvctx);
9618965ea79SLois Curfman McInnes   ierr =  MatConvert(oldmat->A,MATSAME,&a->A); CHKERRQ(ierr);
9628965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->A);
9638965ea79SLois Curfman McInnes   *newmat = mat;
9648965ea79SLois Curfman McInnes   return 0;
9658965ea79SLois Curfman McInnes }
9668965ea79SLois Curfman McInnes 
96777c4ece6SBarry Smith #include "sys.h"
9688965ea79SLois Curfman McInnes 
96990ace30eSBarry Smith int MatLoad_MPIDense_DenseInFile(MPI_Comm comm,int fd,int M, int N, Mat *newmat)
97090ace30eSBarry Smith {
97190ace30eSBarry Smith   int        *rowners, i,size,rank,m,rstart,rend,ierr,nz,j;
97290ace30eSBarry Smith   Scalar     *array,*vals,*vals_ptr;
97390ace30eSBarry Smith   MPI_Status status;
97490ace30eSBarry Smith 
97590ace30eSBarry Smith   MPI_Comm_rank(comm,&rank);
97690ace30eSBarry Smith   MPI_Comm_size(comm,&size);
97790ace30eSBarry Smith 
97890ace30eSBarry Smith   /* determine ownership of all rows */
97990ace30eSBarry Smith   m = M/size + ((M % size) > rank);
98090ace30eSBarry Smith   rowners = (int *) PetscMalloc((size+2)*sizeof(int)); CHKPTRQ(rowners);
98190ace30eSBarry Smith   MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);
98290ace30eSBarry Smith   rowners[0] = 0;
98390ace30eSBarry Smith   for ( i=2; i<=size; i++ ) {
98490ace30eSBarry Smith     rowners[i] += rowners[i-1];
98590ace30eSBarry Smith   }
98690ace30eSBarry Smith   rstart = rowners[rank];
98790ace30eSBarry Smith   rend   = rowners[rank+1];
98890ace30eSBarry Smith 
98990ace30eSBarry Smith   ierr = MatCreateMPIDense(comm,m,PETSC_DECIDE,M,N,PETSC_NULL,newmat);CHKERRQ(ierr);
99090ace30eSBarry Smith   ierr = MatGetArray(*newmat,&array); CHKERRQ(ierr);
99190ace30eSBarry Smith 
99290ace30eSBarry Smith   if (!rank) {
99390ace30eSBarry Smith     vals = (Scalar *) PetscMalloc( m*N*sizeof(Scalar) ); CHKPTRQ(vals);
99490ace30eSBarry Smith 
99590ace30eSBarry Smith     /* read in my part of the matrix numerical values  */
99677c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,vals,m*N,BINARY_SCALAR); CHKERRQ(ierr);
99790ace30eSBarry Smith 
99890ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
99990ace30eSBarry Smith     vals_ptr = vals;
100090ace30eSBarry Smith     for ( i=0; i<m; i++ ) {
100190ace30eSBarry Smith       for ( j=0; j<N; j++ ) {
100290ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
100390ace30eSBarry Smith       }
100490ace30eSBarry Smith     }
100590ace30eSBarry Smith 
100690ace30eSBarry Smith     /* read in other processors and ship out */
100790ace30eSBarry Smith     for ( i=1; i<size; i++ ) {
100890ace30eSBarry Smith       nz   = (rowners[i+1] - rowners[i])*N;
100977c4ece6SBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,BINARY_SCALAR); CHKERRQ(ierr);
101090ace30eSBarry Smith       MPI_Send(vals,nz,MPIU_SCALAR,i,(*newmat)->tag,comm);
101190ace30eSBarry Smith     }
101290ace30eSBarry Smith   }
101390ace30eSBarry Smith   else {
101490ace30eSBarry Smith     /* receive numeric values */
101590ace30eSBarry Smith     vals = (Scalar*) PetscMalloc( m*N*sizeof(Scalar) ); CHKPTRQ(vals);
101690ace30eSBarry Smith 
101790ace30eSBarry Smith     /* receive message of values*/
101890ace30eSBarry Smith     MPI_Recv(vals,m*N,MPIU_SCALAR,0,(*newmat)->tag,comm,&status);
101990ace30eSBarry Smith 
102090ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
102190ace30eSBarry Smith     vals_ptr = vals;
102290ace30eSBarry Smith     for ( i=0; i<m; i++ ) {
102390ace30eSBarry Smith       for ( j=0; j<N; j++ ) {
102490ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
102590ace30eSBarry Smith       }
102690ace30eSBarry Smith     }
102790ace30eSBarry Smith   }
102890ace30eSBarry Smith   PetscFree(rowners);
102990ace30eSBarry Smith   PetscFree(vals);
103090ace30eSBarry Smith   ierr = MatAssemblyBegin(*newmat,FINAL_ASSEMBLY); CHKERRQ(ierr);
103190ace30eSBarry Smith   ierr = MatAssemblyEnd(*newmat,FINAL_ASSEMBLY); CHKERRQ(ierr);
103290ace30eSBarry Smith   return 0;
103390ace30eSBarry Smith }
103490ace30eSBarry Smith 
103590ace30eSBarry Smith 
103619bcc07fSBarry Smith int MatLoad_MPIDense(Viewer viewer,MatType type,Mat *newmat)
10378965ea79SLois Curfman McInnes {
10388965ea79SLois Curfman McInnes   Mat          A;
10398965ea79SLois Curfman McInnes   int          i, nz, ierr, j,rstart, rend, fd;
10408965ea79SLois Curfman McInnes   Scalar       *vals,*svals;
104119bcc07fSBarry Smith   MPI_Comm     comm = ((PetscObject)viewer)->comm;
10428965ea79SLois Curfman McInnes   MPI_Status   status;
10438965ea79SLois Curfman McInnes   int          header[4],rank,size,*rowlengths = 0,M,N,m,*rowners,maxnz,*cols;
10448965ea79SLois Curfman McInnes   int          *ourlens,*sndcounts = 0,*procsnz = 0, *offlens,jj,*mycols,*smycols;
104519bcc07fSBarry Smith   int          tag = ((PetscObject)viewer)->tag;
10468965ea79SLois Curfman McInnes 
10478965ea79SLois Curfman McInnes   MPI_Comm_size(comm,&size); MPI_Comm_rank(comm,&rank);
10488965ea79SLois Curfman McInnes   if (!rank) {
104990ace30eSBarry Smith     ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
105077c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,(char *)header,4,BINARY_INT); CHKERRQ(ierr);
105139ddd567SLois Curfman McInnes     if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_MPIDenseorMPIRow:not matrix object");
10528965ea79SLois Curfman McInnes   }
10538965ea79SLois Curfman McInnes 
10548965ea79SLois Curfman McInnes   MPI_Bcast(header+1,3,MPI_INT,0,comm);
105590ace30eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
105690ace30eSBarry Smith 
105790ace30eSBarry Smith   /*
105890ace30eSBarry Smith        Handle case where matrix is stored on disk as a dense matrix
105990ace30eSBarry Smith   */
106090ace30eSBarry Smith   if (nz == MATRIX_BINARY_FORMAT_DENSE) {
106190ace30eSBarry Smith     return MatLoad_MPIDense_DenseInFile(comm,fd,M,N,newmat);
106290ace30eSBarry Smith   }
106390ace30eSBarry Smith 
10648965ea79SLois Curfman McInnes   /* determine ownership of all rows */
10658965ea79SLois Curfman McInnes   m = M/size + ((M % size) > rank);
10660452661fSBarry Smith   rowners = (int *) PetscMalloc((size+2)*sizeof(int)); CHKPTRQ(rowners);
10678965ea79SLois Curfman McInnes   MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);
10688965ea79SLois Curfman McInnes   rowners[0] = 0;
10698965ea79SLois Curfman McInnes   for ( i=2; i<=size; i++ ) {
10708965ea79SLois Curfman McInnes     rowners[i] += rowners[i-1];
10718965ea79SLois Curfman McInnes   }
10728965ea79SLois Curfman McInnes   rstart = rowners[rank];
10738965ea79SLois Curfman McInnes   rend   = rowners[rank+1];
10748965ea79SLois Curfman McInnes 
10758965ea79SLois Curfman McInnes   /* distribute row lengths to all processors */
10760452661fSBarry Smith   ourlens = (int*) PetscMalloc( 2*(rend-rstart)*sizeof(int) ); CHKPTRQ(ourlens);
10778965ea79SLois Curfman McInnes   offlens = ourlens + (rend-rstart);
10788965ea79SLois Curfman McInnes   if (!rank) {
10790452661fSBarry Smith     rowlengths = (int*) PetscMalloc( M*sizeof(int) ); CHKPTRQ(rowlengths);
108077c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,rowlengths,M,BINARY_INT); CHKERRQ(ierr);
10810452661fSBarry Smith     sndcounts = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(sndcounts);
10828965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) sndcounts[i] = rowners[i+1] - rowners[i];
10838965ea79SLois Curfman McInnes     MPI_Scatterv(rowlengths,sndcounts,rowners,MPI_INT,ourlens,rend-rstart,MPI_INT,0,comm);
10840452661fSBarry Smith     PetscFree(sndcounts);
10858965ea79SLois Curfman McInnes   }
10868965ea79SLois Curfman McInnes   else {
10878965ea79SLois Curfman McInnes     MPI_Scatterv(0,0,0,MPI_INT,ourlens,rend-rstart,MPI_INT, 0,comm);
10888965ea79SLois Curfman McInnes   }
10898965ea79SLois Curfman McInnes 
10908965ea79SLois Curfman McInnes   if (!rank) {
10918965ea79SLois Curfman McInnes     /* calculate the number of nonzeros on each processor */
10920452661fSBarry Smith     procsnz = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(procsnz);
1093cddf8d76SBarry Smith     PetscMemzero(procsnz,size*sizeof(int));
10948965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) {
10958965ea79SLois Curfman McInnes       for ( j=rowners[i]; j< rowners[i+1]; j++ ) {
10968965ea79SLois Curfman McInnes         procsnz[i] += rowlengths[j];
10978965ea79SLois Curfman McInnes       }
10988965ea79SLois Curfman McInnes     }
10990452661fSBarry Smith     PetscFree(rowlengths);
11008965ea79SLois Curfman McInnes 
11018965ea79SLois Curfman McInnes     /* determine max buffer needed and allocate it */
11028965ea79SLois Curfman McInnes     maxnz = 0;
11038965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) {
11040452661fSBarry Smith       maxnz = PetscMax(maxnz,procsnz[i]);
11058965ea79SLois Curfman McInnes     }
11060452661fSBarry Smith     cols = (int *) PetscMalloc( maxnz*sizeof(int) ); CHKPTRQ(cols);
11078965ea79SLois Curfman McInnes 
11088965ea79SLois Curfman McInnes     /* read in my part of the matrix column indices  */
11098965ea79SLois Curfman McInnes     nz = procsnz[0];
11100452661fSBarry Smith     mycols = (int *) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(mycols);
111177c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,mycols,nz,BINARY_INT); CHKERRQ(ierr);
11128965ea79SLois Curfman McInnes 
11138965ea79SLois Curfman McInnes     /* read in every one elses and ship off */
11148965ea79SLois Curfman McInnes     for ( i=1; i<size; i++ ) {
11158965ea79SLois Curfman McInnes       nz = procsnz[i];
111677c4ece6SBarry Smith       ierr = PetscBinaryRead(fd,cols,nz,BINARY_INT); CHKERRQ(ierr);
11178965ea79SLois Curfman McInnes       MPI_Send(cols,nz,MPI_INT,i,tag,comm);
11188965ea79SLois Curfman McInnes     }
11190452661fSBarry Smith     PetscFree(cols);
11208965ea79SLois Curfman McInnes   }
11218965ea79SLois Curfman McInnes   else {
11228965ea79SLois Curfman McInnes     /* determine buffer space needed for message */
11238965ea79SLois Curfman McInnes     nz = 0;
11248965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
11258965ea79SLois Curfman McInnes       nz += ourlens[i];
11268965ea79SLois Curfman McInnes     }
11270452661fSBarry Smith     mycols = (int*) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(mycols);
11288965ea79SLois Curfman McInnes 
11298965ea79SLois Curfman McInnes     /* receive message of column indices*/
11308965ea79SLois Curfman McInnes     MPI_Recv(mycols,nz,MPI_INT,0,tag,comm,&status);
11318965ea79SLois Curfman McInnes     MPI_Get_count(&status,MPI_INT,&maxnz);
113239ddd567SLois Curfman McInnes     if (maxnz != nz) SETERRQ(1,"MatLoad_MPIDenseorMPIRow:something is wrong with file");
11338965ea79SLois Curfman McInnes   }
11348965ea79SLois Curfman McInnes 
11358965ea79SLois Curfman McInnes   /* loop over local rows, determining number of off diagonal entries */
1136cddf8d76SBarry Smith   PetscMemzero(offlens,m*sizeof(int));
11378965ea79SLois Curfman McInnes   jj = 0;
11388965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
11398965ea79SLois Curfman McInnes     for ( j=0; j<ourlens[i]; j++ ) {
11408965ea79SLois Curfman McInnes       if (mycols[jj] < rstart || mycols[jj] >= rend) offlens[i]++;
11418965ea79SLois Curfman McInnes       jj++;
11428965ea79SLois Curfman McInnes     }
11438965ea79SLois Curfman McInnes   }
11448965ea79SLois Curfman McInnes 
11458965ea79SLois Curfman McInnes   /* create our matrix */
11468965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
11478965ea79SLois Curfman McInnes     ourlens[i] -= offlens[i];
11488965ea79SLois Curfman McInnes   }
1149b4fd4287SBarry Smith   ierr = MatCreateMPIDense(comm,m,PETSC_DECIDE,M,N,PETSC_NULL,newmat);CHKERRQ(ierr);
11508965ea79SLois Curfman McInnes   A = *newmat;
11518965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
11528965ea79SLois Curfman McInnes     ourlens[i] += offlens[i];
11538965ea79SLois Curfman McInnes   }
11548965ea79SLois Curfman McInnes 
11558965ea79SLois Curfman McInnes   if (!rank) {
11560452661fSBarry Smith     vals = (Scalar *) PetscMalloc( maxnz*sizeof(Scalar) ); CHKPTRQ(vals);
11578965ea79SLois Curfman McInnes 
11588965ea79SLois Curfman McInnes     /* read in my part of the matrix numerical values  */
11598965ea79SLois Curfman McInnes     nz = procsnz[0];
116077c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,vals,nz,BINARY_SCALAR); CHKERRQ(ierr);
11618965ea79SLois Curfman McInnes 
11628965ea79SLois Curfman McInnes     /* insert into matrix */
11638965ea79SLois Curfman McInnes     jj      = rstart;
11648965ea79SLois Curfman McInnes     smycols = mycols;
11658965ea79SLois Curfman McInnes     svals   = vals;
11668965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
11678965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
11688965ea79SLois Curfman McInnes       smycols += ourlens[i];
11698965ea79SLois Curfman McInnes       svals   += ourlens[i];
11708965ea79SLois Curfman McInnes       jj++;
11718965ea79SLois Curfman McInnes     }
11728965ea79SLois Curfman McInnes 
11738965ea79SLois Curfman McInnes     /* read in other processors and ship out */
11748965ea79SLois Curfman McInnes     for ( i=1; i<size; i++ ) {
11758965ea79SLois Curfman McInnes       nz = procsnz[i];
117677c4ece6SBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,BINARY_SCALAR); CHKERRQ(ierr);
11778965ea79SLois Curfman McInnes       MPI_Send(vals,nz,MPIU_SCALAR,i,A->tag,comm);
11788965ea79SLois Curfman McInnes     }
11790452661fSBarry Smith     PetscFree(procsnz);
11808965ea79SLois Curfman McInnes   }
11818965ea79SLois Curfman McInnes   else {
11828965ea79SLois Curfman McInnes     /* receive numeric values */
11830452661fSBarry Smith     vals = (Scalar*) PetscMalloc( nz*sizeof(Scalar) ); CHKPTRQ(vals);
11848965ea79SLois Curfman McInnes 
11858965ea79SLois Curfman McInnes     /* receive message of values*/
11868965ea79SLois Curfman McInnes     MPI_Recv(vals,nz,MPIU_SCALAR,0,A->tag,comm,&status);
11878965ea79SLois Curfman McInnes     MPI_Get_count(&status,MPIU_SCALAR,&maxnz);
118839ddd567SLois Curfman McInnes     if (maxnz != nz) SETERRQ(1,"MatLoad_MPIDenseorMPIRow:something is wrong with file");
11898965ea79SLois Curfman McInnes 
11908965ea79SLois Curfman McInnes     /* insert into matrix */
11918965ea79SLois Curfman McInnes     jj      = rstart;
11928965ea79SLois Curfman McInnes     smycols = mycols;
11938965ea79SLois Curfman McInnes     svals   = vals;
11948965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
11958965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
11968965ea79SLois Curfman McInnes       smycols += ourlens[i];
11978965ea79SLois Curfman McInnes       svals   += ourlens[i];
11988965ea79SLois Curfman McInnes       jj++;
11998965ea79SLois Curfman McInnes     }
12008965ea79SLois Curfman McInnes   }
12010452661fSBarry Smith   PetscFree(ourlens); PetscFree(vals); PetscFree(mycols); PetscFree(rowners);
12028965ea79SLois Curfman McInnes 
12038965ea79SLois Curfman McInnes   ierr = MatAssemblyBegin(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
12048965ea79SLois Curfman McInnes   ierr = MatAssemblyEnd(A,FINAL_ASSEMBLY); CHKERRQ(ierr);
12058965ea79SLois Curfman McInnes   return 0;
12068965ea79SLois Curfman McInnes }
120790ace30eSBarry Smith 
120890ace30eSBarry Smith 
120990ace30eSBarry Smith 
121090ace30eSBarry Smith 
121190ace30eSBarry Smith 
1212