xref: /petsc/src/mat/impls/dense/mpi/mpidense.c (revision 7056b6fc16b254315cf56de01b1780a34f348d02)
18965ea79SLois Curfman McInnes #ifndef lint
2*7056b6fcSBarry Smith static char vcid[] = "$Id: mpidense.c,v 1.46 1996/08/15 12:47:17 bsmith Exp bsmith $";
38965ea79SLois Curfman McInnes #endif
48965ea79SLois Curfman McInnes 
5ed3cc1f0SBarry Smith /*
6ed3cc1f0SBarry Smith    Basic functions for basic parallel dense matrices.
7ed3cc1f0SBarry Smith */
8ed3cc1f0SBarry Smith 
970f55243SBarry Smith #include "src/mat/impls/dense/mpi/mpidense.h"
10f5eb4b81SSatish Balay #include "src/vec/vecimpl.h"
118965ea79SLois Curfman McInnes 
12*7056b6fcSBarry Smith static int MatSetValues_MPIDense(Mat mat,int m,int *idxm,int n,int *idxn,Scalar *v,InsertMode addv)
138965ea79SLois Curfman McInnes {
1439b7565bSBarry Smith   Mat_MPIDense *A = (Mat_MPIDense *) mat->data;
1539b7565bSBarry Smith   int          ierr, i, j, rstart = A->rstart, rend = A->rend, row;
1639b7565bSBarry Smith   int          roworiented = A->roworiented;
178965ea79SLois Curfman McInnes 
1839b7565bSBarry Smith   if (A->insertmode != NOT_SET_VALUES && A->insertmode != addv) {
1939ddd567SLois Curfman McInnes     SETERRQ(1,"MatSetValues_MPIDense:Cannot mix inserts and adds");
208965ea79SLois Curfman McInnes   }
2139b7565bSBarry Smith   A->insertmode = addv;
228965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
2339ddd567SLois Curfman McInnes     if (idxm[i] < 0) SETERRQ(1,"MatSetValues_MPIDense:Negative row");
2439b7565bSBarry Smith     if (idxm[i] >= A->M) SETERRQ(1,"MatSetValues_MPIDense:Row too large");
258965ea79SLois Curfman McInnes     if (idxm[i] >= rstart && idxm[i] < rend) {
268965ea79SLois Curfman McInnes       row = idxm[i] - rstart;
2739b7565bSBarry Smith       if (roworiented) {
2839b7565bSBarry Smith         ierr = MatSetValues(A->A,1,&row,n,idxn,v+i*n,addv); CHKERRQ(ierr);
2939b7565bSBarry Smith       }
3039b7565bSBarry Smith       else {
318965ea79SLois Curfman McInnes         for ( j=0; j<n; j++ ) {
3239ddd567SLois Curfman McInnes           if (idxn[j] < 0) SETERRQ(1,"MatSetValues_MPIDense:Negative column");
3339b7565bSBarry Smith           if (idxn[j] >= A->N) SETERRQ(1,"MatSetValues_MPIDense:Column too large");
3439b7565bSBarry Smith           ierr = MatSetValues(A->A,1,&row,1,&idxn[j],v+i+j*m,addv); CHKERRQ(ierr);
3539b7565bSBarry Smith         }
368965ea79SLois Curfman McInnes       }
378965ea79SLois Curfman McInnes     }
388965ea79SLois Curfman McInnes     else {
3939b7565bSBarry Smith       if (roworiented) {
4039b7565bSBarry Smith         ierr = StashValues_Private(&A->stash,idxm[i],n,idxn,v+i*n,addv); CHKERRQ(ierr);
4139b7565bSBarry Smith       }
4239b7565bSBarry Smith       else { /* must stash each seperately */
4339b7565bSBarry Smith         row = idxm[i];
4439b7565bSBarry Smith         for ( j=0; j<n; j++ ) {
45*7056b6fcSBarry Smith           ierr = StashValues_Private(&A->stash,row,1,&idxn[j],v+i+j*m,addv);CHKERRQ(ierr);
4639b7565bSBarry Smith         }
4739b7565bSBarry Smith       }
48b49de8d1SLois Curfman McInnes     }
49b49de8d1SLois Curfman McInnes   }
50b49de8d1SLois Curfman McInnes   return 0;
51b49de8d1SLois Curfman McInnes }
52b49de8d1SLois Curfman McInnes 
53b49de8d1SLois Curfman McInnes static int MatGetValues_MPIDense(Mat mat,int m,int *idxm,int n,int *idxn,Scalar *v)
54b49de8d1SLois Curfman McInnes {
55b49de8d1SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
56b49de8d1SLois Curfman McInnes   int          ierr, i, j, rstart = mdn->rstart, rend = mdn->rend, row;
57b49de8d1SLois Curfman McInnes 
58b49de8d1SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
59b49de8d1SLois Curfman McInnes     if (idxm[i] < 0) SETERRQ(1,"MatGetValues_MPIDense:Negative row");
60b49de8d1SLois Curfman McInnes     if (idxm[i] >= mdn->M) SETERRQ(1,"MatGetValues_MPIDense:Row too large");
61b49de8d1SLois Curfman McInnes     if (idxm[i] >= rstart && idxm[i] < rend) {
62b49de8d1SLois Curfman McInnes       row = idxm[i] - rstart;
63b49de8d1SLois Curfman McInnes       for ( j=0; j<n; j++ ) {
64b49de8d1SLois Curfman McInnes         if (idxn[j] < 0) SETERRQ(1,"MatGetValues_MPIDense:Negative column");
65b49de8d1SLois Curfman McInnes         if (idxn[j] >= mdn->N)
66b49de8d1SLois Curfman McInnes           SETERRQ(1,"MatGetValues_MPIDense:Column too large");
67b49de8d1SLois Curfman McInnes         ierr = MatGetValues(mdn->A,1,&row,1,&idxn[j],v+i*n+j); CHKERRQ(ierr);
68b49de8d1SLois Curfman McInnes       }
69b49de8d1SLois Curfman McInnes     }
70b49de8d1SLois Curfman McInnes     else {
71b49de8d1SLois Curfman McInnes       SETERRQ(1,"MatGetValues_MPIDense:Only local values currently supported");
728965ea79SLois Curfman McInnes     }
738965ea79SLois Curfman McInnes   }
748965ea79SLois Curfman McInnes   return 0;
758965ea79SLois Curfman McInnes }
768965ea79SLois Curfman McInnes 
77ff14e315SSatish Balay static int MatGetArray_MPIDense(Mat A,Scalar **array)
78ff14e315SSatish Balay {
79ff14e315SSatish Balay   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
80ff14e315SSatish Balay   int ierr;
81ff14e315SSatish Balay 
82ff14e315SSatish Balay   ierr = MatGetArray(a->A,array); CHKERRQ(ierr);
83ff14e315SSatish Balay   return 0;
84ff14e315SSatish Balay }
85ff14e315SSatish Balay 
86ff14e315SSatish Balay static int MatRestoreArray_MPIDense(Mat A,Scalar **array)
87ff14e315SSatish Balay {
88ff14e315SSatish Balay   return 0;
89ff14e315SSatish Balay }
90ff14e315SSatish Balay 
9139ddd567SLois Curfman McInnes static int MatAssemblyBegin_MPIDense(Mat mat,MatAssemblyType mode)
928965ea79SLois Curfman McInnes {
9339ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
948965ea79SLois Curfman McInnes   MPI_Comm     comm = mat->comm;
9539ddd567SLois Curfman McInnes   int          size = mdn->size, *owners = mdn->rowners, rank = mdn->rank;
968965ea79SLois Curfman McInnes   int          *nprocs,i,j,idx,*procs,nsends,nreceives,nmax,*work;
9739ddd567SLois Curfman McInnes   int          tag = mat->tag, *owner,*starts,count,ierr;
988965ea79SLois Curfman McInnes   InsertMode   addv;
9939ddd567SLois Curfman McInnes   MPI_Request  *send_waits,*recv_waits;
1008965ea79SLois Curfman McInnes   Scalar       *rvalues,*svalues;
1018965ea79SLois Curfman McInnes 
1028965ea79SLois Curfman McInnes   /* make sure all processors are either in INSERTMODE or ADDMODE */
1036d84be18SBarry Smith   MPI_Allreduce(&mdn->insertmode,&addv,1,MPI_INT,MPI_BOR,comm);
104*7056b6fcSBarry Smith   if (addv == (ADD_VALUES|INSERT_VALUES)) {
105*7056b6fcSBarry Smith     SETERRQ(1,"MatAssemblyBegin_MPIDense:Cannot mix adds/inserts on different procs");
1068965ea79SLois Curfman McInnes   }
10739ddd567SLois Curfman McInnes   mdn->insertmode = addv; /* in case this processor had no cache */
1088965ea79SLois Curfman McInnes 
1098965ea79SLois Curfman McInnes   /*  first count number of contributors to each processor */
1100452661fSBarry Smith   nprocs = (int *) PetscMalloc( 2*size*sizeof(int) ); CHKPTRQ(nprocs);
111cddf8d76SBarry Smith   PetscMemzero(nprocs,2*size*sizeof(int)); procs = nprocs + size;
1120452661fSBarry Smith   owner = (int *) PetscMalloc( (mdn->stash.n+1)*sizeof(int) ); CHKPTRQ(owner);
11339ddd567SLois Curfman McInnes   for ( i=0; i<mdn->stash.n; i++ ) {
11439ddd567SLois Curfman McInnes     idx = mdn->stash.idx[i];
1158965ea79SLois Curfman McInnes     for ( j=0; j<size; j++ ) {
1168965ea79SLois Curfman McInnes       if (idx >= owners[j] && idx < owners[j+1]) {
1178965ea79SLois Curfman McInnes         nprocs[j]++; procs[j] = 1; owner[i] = j; break;
1188965ea79SLois Curfman McInnes       }
1198965ea79SLois Curfman McInnes     }
1208965ea79SLois Curfman McInnes   }
1218965ea79SLois Curfman McInnes   nsends = 0;  for ( i=0; i<size; i++ ) { nsends += procs[i];}
1228965ea79SLois Curfman McInnes 
1238965ea79SLois Curfman McInnes   /* inform other processors of number of messages and max length*/
1240452661fSBarry Smith   work = (int *) PetscMalloc( size*sizeof(int) ); CHKPTRQ(work);
1256d84be18SBarry Smith   MPI_Allreduce(procs,work,size,MPI_INT,MPI_SUM,comm);
1268965ea79SLois Curfman McInnes   nreceives = work[rank];
1276d84be18SBarry Smith   MPI_Allreduce(nprocs,work,size,MPI_INT,MPI_MAX,comm);
1288965ea79SLois Curfman McInnes   nmax = work[rank];
1290452661fSBarry Smith   PetscFree(work);
1308965ea79SLois Curfman McInnes 
1318965ea79SLois Curfman McInnes   /* post receives:
1328965ea79SLois Curfman McInnes        1) each message will consist of ordered pairs
1338965ea79SLois Curfman McInnes      (global index,value) we store the global index as a double
1348965ea79SLois Curfman McInnes      to simplify the message passing.
1358965ea79SLois Curfman McInnes        2) since we don't know how long each individual message is we
1368965ea79SLois Curfman McInnes      allocate the largest needed buffer for each receive. Potentially
1378965ea79SLois Curfman McInnes      this is a lot of wasted space.
1388965ea79SLois Curfman McInnes 
1398965ea79SLois Curfman McInnes        This could be done better.
1408965ea79SLois Curfman McInnes   */
1410452661fSBarry Smith   rvalues = (Scalar *) PetscMalloc(3*(nreceives+1)*(nmax+1)*sizeof(Scalar));
1428965ea79SLois Curfman McInnes   CHKPTRQ(rvalues);
1430452661fSBarry Smith   recv_waits = (MPI_Request *) PetscMalloc((nreceives+1)*sizeof(MPI_Request));
1448965ea79SLois Curfman McInnes   CHKPTRQ(recv_waits);
1458965ea79SLois Curfman McInnes   for ( i=0; i<nreceives; i++ ) {
146*7056b6fcSBarry Smith     MPI_Irecv(rvalues+3*nmax*i,3*nmax,MPIU_SCALAR,MPI_ANY_SOURCE,tag,comm,recv_waits+i);
1478965ea79SLois Curfman McInnes   }
1488965ea79SLois Curfman McInnes 
1498965ea79SLois Curfman McInnes   /* do sends:
1508965ea79SLois Curfman McInnes       1) starts[i] gives the starting index in svalues for stuff going to
1518965ea79SLois Curfman McInnes          the ith processor
1528965ea79SLois Curfman McInnes   */
1530452661fSBarry Smith   svalues = (Scalar *) PetscMalloc( 3*(mdn->stash.n+1)*sizeof(Scalar) );
15439ddd567SLois Curfman McInnes   CHKPTRQ(svalues);
1550452661fSBarry Smith   send_waits = (MPI_Request *) PetscMalloc( (nsends+1)*sizeof(MPI_Request));
1568965ea79SLois Curfman McInnes   CHKPTRQ(send_waits);
1570452661fSBarry Smith   starts = (int *) PetscMalloc( size*sizeof(int) ); CHKPTRQ(starts);
1588965ea79SLois Curfman McInnes   starts[0] = 0;
1598965ea79SLois Curfman McInnes   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
16039ddd567SLois Curfman McInnes   for ( i=0; i<mdn->stash.n; i++ ) {
16139ddd567SLois Curfman McInnes     svalues[3*starts[owner[i]]]       = (Scalar)  mdn->stash.idx[i];
16239ddd567SLois Curfman McInnes     svalues[3*starts[owner[i]]+1]     = (Scalar)  mdn->stash.idy[i];
16339ddd567SLois Curfman McInnes     svalues[3*(starts[owner[i]]++)+2] =  mdn->stash.array[i];
1648965ea79SLois Curfman McInnes   }
1650452661fSBarry Smith   PetscFree(owner);
1668965ea79SLois Curfman McInnes   starts[0] = 0;
1678965ea79SLois Curfman McInnes   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
1688965ea79SLois Curfman McInnes   count = 0;
1698965ea79SLois Curfman McInnes   for ( i=0; i<size; i++ ) {
1708965ea79SLois Curfman McInnes     if (procs[i]) {
171*7056b6fcSBarry Smith       MPI_Isend(svalues+3*starts[i],3*nprocs[i],MPIU_SCALAR,i,tag,comm,send_waits+count++);
1728965ea79SLois Curfman McInnes     }
1738965ea79SLois Curfman McInnes   }
1740452661fSBarry Smith   PetscFree(starts); PetscFree(nprocs);
1758965ea79SLois Curfman McInnes 
1768965ea79SLois Curfman McInnes   /* Free cache space */
17739ddd567SLois Curfman McInnes   ierr = StashDestroy_Private(&mdn->stash); CHKERRQ(ierr);
1788965ea79SLois Curfman McInnes 
17939ddd567SLois Curfman McInnes   mdn->svalues    = svalues;    mdn->rvalues = rvalues;
18039ddd567SLois Curfman McInnes   mdn->nsends     = nsends;     mdn->nrecvs = nreceives;
18139ddd567SLois Curfman McInnes   mdn->send_waits = send_waits; mdn->recv_waits = recv_waits;
18239ddd567SLois Curfman McInnes   mdn->rmax       = nmax;
1838965ea79SLois Curfman McInnes 
1848965ea79SLois Curfman McInnes   return 0;
1858965ea79SLois Curfman McInnes }
18639ddd567SLois Curfman McInnes extern int MatSetUpMultiply_MPIDense(Mat);
1878965ea79SLois Curfman McInnes 
18839ddd567SLois Curfman McInnes static int MatAssemblyEnd_MPIDense(Mat mat,MatAssemblyType mode)
1898965ea79SLois Curfman McInnes {
19039ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
1918965ea79SLois Curfman McInnes   MPI_Status   *send_status,recv_status;
19239ddd567SLois Curfman McInnes   int          imdex, nrecvs=mdn->nrecvs, count=nrecvs, i, n, ierr, row, col;
1938965ea79SLois Curfman McInnes   Scalar       *values,val;
19439ddd567SLois Curfman McInnes   InsertMode   addv = mdn->insertmode;
1958965ea79SLois Curfman McInnes 
1968965ea79SLois Curfman McInnes   /*  wait on receives */
1978965ea79SLois Curfman McInnes   while (count) {
19839ddd567SLois Curfman McInnes     MPI_Waitany(nrecvs,mdn->recv_waits,&imdex,&recv_status);
1998965ea79SLois Curfman McInnes     /* unpack receives into our local space */
20039ddd567SLois Curfman McInnes     values = mdn->rvalues + 3*imdex*mdn->rmax;
2018965ea79SLois Curfman McInnes     MPI_Get_count(&recv_status,MPIU_SCALAR,&n);
2028965ea79SLois Curfman McInnes     n = n/3;
2038965ea79SLois Curfman McInnes     for ( i=0; i<n; i++ ) {
204227d817aSBarry Smith       row = (int) PetscReal(values[3*i]) - mdn->rstart;
205227d817aSBarry Smith       col = (int) PetscReal(values[3*i+1]);
2068965ea79SLois Curfman McInnes       val = values[3*i+2];
20739ddd567SLois Curfman McInnes       if (col >= 0 && col < mdn->N) {
20839ddd567SLois Curfman McInnes         MatSetValues(mdn->A,1,&row,1,&col,&val,addv);
2098965ea79SLois Curfman McInnes       }
21039ddd567SLois Curfman McInnes       else {SETERRQ(1,"MatAssemblyEnd_MPIDense:Invalid column");}
2118965ea79SLois Curfman McInnes     }
2128965ea79SLois Curfman McInnes     count--;
2138965ea79SLois Curfman McInnes   }
2140452661fSBarry Smith   PetscFree(mdn->recv_waits); PetscFree(mdn->rvalues);
2158965ea79SLois Curfman McInnes 
2168965ea79SLois Curfman McInnes   /* wait on sends */
21739ddd567SLois Curfman McInnes   if (mdn->nsends) {
218*7056b6fcSBarry Smith     send_status = (MPI_Status *) PetscMalloc(mdn->nsends*sizeof(MPI_Status));CHKPTRQ(send_status);
21939ddd567SLois Curfman McInnes     MPI_Waitall(mdn->nsends,mdn->send_waits,send_status);
2200452661fSBarry Smith     PetscFree(send_status);
2218965ea79SLois Curfman McInnes   }
2220452661fSBarry Smith   PetscFree(mdn->send_waits); PetscFree(mdn->svalues);
2238965ea79SLois Curfman McInnes 
22439ddd567SLois Curfman McInnes   mdn->insertmode = NOT_SET_VALUES;
22539ddd567SLois Curfman McInnes   ierr = MatAssemblyBegin(mdn->A,mode); CHKERRQ(ierr);
22639ddd567SLois Curfman McInnes   ierr = MatAssemblyEnd(mdn->A,mode); CHKERRQ(ierr);
2278965ea79SLois Curfman McInnes 
2286d4a8577SBarry Smith   if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) {
22939ddd567SLois Curfman McInnes     ierr = MatSetUpMultiply_MPIDense(mat); CHKERRQ(ierr);
2308965ea79SLois Curfman McInnes   }
2318965ea79SLois Curfman McInnes   return 0;
2328965ea79SLois Curfman McInnes }
2338965ea79SLois Curfman McInnes 
23439ddd567SLois Curfman McInnes static int MatZeroEntries_MPIDense(Mat A)
2358965ea79SLois Curfman McInnes {
23639ddd567SLois Curfman McInnes   Mat_MPIDense *l = (Mat_MPIDense *) A->data;
23739ddd567SLois Curfman McInnes   return MatZeroEntries(l->A);
2388965ea79SLois Curfman McInnes }
2398965ea79SLois Curfman McInnes 
2408965ea79SLois Curfman McInnes /* the code does not do the diagonal entries correctly unless the
2418965ea79SLois Curfman McInnes    matrix is square and the column and row owerships are identical.
2428965ea79SLois Curfman McInnes    This is a BUG. The only way to fix it seems to be to access
2433501a2bdSLois Curfman McInnes    mdn->A and mdn->B directly and not through the MatZeroRows()
2448965ea79SLois Curfman McInnes    routine.
2458965ea79SLois Curfman McInnes */
24639ddd567SLois Curfman McInnes static int MatZeroRows_MPIDense(Mat A,IS is,Scalar *diag)
2478965ea79SLois Curfman McInnes {
24839ddd567SLois Curfman McInnes   Mat_MPIDense   *l = (Mat_MPIDense *) A->data;
2498965ea79SLois Curfman McInnes   int            i,ierr,N, *rows,*owners = l->rowners,size = l->size;
2508965ea79SLois Curfman McInnes   int            *procs,*nprocs,j,found,idx,nsends,*work;
2518965ea79SLois Curfman McInnes   int            nmax,*svalues,*starts,*owner,nrecvs,rank = l->rank;
2528965ea79SLois Curfman McInnes   int            *rvalues,tag = A->tag,count,base,slen,n,*source;
2538965ea79SLois Curfman McInnes   int            *lens,imdex,*lrows,*values;
2548965ea79SLois Curfman McInnes   MPI_Comm       comm = A->comm;
2558965ea79SLois Curfman McInnes   MPI_Request    *send_waits,*recv_waits;
2568965ea79SLois Curfman McInnes   MPI_Status     recv_status,*send_status;
2578965ea79SLois Curfman McInnes   IS             istmp;
2588965ea79SLois Curfman McInnes 
25977c4ece6SBarry Smith   ierr = ISGetSize(is,&N); CHKERRQ(ierr);
2608965ea79SLois Curfman McInnes   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
2618965ea79SLois Curfman McInnes 
2628965ea79SLois Curfman McInnes   /*  first count number of contributors to each processor */
2630452661fSBarry Smith   nprocs = (int *) PetscMalloc( 2*size*sizeof(int) ); CHKPTRQ(nprocs);
264cddf8d76SBarry Smith   PetscMemzero(nprocs,2*size*sizeof(int)); procs = nprocs + size;
2650452661fSBarry Smith   owner = (int *) PetscMalloc((N+1)*sizeof(int)); CHKPTRQ(owner); /* see note*/
2668965ea79SLois Curfman McInnes   for ( i=0; i<N; i++ ) {
2678965ea79SLois Curfman McInnes     idx = rows[i];
2688965ea79SLois Curfman McInnes     found = 0;
2698965ea79SLois Curfman McInnes     for ( j=0; j<size; j++ ) {
2708965ea79SLois Curfman McInnes       if (idx >= owners[j] && idx < owners[j+1]) {
2718965ea79SLois Curfman McInnes         nprocs[j]++; procs[j] = 1; owner[i] = j; found = 1; break;
2728965ea79SLois Curfman McInnes       }
2738965ea79SLois Curfman McInnes     }
27439ddd567SLois Curfman McInnes     if (!found) SETERRQ(1,"MatZeroRows_MPIDense:Index out of range");
2758965ea79SLois Curfman McInnes   }
2768965ea79SLois Curfman McInnes   nsends = 0;  for ( i=0; i<size; i++ ) { nsends += procs[i];}
2778965ea79SLois Curfman McInnes 
2788965ea79SLois Curfman McInnes   /* inform other processors of number of messages and max length*/
2790452661fSBarry Smith   work = (int *) PetscMalloc( size*sizeof(int) ); CHKPTRQ(work);
2808965ea79SLois Curfman McInnes   MPI_Allreduce( procs, work,size,MPI_INT,MPI_SUM,comm);
2818965ea79SLois Curfman McInnes   nrecvs = work[rank];
2828965ea79SLois Curfman McInnes   MPI_Allreduce( nprocs, work,size,MPI_INT,MPI_MAX,comm);
2838965ea79SLois Curfman McInnes   nmax = work[rank];
2840452661fSBarry Smith   PetscFree(work);
2858965ea79SLois Curfman McInnes 
2868965ea79SLois Curfman McInnes   /* post receives:   */
2870452661fSBarry Smith   rvalues = (int *) PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(int)); /*see note */
2888965ea79SLois Curfman McInnes   CHKPTRQ(rvalues);
2890452661fSBarry Smith   recv_waits = (MPI_Request *) PetscMalloc((nrecvs+1)*sizeof(MPI_Request));
2908965ea79SLois Curfman McInnes   CHKPTRQ(recv_waits);
2918965ea79SLois Curfman McInnes   for ( i=0; i<nrecvs; i++ ) {
2928965ea79SLois Curfman McInnes     MPI_Irecv(rvalues+nmax*i,nmax,MPI_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);
2938965ea79SLois Curfman McInnes   }
2948965ea79SLois Curfman McInnes 
2958965ea79SLois Curfman McInnes   /* do sends:
2968965ea79SLois Curfman McInnes       1) starts[i] gives the starting index in svalues for stuff going to
2978965ea79SLois Curfman McInnes          the ith processor
2988965ea79SLois Curfman McInnes   */
2990452661fSBarry Smith   svalues    = (int *) PetscMalloc( (N+1)*sizeof(int) ); CHKPTRQ(svalues);
300*7056b6fcSBarry Smith   send_waits = (MPI_Request *) PetscMalloc((nsends+1)*sizeof(MPI_Request));CHKPTRQ(send_waits);
3010452661fSBarry Smith   starts     = (int *) PetscMalloc( (size+1)*sizeof(int) ); CHKPTRQ(starts);
3028965ea79SLois Curfman McInnes   starts[0]  = 0;
3038965ea79SLois Curfman McInnes   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
3048965ea79SLois Curfman McInnes   for ( i=0; i<N; i++ ) {
3058965ea79SLois Curfman McInnes     svalues[starts[owner[i]]++] = rows[i];
3068965ea79SLois Curfman McInnes   }
3078965ea79SLois Curfman McInnes   ISRestoreIndices(is,&rows);
3088965ea79SLois Curfman McInnes 
3098965ea79SLois Curfman McInnes   starts[0] = 0;
3108965ea79SLois Curfman McInnes   for ( i=1; i<size+1; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
3118965ea79SLois Curfman McInnes   count = 0;
3128965ea79SLois Curfman McInnes   for ( i=0; i<size; i++ ) {
3138965ea79SLois Curfman McInnes     if (procs[i]) {
3148965ea79SLois Curfman McInnes       MPI_Isend(svalues+starts[i],nprocs[i],MPI_INT,i,tag,comm,send_waits+count++);
3158965ea79SLois Curfman McInnes     }
3168965ea79SLois Curfman McInnes   }
3170452661fSBarry Smith   PetscFree(starts);
3188965ea79SLois Curfman McInnes 
3198965ea79SLois Curfman McInnes   base = owners[rank];
3208965ea79SLois Curfman McInnes 
3218965ea79SLois Curfman McInnes   /*  wait on receives */
3220452661fSBarry Smith   lens   = (int *) PetscMalloc( 2*(nrecvs+1)*sizeof(int) ); CHKPTRQ(lens);
3238965ea79SLois Curfman McInnes   source = lens + nrecvs;
3248965ea79SLois Curfman McInnes   count  = nrecvs; slen = 0;
3258965ea79SLois Curfman McInnes   while (count) {
3268965ea79SLois Curfman McInnes     MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);
3278965ea79SLois Curfman McInnes     /* unpack receives into our local space */
3288965ea79SLois Curfman McInnes     MPI_Get_count(&recv_status,MPI_INT,&n);
3298965ea79SLois Curfman McInnes     source[imdex]  = recv_status.MPI_SOURCE;
3308965ea79SLois Curfman McInnes     lens[imdex]  = n;
3318965ea79SLois Curfman McInnes     slen += n;
3328965ea79SLois Curfman McInnes     count--;
3338965ea79SLois Curfman McInnes   }
3340452661fSBarry Smith   PetscFree(recv_waits);
3358965ea79SLois Curfman McInnes 
3368965ea79SLois Curfman McInnes   /* move the data into the send scatter */
3370452661fSBarry Smith   lrows = (int *) PetscMalloc( (slen+1)*sizeof(int) ); CHKPTRQ(lrows);
3388965ea79SLois Curfman McInnes   count = 0;
3398965ea79SLois Curfman McInnes   for ( i=0; i<nrecvs; i++ ) {
3408965ea79SLois Curfman McInnes     values = rvalues + i*nmax;
3418965ea79SLois Curfman McInnes     for ( j=0; j<lens[i]; j++ ) {
3428965ea79SLois Curfman McInnes       lrows[count++] = values[j] - base;
3438965ea79SLois Curfman McInnes     }
3448965ea79SLois Curfman McInnes   }
3450452661fSBarry Smith   PetscFree(rvalues); PetscFree(lens);
3460452661fSBarry Smith   PetscFree(owner); PetscFree(nprocs);
3478965ea79SLois Curfman McInnes 
3488965ea79SLois Curfman McInnes   /* actually zap the local rows */
349537820f0SBarry Smith   ierr = ISCreateGeneral(MPI_COMM_SELF,slen,lrows,&istmp);CHKERRQ(ierr);
3508965ea79SLois Curfman McInnes   PLogObjectParent(A,istmp);
3510452661fSBarry Smith   PetscFree(lrows);
3528965ea79SLois Curfman McInnes   ierr = MatZeroRows(l->A,istmp,diag); CHKERRQ(ierr);
3538965ea79SLois Curfman McInnes   ierr = ISDestroy(istmp); CHKERRQ(ierr);
3548965ea79SLois Curfman McInnes 
3558965ea79SLois Curfman McInnes   /* wait on sends */
3568965ea79SLois Curfman McInnes   if (nsends) {
357*7056b6fcSBarry Smith     send_status = (MPI_Status *) PetscMalloc(nsends*sizeof(MPI_Status));CHKPTRQ(send_status);
3588965ea79SLois Curfman McInnes     MPI_Waitall(nsends,send_waits,send_status);
3590452661fSBarry Smith     PetscFree(send_status);
3608965ea79SLois Curfman McInnes   }
3610452661fSBarry Smith   PetscFree(send_waits); PetscFree(svalues);
3628965ea79SLois Curfman McInnes 
3638965ea79SLois Curfman McInnes   return 0;
3648965ea79SLois Curfman McInnes }
3658965ea79SLois Curfman McInnes 
36639ddd567SLois Curfman McInnes static int MatMult_MPIDense(Mat mat,Vec xx,Vec yy)
3678965ea79SLois Curfman McInnes {
36839ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3698965ea79SLois Curfman McInnes   int          ierr;
370c456f294SBarry Smith 
371*7056b6fcSBarry Smith   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_ALL,mdn->Mvctx);CHKERRQ(ierr);
372*7056b6fcSBarry Smith   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_ALL,mdn->Mvctx);CHKERRQ(ierr);
37344cd7ae7SLois Curfman McInnes   ierr = MatMult_SeqDense(mdn->A,mdn->lvec,yy); CHKERRQ(ierr);
3748965ea79SLois Curfman McInnes   return 0;
3758965ea79SLois Curfman McInnes }
3768965ea79SLois Curfman McInnes 
37739ddd567SLois Curfman McInnes static int MatMultAdd_MPIDense(Mat mat,Vec xx,Vec yy,Vec zz)
3788965ea79SLois Curfman McInnes {
37939ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3808965ea79SLois Curfman McInnes   int          ierr;
381c456f294SBarry Smith 
382c456f294SBarry Smith   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_ALL,mdn->Mvctx);CHKERRQ(ierr);
383c456f294SBarry Smith   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_ALL,mdn->Mvctx);CHKERRQ(ierr);
38444cd7ae7SLois Curfman McInnes   ierr = MatMultAdd_SeqDense(mdn->A,mdn->lvec,yy,zz); CHKERRQ(ierr);
3858965ea79SLois Curfman McInnes   return 0;
3868965ea79SLois Curfman McInnes }
3878965ea79SLois Curfman McInnes 
388096963f5SLois Curfman McInnes static int MatMultTrans_MPIDense(Mat A,Vec xx,Vec yy)
389096963f5SLois Curfman McInnes {
390096963f5SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
391096963f5SLois Curfman McInnes   int          ierr;
3923501a2bdSLois Curfman McInnes   Scalar       zero = 0.0;
393096963f5SLois Curfman McInnes 
3943501a2bdSLois Curfman McInnes   ierr = VecSet(&zero,yy); CHKERRQ(ierr);
39544cd7ae7SLois Curfman McInnes   ierr = MatMultTrans_SeqDense(a->A,xx,a->lvec); CHKERRQ(ierr);
396537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
397537820f0SBarry Smith   ierr = VecScatterEnd(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
398096963f5SLois Curfman McInnes   return 0;
399096963f5SLois Curfman McInnes }
400096963f5SLois Curfman McInnes 
401096963f5SLois Curfman McInnes static int MatMultTransAdd_MPIDense(Mat A,Vec xx,Vec yy,Vec zz)
402096963f5SLois Curfman McInnes {
403096963f5SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
404096963f5SLois Curfman McInnes   int          ierr;
405096963f5SLois Curfman McInnes 
4063501a2bdSLois Curfman McInnes   ierr = VecCopy(yy,zz); CHKERRQ(ierr);
40744cd7ae7SLois Curfman McInnes   ierr = MatMultTrans_SeqDense(a->A,xx,a->lvec); CHKERRQ(ierr);
408537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
409537820f0SBarry Smith   ierr = VecScatterEnd(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
410096963f5SLois Curfman McInnes   return 0;
411096963f5SLois Curfman McInnes }
412096963f5SLois Curfman McInnes 
41339ddd567SLois Curfman McInnes static int MatGetDiagonal_MPIDense(Mat A,Vec v)
4148965ea79SLois Curfman McInnes {
41539ddd567SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
416096963f5SLois Curfman McInnes   Mat_SeqDense *aloc = (Mat_SeqDense *) a->A->data;
41744cd7ae7SLois Curfman McInnes   int          ierr, len, i, n, m = a->m, radd;
41844cd7ae7SLois Curfman McInnes   Scalar       *x, zero = 0.0;
419ed3cc1f0SBarry Smith 
42044cd7ae7SLois Curfman McInnes   VecSet(&zero,v);
421096963f5SLois Curfman McInnes   ierr = VecGetArray(v,&x); CHKERRQ(ierr);
422096963f5SLois Curfman McInnes   ierr = VecGetSize(v,&n); CHKERRQ(ierr);
423096963f5SLois Curfman McInnes   if (n != a->M) SETERRQ(1,"MatGetDiagonal_SeqDense:Nonconforming mat and vec");
42444cd7ae7SLois Curfman McInnes   len = PetscMin(aloc->m,aloc->n);
4257ddc982cSLois Curfman McInnes   radd = a->rstart*m;
42644cd7ae7SLois Curfman McInnes   for ( i=0; i<len; i++ ) {
427096963f5SLois Curfman McInnes     x[i] = aloc->v[radd + i*m + i];
428096963f5SLois Curfman McInnes   }
429096963f5SLois Curfman McInnes   return 0;
4308965ea79SLois Curfman McInnes }
4318965ea79SLois Curfman McInnes 
43239ddd567SLois Curfman McInnes static int MatDestroy_MPIDense(PetscObject obj)
4338965ea79SLois Curfman McInnes {
4348965ea79SLois Curfman McInnes   Mat          mat = (Mat) obj;
4353501a2bdSLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
4368965ea79SLois Curfman McInnes   int          ierr;
437ed3cc1f0SBarry Smith 
4388965ea79SLois Curfman McInnes #if defined(PETSC_LOG)
4393501a2bdSLois Curfman McInnes   PLogObjectState(obj,"Rows=%d, Cols=%d",mdn->M,mdn->N);
4408965ea79SLois Curfman McInnes #endif
4410452661fSBarry Smith   PetscFree(mdn->rowners);
4423501a2bdSLois Curfman McInnes   ierr = MatDestroy(mdn->A); CHKERRQ(ierr);
4433501a2bdSLois Curfman McInnes   if (mdn->lvec)   VecDestroy(mdn->lvec);
4443501a2bdSLois Curfman McInnes   if (mdn->Mvctx)  VecScatterDestroy(mdn->Mvctx);
445622d7880SLois Curfman McInnes   if (mdn->factor) {
446622d7880SLois Curfman McInnes     if (mdn->factor->temp)   PetscFree(mdn->factor->temp);
447622d7880SLois Curfman McInnes     if (mdn->factor->tag)    PetscFree(mdn->factor->tag);
448622d7880SLois Curfman McInnes     if (mdn->factor->pivots) PetscFree(mdn->factor->pivots);
449622d7880SLois Curfman McInnes     PetscFree(mdn->factor);
450622d7880SLois Curfman McInnes   }
4510452661fSBarry Smith   PetscFree(mdn);
4528965ea79SLois Curfman McInnes   PLogObjectDestroy(mat);
4530452661fSBarry Smith   PetscHeaderDestroy(mat);
4548965ea79SLois Curfman McInnes   return 0;
4558965ea79SLois Curfman McInnes }
45639ddd567SLois Curfman McInnes 
4578965ea79SLois Curfman McInnes #include "pinclude/pviewer.h"
4588965ea79SLois Curfman McInnes 
45939ddd567SLois Curfman McInnes static int MatView_MPIDense_Binary(Mat mat,Viewer viewer)
4608965ea79SLois Curfman McInnes {
46139ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
4628965ea79SLois Curfman McInnes   int          ierr;
463*7056b6fcSBarry Smith 
46439ddd567SLois Curfman McInnes   if (mdn->size == 1) {
46539ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
4668965ea79SLois Curfman McInnes   }
46739ddd567SLois Curfman McInnes   else SETERRQ(1,"MatView_MPIDense_Binary:Only uniprocessor output supported");
4688965ea79SLois Curfman McInnes   return 0;
4698965ea79SLois Curfman McInnes }
4708965ea79SLois Curfman McInnes 
47139ddd567SLois Curfman McInnes static int MatView_MPIDense_ASCII(Mat mat,Viewer viewer)
4728965ea79SLois Curfman McInnes {
47339ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
47439ddd567SLois Curfman McInnes   int          ierr, format;
4758965ea79SLois Curfman McInnes   FILE         *fd;
47619bcc07fSBarry Smith   ViewerType   vtype;
4778965ea79SLois Curfman McInnes 
47819bcc07fSBarry Smith   ViewerGetType(viewer,&vtype);
47990ace30eSBarry Smith   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
48090ace30eSBarry Smith   ierr = ViewerGetFormat(viewer,&format);
48190ace30eSBarry Smith   if (format == ASCII_FORMAT_INFO_DETAILED) {
482096963f5SLois Curfman McInnes     int nz, nzalloc, mem, rank;
483096963f5SLois Curfman McInnes     MPI_Comm_rank(mat->comm,&rank);
484096963f5SLois Curfman McInnes     ierr = MatGetInfo(mat,MAT_LOCAL,&nz,&nzalloc,&mem);
48577c4ece6SBarry Smith     PetscSequentialPhaseBegin(mat->comm,1);
4863501a2bdSLois Curfman McInnes       fprintf(fd,"  [%d] local rows %d nz %d nz alloced %d mem %d \n",
487096963f5SLois Curfman McInnes           rank,mdn->m,nz,nzalloc,mem);
488096963f5SLois Curfman McInnes       fflush(fd);
48977c4ece6SBarry Smith     PetscSequentialPhaseEnd(mat->comm,1);
4903501a2bdSLois Curfman McInnes     ierr = VecScatterView(mdn->Mvctx,viewer); CHKERRQ(ierr);
4913501a2bdSLois Curfman McInnes     return 0;
4923501a2bdSLois Curfman McInnes   }
49390ace30eSBarry Smith   else if (format == ASCII_FORMAT_INFO) {
494096963f5SLois Curfman McInnes     return 0;
4958965ea79SLois Curfman McInnes   }
49619bcc07fSBarry Smith   if (vtype == ASCII_FILE_VIEWER) {
49777c4ece6SBarry Smith     PetscSequentialPhaseBegin(mat->comm,1);
49839ddd567SLois Curfman McInnes     fprintf(fd,"[%d] rows %d starts %d ends %d cols %d\n",
49939ddd567SLois Curfman McInnes              mdn->rank,mdn->m,mdn->rstart,mdn->rend,mdn->n);
50039ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
5018965ea79SLois Curfman McInnes     fflush(fd);
50277c4ece6SBarry Smith     PetscSequentialPhaseEnd(mat->comm,1);
5038965ea79SLois Curfman McInnes   }
5048965ea79SLois Curfman McInnes   else {
50539ddd567SLois Curfman McInnes     int size = mdn->size, rank = mdn->rank;
5068965ea79SLois Curfman McInnes     if (size == 1) {
50739ddd567SLois Curfman McInnes       ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
5088965ea79SLois Curfman McInnes     }
5098965ea79SLois Curfman McInnes     else {
5108965ea79SLois Curfman McInnes       /* assemble the entire matrix onto first processor. */
5118965ea79SLois Curfman McInnes       Mat          A;
51239ddd567SLois Curfman McInnes       int          M = mdn->M, N = mdn->N,m,row,i, nz, *cols;
51339ddd567SLois Curfman McInnes       Scalar       *vals;
51439ddd567SLois Curfman McInnes       Mat_SeqDense *Amdn = (Mat_SeqDense*) mdn->A->data;
5158965ea79SLois Curfman McInnes 
5168965ea79SLois Curfman McInnes       if (!rank) {
517b4fd4287SBarry Smith         ierr = MatCreateMPIDense(mat->comm,M,M,N,N,PETSC_NULL,&A); CHKERRQ(ierr);
5188965ea79SLois Curfman McInnes       }
5198965ea79SLois Curfman McInnes       else {
520b4fd4287SBarry Smith         ierr = MatCreateMPIDense(mat->comm,0,M,N,N,PETSC_NULL,&A); CHKERRQ(ierr);
5218965ea79SLois Curfman McInnes       }
5228965ea79SLois Curfman McInnes       PLogObjectParent(mat,A);
5238965ea79SLois Curfman McInnes 
52439ddd567SLois Curfman McInnes       /* Copy the matrix ... This isn't the most efficient means,
52539ddd567SLois Curfman McInnes          but it's quick for now */
52639ddd567SLois Curfman McInnes       row = mdn->rstart; m = Amdn->m;
5278965ea79SLois Curfman McInnes       for ( i=0; i<m; i++ ) {
52839ddd567SLois Curfman McInnes         ierr = MatGetRow(mat,row,&nz,&cols,&vals); CHKERRQ(ierr);
52939ddd567SLois Curfman McInnes         ierr = MatSetValues(A,1,&row,nz,cols,vals,INSERT_VALUES); CHKERRQ(ierr);
53039ddd567SLois Curfman McInnes         ierr = MatRestoreRow(mat,row,&nz,&cols,&vals); CHKERRQ(ierr);
53139ddd567SLois Curfman McInnes         row++;
5328965ea79SLois Curfman McInnes       }
5338965ea79SLois Curfman McInnes 
5346d4a8577SBarry Smith       ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
5356d4a8577SBarry Smith       ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
5368965ea79SLois Curfman McInnes       if (!rank) {
53739ddd567SLois Curfman McInnes         ierr = MatView(((Mat_MPIDense*)(A->data))->A,viewer); CHKERRQ(ierr);
5388965ea79SLois Curfman McInnes       }
5398965ea79SLois Curfman McInnes       ierr = MatDestroy(A); CHKERRQ(ierr);
5408965ea79SLois Curfman McInnes     }
5418965ea79SLois Curfman McInnes   }
5428965ea79SLois Curfman McInnes   return 0;
5438965ea79SLois Curfman McInnes }
5448965ea79SLois Curfman McInnes 
54539ddd567SLois Curfman McInnes static int MatView_MPIDense(PetscObject obj,Viewer viewer)
5468965ea79SLois Curfman McInnes {
5478965ea79SLois Curfman McInnes   Mat          mat = (Mat) obj;
54839ddd567SLois Curfman McInnes   int          ierr;
549bcd2baecSBarry Smith   ViewerType   vtype;
5508965ea79SLois Curfman McInnes 
551bcd2baecSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
552bcd2baecSBarry Smith   if (vtype == ASCII_FILE_VIEWER) {
55339ddd567SLois Curfman McInnes     ierr = MatView_MPIDense_ASCII(mat,viewer); CHKERRQ(ierr);
5548965ea79SLois Curfman McInnes   }
555bcd2baecSBarry Smith   else if (vtype == ASCII_FILES_VIEWER) {
55639ddd567SLois Curfman McInnes     ierr = MatView_MPIDense_ASCII(mat,viewer); CHKERRQ(ierr);
5578965ea79SLois Curfman McInnes   }
558bcd2baecSBarry Smith   else if (vtype == BINARY_FILE_VIEWER) {
55939ddd567SLois Curfman McInnes     return MatView_MPIDense_Binary(mat,viewer);
5608965ea79SLois Curfman McInnes   }
5618965ea79SLois Curfman McInnes   return 0;
5628965ea79SLois Curfman McInnes }
5638965ea79SLois Curfman McInnes 
564*7056b6fcSBarry Smith static int MatGetInfo_MPIDense(Mat A,MatInfoType flag,int *nz,int *nzalloc,int *mem)
5658965ea79SLois Curfman McInnes {
5663501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
5673501a2bdSLois Curfman McInnes   Mat          mdn = mat->A;
56839ddd567SLois Curfman McInnes   int          ierr, isend[3], irecv[3];
5698965ea79SLois Curfman McInnes 
5703501a2bdSLois Curfman McInnes   ierr = MatGetInfo(mdn,MAT_LOCAL,&isend[0],&isend[1],&isend[2]); CHKERRQ(ierr);
5718965ea79SLois Curfman McInnes   if (flag == MAT_LOCAL) {
572bcd2baecSBarry Smith     if (nz)      *nz      = isend[0];
573bcd2baecSBarry Smith     if (nzalloc) *nzalloc = isend[1];
574bcd2baecSBarry Smith     if (mem)     *mem     = isend[2];
5758965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_MAX) {
5763501a2bdSLois Curfman McInnes     MPI_Allreduce(isend,irecv,3,MPI_INT,MPI_MAX,A->comm);
577bcd2baecSBarry Smith     if (nz)      *nz      = irecv[0];
578bcd2baecSBarry Smith     if (nzalloc) *nzalloc = irecv[1];
579bcd2baecSBarry Smith     if (mem)     *mem     = irecv[2];
5808965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_SUM) {
5813501a2bdSLois Curfman McInnes     MPI_Allreduce(isend,irecv,3,MPI_INT,MPI_SUM,A->comm);
582bcd2baecSBarry Smith     if (nz)      *nz      = irecv[0];
583bcd2baecSBarry Smith     if (nzalloc) *nzalloc = irecv[1];
584bcd2baecSBarry Smith     if (mem)     *mem     = irecv[2];
5858965ea79SLois Curfman McInnes   }
5868965ea79SLois Curfman McInnes   return 0;
5878965ea79SLois Curfman McInnes }
5888965ea79SLois Curfman McInnes 
5898c469469SLois Curfman McInnes /* extern int MatLUFactorSymbolic_MPIDense(Mat,IS,IS,double,Mat*);
5908aaee692SLois Curfman McInnes    extern int MatLUFactorNumeric_MPIDense(Mat,Mat*);
5918aaee692SLois Curfman McInnes    extern int MatLUFactor_MPIDense(Mat,IS,IS,double);
5928aaee692SLois Curfman McInnes    extern int MatSolve_MPIDense(Mat,Vec,Vec);
5938c469469SLois Curfman McInnes    extern int MatSolveAdd_MPIDense(Mat,Vec,Vec,Vec);
5948aaee692SLois Curfman McInnes    extern int MatSolveTrans_MPIDense(Mat,Vec,Vec);
5958aaee692SLois Curfman McInnes    extern int MatSolveTransAdd_MPIDense(Mat,Vec,Vec,Vec); */
5968aaee692SLois Curfman McInnes 
59739ddd567SLois Curfman McInnes static int MatSetOption_MPIDense(Mat A,MatOption op)
5988965ea79SLois Curfman McInnes {
59939ddd567SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
6008965ea79SLois Curfman McInnes 
6016d4a8577SBarry Smith   if (op == MAT_NO_NEW_NONZERO_LOCATIONS ||
6026d4a8577SBarry Smith       op == MAT_YES_NEW_NONZERO_LOCATIONS ||
6036d4a8577SBarry Smith       op == MAT_COLUMNS_SORTED ||
6046d4a8577SBarry Smith       op == MAT_ROW_ORIENTED) {
6058965ea79SLois Curfman McInnes         MatSetOption(a->A,op);
6068965ea79SLois Curfman McInnes   }
6076d4a8577SBarry Smith   else if (op == MAT_ROWS_SORTED ||
6086d4a8577SBarry Smith            op == MAT_SYMMETRIC ||
6096d4a8577SBarry Smith            op == MAT_STRUCTURALLY_SYMMETRIC ||
6106d4a8577SBarry Smith            op == MAT_YES_NEW_DIAGONALS)
61194a424c1SBarry Smith     PLogInfo(A,"Info:MatSetOption_MPIDense:Option ignored\n");
6126d4a8577SBarry Smith   else if (op == MAT_COLUMN_ORIENTED)
61339b7565bSBarry Smith     { a->roworiented = 0; MatSetOption(a->A,op);}
6146d4a8577SBarry Smith   else if (op == MAT_NO_NEW_DIAGONALS)
6156d4a8577SBarry Smith     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_MPIDense:MAT_NO_NEW_DIAGONALS");}
6168965ea79SLois Curfman McInnes   else
61739ddd567SLois Curfman McInnes     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_MPIDense:unknown option");}
6188965ea79SLois Curfman McInnes   return 0;
6198965ea79SLois Curfman McInnes }
6208965ea79SLois Curfman McInnes 
6213501a2bdSLois Curfman McInnes static int MatGetSize_MPIDense(Mat A,int *m,int *n)
6228965ea79SLois Curfman McInnes {
6233501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6248965ea79SLois Curfman McInnes   *m = mat->M; *n = mat->N;
6258965ea79SLois Curfman McInnes   return 0;
6268965ea79SLois Curfman McInnes }
6278965ea79SLois Curfman McInnes 
6283501a2bdSLois Curfman McInnes static int MatGetLocalSize_MPIDense(Mat A,int *m,int *n)
6298965ea79SLois Curfman McInnes {
6303501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6318965ea79SLois Curfman McInnes   *m = mat->m; *n = mat->N;
6328965ea79SLois Curfman McInnes   return 0;
6338965ea79SLois Curfman McInnes }
6348965ea79SLois Curfman McInnes 
6353501a2bdSLois Curfman McInnes static int MatGetOwnershipRange_MPIDense(Mat A,int *m,int *n)
6368965ea79SLois Curfman McInnes {
6373501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6388965ea79SLois Curfman McInnes   *m = mat->rstart; *n = mat->rend;
6398965ea79SLois Curfman McInnes   return 0;
6408965ea79SLois Curfman McInnes }
6418965ea79SLois Curfman McInnes 
6423501a2bdSLois Curfman McInnes static int MatGetRow_MPIDense(Mat A,int row,int *nz,int **idx,Scalar **v)
6438965ea79SLois Curfman McInnes {
6443501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
64539ddd567SLois Curfman McInnes   int          lrow, rstart = mat->rstart, rend = mat->rend;
6468965ea79SLois Curfman McInnes 
64739ddd567SLois Curfman McInnes   if (row < rstart || row >= rend) SETERRQ(1,"MatGetRow_MPIDense:only local rows")
6488965ea79SLois Curfman McInnes   lrow = row - rstart;
64939ddd567SLois Curfman McInnes   return MatGetRow(mat->A,lrow,nz,idx,v);
6508965ea79SLois Curfman McInnes }
6518965ea79SLois Curfman McInnes 
65239ddd567SLois Curfman McInnes static int MatRestoreRow_MPIDense(Mat mat,int row,int *nz,int **idx,Scalar **v)
6538965ea79SLois Curfman McInnes {
6540452661fSBarry Smith   if (idx) PetscFree(*idx);
6550452661fSBarry Smith   if (v) PetscFree(*v);
6568965ea79SLois Curfman McInnes   return 0;
6578965ea79SLois Curfman McInnes }
6588965ea79SLois Curfman McInnes 
659cddf8d76SBarry Smith static int MatNorm_MPIDense(Mat A,NormType type,double *norm)
660096963f5SLois Curfman McInnes {
6613501a2bdSLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) A->data;
6623501a2bdSLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense*) mdn->A->data;
6633501a2bdSLois Curfman McInnes   int          ierr, i, j;
6643501a2bdSLois Curfman McInnes   double       sum = 0.0;
6653501a2bdSLois Curfman McInnes   Scalar       *v = mat->v;
6663501a2bdSLois Curfman McInnes 
6673501a2bdSLois Curfman McInnes   if (mdn->size == 1) {
6683501a2bdSLois Curfman McInnes     ierr =  MatNorm(mdn->A,type,norm); CHKERRQ(ierr);
6693501a2bdSLois Curfman McInnes   } else {
6703501a2bdSLois Curfman McInnes     if (type == NORM_FROBENIUS) {
6713501a2bdSLois Curfman McInnes       for (i=0; i<mat->n*mat->m; i++ ) {
6723501a2bdSLois Curfman McInnes #if defined(PETSC_COMPLEX)
6733501a2bdSLois Curfman McInnes         sum += real(conj(*v)*(*v)); v++;
6743501a2bdSLois Curfman McInnes #else
6753501a2bdSLois Curfman McInnes         sum += (*v)*(*v); v++;
6763501a2bdSLois Curfman McInnes #endif
6773501a2bdSLois Curfman McInnes       }
6786d84be18SBarry Smith       MPI_Allreduce(&sum,norm,1,MPI_DOUBLE,MPI_SUM,A->comm);
6793501a2bdSLois Curfman McInnes       *norm = sqrt(*norm);
6803501a2bdSLois Curfman McInnes       PLogFlops(2*mat->n*mat->m);
6813501a2bdSLois Curfman McInnes     }
6823501a2bdSLois Curfman McInnes     else if (type == NORM_1) {
6833501a2bdSLois Curfman McInnes       double *tmp, *tmp2;
6840452661fSBarry Smith       tmp  = (double *) PetscMalloc( 2*mdn->N*sizeof(double) ); CHKPTRQ(tmp);
6853501a2bdSLois Curfman McInnes       tmp2 = tmp + mdn->N;
686cddf8d76SBarry Smith       PetscMemzero(tmp,2*mdn->N*sizeof(double));
687096963f5SLois Curfman McInnes       *norm = 0.0;
6883501a2bdSLois Curfman McInnes       v = mat->v;
6893501a2bdSLois Curfman McInnes       for ( j=0; j<mat->n; j++ ) {
6903501a2bdSLois Curfman McInnes         for ( i=0; i<mat->m; i++ ) {
69167e560aaSBarry Smith           tmp[j] += PetscAbsScalar(*v);  v++;
6923501a2bdSLois Curfman McInnes         }
6933501a2bdSLois Curfman McInnes       }
6946d84be18SBarry Smith       MPI_Allreduce(tmp,tmp2,mdn->N,MPI_DOUBLE,MPI_SUM,A->comm);
6953501a2bdSLois Curfman McInnes       for ( j=0; j<mdn->N; j++ ) {
6963501a2bdSLois Curfman McInnes         if (tmp2[j] > *norm) *norm = tmp2[j];
6973501a2bdSLois Curfman McInnes       }
6980452661fSBarry Smith       PetscFree(tmp);
6993501a2bdSLois Curfman McInnes       PLogFlops(mat->n*mat->m);
7003501a2bdSLois Curfman McInnes     }
7013501a2bdSLois Curfman McInnes     else if (type == NORM_INFINITY) { /* max row norm */
7023501a2bdSLois Curfman McInnes       double ntemp;
7033501a2bdSLois Curfman McInnes       ierr = MatNorm(mdn->A,type,&ntemp); CHKERRQ(ierr);
7046d84be18SBarry Smith       MPI_Allreduce(&ntemp,norm,1,MPI_DOUBLE,MPI_MAX,A->comm);
7053501a2bdSLois Curfman McInnes     }
7063501a2bdSLois Curfman McInnes     else {
7073501a2bdSLois Curfman McInnes       SETERRQ(1,"MatNorm_MPIDense:No support for two norm");
7083501a2bdSLois Curfman McInnes     }
7093501a2bdSLois Curfman McInnes   }
7103501a2bdSLois Curfman McInnes   return 0;
7113501a2bdSLois Curfman McInnes }
7123501a2bdSLois Curfman McInnes 
7133501a2bdSLois Curfman McInnes static int MatTranspose_MPIDense(Mat A,Mat *matout)
7143501a2bdSLois Curfman McInnes {
7153501a2bdSLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
7163501a2bdSLois Curfman McInnes   Mat_SeqDense *Aloc = (Mat_SeqDense *) a->A->data;
7173501a2bdSLois Curfman McInnes   Mat          B;
7183501a2bdSLois Curfman McInnes   int          M = a->M, N = a->N, m, n, *rwork, rstart = a->rstart;
7193501a2bdSLois Curfman McInnes   int          j, i, ierr;
7203501a2bdSLois Curfman McInnes   Scalar       *v;
7213501a2bdSLois Curfman McInnes 
722*7056b6fcSBarry Smith   if (matout == PETSC_NULL && M != N) {
7233501a2bdSLois Curfman McInnes     SETERRQ(1,"MatTranspose_MPIDense:Supports square matrix only in-place");
724*7056b6fcSBarry Smith   }
725*7056b6fcSBarry Smith   ierr = MatCreateMPIDense(A->comm,PETSC_DECIDE,PETSC_DECIDE,N,M,PETSC_NULL,&B);CHKERRQ(ierr);
7263501a2bdSLois Curfman McInnes 
7273501a2bdSLois Curfman McInnes   m = Aloc->m; n = Aloc->n; v = Aloc->v;
7280452661fSBarry Smith   rwork = (int *) PetscMalloc(n*sizeof(int)); CHKPTRQ(rwork);
7293501a2bdSLois Curfman McInnes   for ( j=0; j<n; j++ ) {
7303501a2bdSLois Curfman McInnes     for (i=0; i<m; i++) rwork[i] = rstart + i;
7313501a2bdSLois Curfman McInnes     ierr = MatSetValues(B,1,&j,m,rwork,v,INSERT_VALUES); CHKERRQ(ierr);
7323501a2bdSLois Curfman McInnes     v   += m;
7333501a2bdSLois Curfman McInnes   }
7340452661fSBarry Smith   PetscFree(rwork);
7356d4a8577SBarry Smith   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
7366d4a8577SBarry Smith   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
7373638b69dSLois Curfman McInnes   if (matout != PETSC_NULL) {
7383501a2bdSLois Curfman McInnes     *matout = B;
7393501a2bdSLois Curfman McInnes   } else {
7403501a2bdSLois Curfman McInnes     /* This isn't really an in-place transpose, but free data struct from a */
7410452661fSBarry Smith     PetscFree(a->rowners);
7423501a2bdSLois Curfman McInnes     ierr = MatDestroy(a->A); CHKERRQ(ierr);
7433501a2bdSLois Curfman McInnes     if (a->lvec) VecDestroy(a->lvec);
7443501a2bdSLois Curfman McInnes     if (a->Mvctx) VecScatterDestroy(a->Mvctx);
7450452661fSBarry Smith     PetscFree(a);
7463501a2bdSLois Curfman McInnes     PetscMemcpy(A,B,sizeof(struct _Mat));
7470452661fSBarry Smith     PetscHeaderDestroy(B);
7483501a2bdSLois Curfman McInnes   }
749096963f5SLois Curfman McInnes   return 0;
750096963f5SLois Curfman McInnes }
751096963f5SLois Curfman McInnes 
75244cd7ae7SLois Curfman McInnes #include "pinclude/plapack.h"
75344cd7ae7SLois Curfman McInnes static int MatScale_MPIDense(Scalar *alpha,Mat inA)
75444cd7ae7SLois Curfman McInnes {
75544cd7ae7SLois Curfman McInnes   Mat_MPIDense *A = (Mat_MPIDense *) inA->data;
75644cd7ae7SLois Curfman McInnes   Mat_SeqDense *a = (Mat_SeqDense *) A->A->data;
75744cd7ae7SLois Curfman McInnes   int          one = 1, nz;
75844cd7ae7SLois Curfman McInnes 
75944cd7ae7SLois Curfman McInnes   nz = a->m*a->n;
76044cd7ae7SLois Curfman McInnes   BLscal_( &nz, alpha, a->v, &one );
76144cd7ae7SLois Curfman McInnes   PLogFlops(nz);
76244cd7ae7SLois Curfman McInnes   return 0;
76344cd7ae7SLois Curfman McInnes }
76444cd7ae7SLois Curfman McInnes 
7653d1612f7SBarry Smith static int MatConvertSameType_MPIDense(Mat,Mat *,int);
7668965ea79SLois Curfman McInnes 
7678965ea79SLois Curfman McInnes /* -------------------------------------------------------------------*/
76839ddd567SLois Curfman McInnes static struct _MatOps MatOps = {MatSetValues_MPIDense,
76939ddd567SLois Curfman McInnes        MatGetRow_MPIDense,MatRestoreRow_MPIDense,
77039ddd567SLois Curfman McInnes        MatMult_MPIDense,MatMultAdd_MPIDense,
771096963f5SLois Curfman McInnes        MatMultTrans_MPIDense,MatMultTransAdd_MPIDense,
772e7ca0642SLois Curfman McInnes /*       MatSolve_MPIDense,0, */
773e7ca0642SLois Curfman McInnes        0,0,
77439ddd567SLois Curfman McInnes        0,0,
7758c469469SLois Curfman McInnes        0,0,
7768c469469SLois Curfman McInnes /*       MatLUFactor_MPIDense,0, */
7778aaee692SLois Curfman McInnes        0,MatTranspose_MPIDense,
77839ddd567SLois Curfman McInnes        MatGetInfo_MPIDense,0,
779096963f5SLois Curfman McInnes        MatGetDiagonal_MPIDense,0,MatNorm_MPIDense,
78039ddd567SLois Curfman McInnes        MatAssemblyBegin_MPIDense,MatAssemblyEnd_MPIDense,
7818965ea79SLois Curfman McInnes        0,
78239ddd567SLois Curfman McInnes        MatSetOption_MPIDense,MatZeroEntries_MPIDense,MatZeroRows_MPIDense,
7838c469469SLois Curfman McInnes        0,0,0,
7848c469469SLois Curfman McInnes /*       0,MatLUFactorSymbolic_MPIDense,MatLUFactorNumeric_MPIDense, */
7858aaee692SLois Curfman McInnes        0,0,
78639ddd567SLois Curfman McInnes        MatGetSize_MPIDense,MatGetLocalSize_MPIDense,
78739ddd567SLois Curfman McInnes        MatGetOwnershipRange_MPIDense,
788ff14e315SSatish Balay        0,0, MatGetArray_MPIDense, MatRestoreArray_MPIDense,
789905e6a2fSBarry Smith        0,MatConvertSameType_MPIDense,
790b49de8d1SLois Curfman McInnes        0,0,0,0,0,
79144cd7ae7SLois Curfman McInnes        0,0,MatGetValues_MPIDense,0,0,MatScale_MPIDense};
7928965ea79SLois Curfman McInnes 
7938965ea79SLois Curfman McInnes /*@C
79439ddd567SLois Curfman McInnes    MatCreateMPIDense - Creates a sparse parallel matrix in dense format.
7958965ea79SLois Curfman McInnes 
7968965ea79SLois Curfman McInnes    Input Parameters:
7978965ea79SLois Curfman McInnes .  comm - MPI communicator
7988965ea79SLois Curfman McInnes .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
7998965ea79SLois Curfman McInnes .  n - number of local columns (or PETSC_DECIDE to have calculated
8008965ea79SLois Curfman McInnes            if N is given)
8018965ea79SLois Curfman McInnes .  M - number of global rows (or PETSC_DECIDE to have calculated if m is given)
8028965ea79SLois Curfman McInnes .  N - number of global columns (or PETSC_DECIDE to have calculated
8038965ea79SLois Curfman McInnes            if n is given)
804b4fd4287SBarry Smith .  data - optional location of matrix data.  Set data=PETSC_NULL for PETSc
805dfc5480cSLois Curfman McInnes    to control all matrix memory allocation.
8068965ea79SLois Curfman McInnes 
8078965ea79SLois Curfman McInnes    Output Parameter:
808477f1c0bSLois Curfman McInnes .  A - the matrix
8098965ea79SLois Curfman McInnes 
8108965ea79SLois Curfman McInnes    Notes:
81139ddd567SLois Curfman McInnes    The dense format is fully compatible with standard Fortran 77
81239ddd567SLois Curfman McInnes    storage by columns.
8138965ea79SLois Curfman McInnes 
81418f449edSLois Curfman McInnes    The data input variable is intended primarily for Fortran programmers
81518f449edSLois Curfman McInnes    who wish to allocate their own matrix memory space.  Most users should
816b4fd4287SBarry Smith    set data=PETSC_NULL.
81718f449edSLois Curfman McInnes 
8188965ea79SLois Curfman McInnes    The user MUST specify either the local or global matrix dimensions
8198965ea79SLois Curfman McInnes    (possibly both).
8208965ea79SLois Curfman McInnes 
8213501a2bdSLois Curfman McInnes    Currently, the only parallel dense matrix decomposition is by rows,
8223501a2bdSLois Curfman McInnes    so that n=N and each submatrix owns all of the global columns.
8233501a2bdSLois Curfman McInnes 
82439ddd567SLois Curfman McInnes .keywords: matrix, dense, parallel
8258965ea79SLois Curfman McInnes 
82639ddd567SLois Curfman McInnes .seealso: MatCreate(), MatCreateSeqDense(), MatSetValues()
8278965ea79SLois Curfman McInnes @*/
828477f1c0bSLois Curfman McInnes int MatCreateMPIDense(MPI_Comm comm,int m,int n,int M,int N,Scalar *data,Mat *A)
8298965ea79SLois Curfman McInnes {
8308965ea79SLois Curfman McInnes   Mat          mat;
83139ddd567SLois Curfman McInnes   Mat_MPIDense *a;
83225cdf11fSBarry Smith   int          ierr, i,flg;
8338965ea79SLois Curfman McInnes 
834ed2daf61SLois Curfman McInnes   /* Note:  For now, when data is specified above, this assumes the user correctly
835ed2daf61SLois Curfman McInnes    allocates the local dense storage space.  We should add error checking. */
83618f449edSLois Curfman McInnes 
837477f1c0bSLois Curfman McInnes   *A = 0;
8380452661fSBarry Smith   PetscHeaderCreate(mat,_Mat,MAT_COOKIE,MATMPIDENSE,comm);
8398965ea79SLois Curfman McInnes   PLogObjectCreate(mat);
8400452661fSBarry Smith   mat->data       = (void *) (a = PetscNew(Mat_MPIDense)); CHKPTRQ(a);
8418965ea79SLois Curfman McInnes   PetscMemcpy(&mat->ops,&MatOps,sizeof(struct _MatOps));
84239ddd567SLois Curfman McInnes   mat->destroy    = MatDestroy_MPIDense;
84339ddd567SLois Curfman McInnes   mat->view       = MatView_MPIDense;
8448965ea79SLois Curfman McInnes   mat->factor     = 0;
8458965ea79SLois Curfman McInnes 
846622d7880SLois Curfman McInnes   a->factor     = 0;
8478965ea79SLois Curfman McInnes   a->insertmode = NOT_SET_VALUES;
8488965ea79SLois Curfman McInnes   MPI_Comm_rank(comm,&a->rank);
8498965ea79SLois Curfman McInnes   MPI_Comm_size(comm,&a->size);
8508965ea79SLois Curfman McInnes 
85139ddd567SLois Curfman McInnes   if (M == PETSC_DECIDE) MPI_Allreduce(&m,&M,1,MPI_INT,MPI_SUM,comm);
8528965ea79SLois Curfman McInnes   if (m == PETSC_DECIDE) {m = M/a->size + ((M % a->size) > a->rank);}
85339ddd567SLois Curfman McInnes 
85439ddd567SLois Curfman McInnes   /* each row stores all columns */
85539ddd567SLois Curfman McInnes   if (N == PETSC_DECIDE) N = n;
856d7e8b826SBarry Smith   if (n == PETSC_DECIDE) {n = N/a->size + ((N % a->size) > a->rank);}
857d7e8b826SBarry Smith   /*  if (n != N) SETERRQ(1,"MatCreateMPIDense:For now, only n=N is supported"); */
858aca0ad90SLois Curfman McInnes   a->N = mat->N = N;
859aca0ad90SLois Curfman McInnes   a->M = mat->M = M;
860aca0ad90SLois Curfman McInnes   a->m = mat->m = m;
861aca0ad90SLois Curfman McInnes   a->n = mat->n = n;
8628965ea79SLois Curfman McInnes 
8638965ea79SLois Curfman McInnes   /* build local table of row and column ownerships */
864d7e8b826SBarry Smith   a->rowners = (int *) PetscMalloc(2*(a->size+2)*sizeof(int)); CHKPTRQ(a->rowners);
865d7e8b826SBarry Smith   a->cowners = a->rowners + a->size + 1;
866*7056b6fcSBarry Smith   PLogObjectMemory(mat,2*(a->size+2)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_MPIDense));
8678965ea79SLois Curfman McInnes   MPI_Allgather(&m,1,MPI_INT,a->rowners+1,1,MPI_INT,comm);
8688965ea79SLois Curfman McInnes   a->rowners[0] = 0;
8698965ea79SLois Curfman McInnes   for ( i=2; i<=a->size; i++ ) {
8708965ea79SLois Curfman McInnes     a->rowners[i] += a->rowners[i-1];
8718965ea79SLois Curfman McInnes   }
8728965ea79SLois Curfman McInnes   a->rstart = a->rowners[a->rank];
8738965ea79SLois Curfman McInnes   a->rend   = a->rowners[a->rank+1];
874d7e8b826SBarry Smith   MPI_Allgather(&n,1,MPI_INT,a->cowners+1,1,MPI_INT,comm);
875d7e8b826SBarry Smith   a->cowners[0] = 0;
876d7e8b826SBarry Smith   for ( i=2; i<=a->size; i++ ) {
877d7e8b826SBarry Smith     a->cowners[i] += a->cowners[i-1];
878d7e8b826SBarry Smith   }
8798965ea79SLois Curfman McInnes 
88018f449edSLois Curfman McInnes   ierr = MatCreateSeqDense(MPI_COMM_SELF,m,N,data,&a->A); CHKERRQ(ierr);
8818965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->A);
8828965ea79SLois Curfman McInnes 
8838965ea79SLois Curfman McInnes   /* build cache for off array entries formed */
8848965ea79SLois Curfman McInnes   ierr = StashBuild_Private(&a->stash); CHKERRQ(ierr);
8858965ea79SLois Curfman McInnes 
8868965ea79SLois Curfman McInnes   /* stuff used for matrix vector multiply */
8878965ea79SLois Curfman McInnes   a->lvec        = 0;
8888965ea79SLois Curfman McInnes   a->Mvctx       = 0;
88939b7565bSBarry Smith   a->roworiented = 1;
8908965ea79SLois Curfman McInnes 
891477f1c0bSLois Curfman McInnes   *A = mat;
89225cdf11fSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-help",&flg); CHKERRQ(ierr);
89325cdf11fSBarry Smith   if (flg) {
8948c469469SLois Curfman McInnes     ierr = MatPrintHelp(mat); CHKERRQ(ierr);
8958c469469SLois Curfman McInnes   }
8968965ea79SLois Curfman McInnes   return 0;
8978965ea79SLois Curfman McInnes }
8988965ea79SLois Curfman McInnes 
8993d1612f7SBarry Smith static int MatConvertSameType_MPIDense(Mat A,Mat *newmat,int cpvalues)
9008965ea79SLois Curfman McInnes {
9018965ea79SLois Curfman McInnes   Mat          mat;
9023501a2bdSLois Curfman McInnes   Mat_MPIDense *a,*oldmat = (Mat_MPIDense *) A->data;
90339ddd567SLois Curfman McInnes   int          ierr;
9042ba99913SLois Curfman McInnes   FactorCtx    *factor;
9058965ea79SLois Curfman McInnes 
9068965ea79SLois Curfman McInnes   *newmat       = 0;
9070452661fSBarry Smith   PetscHeaderCreate(mat,_Mat,MAT_COOKIE,MATMPIDENSE,A->comm);
9088965ea79SLois Curfman McInnes   PLogObjectCreate(mat);
9090452661fSBarry Smith   mat->data      = (void *) (a = PetscNew(Mat_MPIDense)); CHKPTRQ(a);
9108965ea79SLois Curfman McInnes   PetscMemcpy(&mat->ops,&MatOps,sizeof(struct _MatOps));
91139ddd567SLois Curfman McInnes   mat->destroy   = MatDestroy_MPIDense;
91239ddd567SLois Curfman McInnes   mat->view      = MatView_MPIDense;
9133501a2bdSLois Curfman McInnes   mat->factor    = A->factor;
914c456f294SBarry Smith   mat->assembled = PETSC_TRUE;
9158965ea79SLois Curfman McInnes 
91644cd7ae7SLois Curfman McInnes   a->m = mat->m = oldmat->m;
91744cd7ae7SLois Curfman McInnes   a->n = mat->n = oldmat->n;
91844cd7ae7SLois Curfman McInnes   a->M = mat->M = oldmat->M;
91944cd7ae7SLois Curfman McInnes   a->N = mat->N = oldmat->N;
9202ba99913SLois Curfman McInnes   if (oldmat->factor) {
9212ba99913SLois Curfman McInnes     a->factor = (FactorCtx *) (factor = PetscNew(FactorCtx)); CHKPTRQ(factor);
9222ba99913SLois Curfman McInnes     /* copy factor contents ... add this code! */
9232ba99913SLois Curfman McInnes   } else a->factor = 0;
9248965ea79SLois Curfman McInnes 
9258965ea79SLois Curfman McInnes   a->rstart     = oldmat->rstart;
9268965ea79SLois Curfman McInnes   a->rend       = oldmat->rend;
9278965ea79SLois Curfman McInnes   a->size       = oldmat->size;
9288965ea79SLois Curfman McInnes   a->rank       = oldmat->rank;
9298965ea79SLois Curfman McInnes   a->insertmode = NOT_SET_VALUES;
9308965ea79SLois Curfman McInnes 
9310452661fSBarry Smith   a->rowners = (int *) PetscMalloc((a->size+1)*sizeof(int)); CHKPTRQ(a->rowners);
93239ddd567SLois Curfman McInnes   PLogObjectMemory(mat,(a->size+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_MPIDense));
9338965ea79SLois Curfman McInnes   PetscMemcpy(a->rowners,oldmat->rowners,(a->size+1)*sizeof(int));
9348965ea79SLois Curfman McInnes   ierr = StashInitialize_Private(&a->stash); CHKERRQ(ierr);
9358965ea79SLois Curfman McInnes 
9368965ea79SLois Curfman McInnes   ierr =  VecDuplicate(oldmat->lvec,&a->lvec); CHKERRQ(ierr);
9378965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->lvec);
93855659b69SBarry Smith   ierr =  VecScatterCopy(oldmat->Mvctx,&a->Mvctx); CHKERRQ(ierr);
9398965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->Mvctx);
9408965ea79SLois Curfman McInnes   ierr =  MatConvert(oldmat->A,MATSAME,&a->A); CHKERRQ(ierr);
9418965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->A);
9428965ea79SLois Curfman McInnes   *newmat = mat;
9438965ea79SLois Curfman McInnes   return 0;
9448965ea79SLois Curfman McInnes }
9458965ea79SLois Curfman McInnes 
94677c4ece6SBarry Smith #include "sys.h"
9478965ea79SLois Curfman McInnes 
94890ace30eSBarry Smith int MatLoad_MPIDense_DenseInFile(MPI_Comm comm,int fd,int M, int N, Mat *newmat)
94990ace30eSBarry Smith {
95090ace30eSBarry Smith   int        *rowners, i,size,rank,m,rstart,rend,ierr,nz,j;
95190ace30eSBarry Smith   Scalar     *array,*vals,*vals_ptr;
95290ace30eSBarry Smith   MPI_Status status;
95390ace30eSBarry Smith 
95490ace30eSBarry Smith   MPI_Comm_rank(comm,&rank);
95590ace30eSBarry Smith   MPI_Comm_size(comm,&size);
95690ace30eSBarry Smith 
95790ace30eSBarry Smith   /* determine ownership of all rows */
95890ace30eSBarry Smith   m = M/size + ((M % size) > rank);
95990ace30eSBarry Smith   rowners = (int *) PetscMalloc((size+2)*sizeof(int)); CHKPTRQ(rowners);
96090ace30eSBarry Smith   MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);
96190ace30eSBarry Smith   rowners[0] = 0;
96290ace30eSBarry Smith   for ( i=2; i<=size; i++ ) {
96390ace30eSBarry Smith     rowners[i] += rowners[i-1];
96490ace30eSBarry Smith   }
96590ace30eSBarry Smith   rstart = rowners[rank];
96690ace30eSBarry Smith   rend   = rowners[rank+1];
96790ace30eSBarry Smith 
96890ace30eSBarry Smith   ierr = MatCreateMPIDense(comm,m,PETSC_DECIDE,M,N,PETSC_NULL,newmat);CHKERRQ(ierr);
96990ace30eSBarry Smith   ierr = MatGetArray(*newmat,&array); CHKERRQ(ierr);
97090ace30eSBarry Smith 
97190ace30eSBarry Smith   if (!rank) {
97290ace30eSBarry Smith     vals = (Scalar *) PetscMalloc( m*N*sizeof(Scalar) ); CHKPTRQ(vals);
97390ace30eSBarry Smith 
97490ace30eSBarry Smith     /* read in my part of the matrix numerical values  */
97577c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,vals,m*N,BINARY_SCALAR); CHKERRQ(ierr);
97690ace30eSBarry Smith 
97790ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
97890ace30eSBarry Smith     vals_ptr = vals;
97990ace30eSBarry Smith     for ( i=0; i<m; i++ ) {
98090ace30eSBarry Smith       for ( j=0; j<N; j++ ) {
98190ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
98290ace30eSBarry Smith       }
98390ace30eSBarry Smith     }
98490ace30eSBarry Smith 
98590ace30eSBarry Smith     /* read in other processors and ship out */
98690ace30eSBarry Smith     for ( i=1; i<size; i++ ) {
98790ace30eSBarry Smith       nz   = (rowners[i+1] - rowners[i])*N;
98877c4ece6SBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,BINARY_SCALAR); CHKERRQ(ierr);
98990ace30eSBarry Smith       MPI_Send(vals,nz,MPIU_SCALAR,i,(*newmat)->tag,comm);
99090ace30eSBarry Smith     }
99190ace30eSBarry Smith   }
99290ace30eSBarry Smith   else {
99390ace30eSBarry Smith     /* receive numeric values */
99490ace30eSBarry Smith     vals = (Scalar*) PetscMalloc( m*N*sizeof(Scalar) ); CHKPTRQ(vals);
99590ace30eSBarry Smith 
99690ace30eSBarry Smith     /* receive message of values*/
99790ace30eSBarry Smith     MPI_Recv(vals,m*N,MPIU_SCALAR,0,(*newmat)->tag,comm,&status);
99890ace30eSBarry Smith 
99990ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
100090ace30eSBarry Smith     vals_ptr = vals;
100190ace30eSBarry Smith     for ( i=0; i<m; i++ ) {
100290ace30eSBarry Smith       for ( j=0; j<N; j++ ) {
100390ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
100490ace30eSBarry Smith       }
100590ace30eSBarry Smith     }
100690ace30eSBarry Smith   }
100790ace30eSBarry Smith   PetscFree(rowners);
100890ace30eSBarry Smith   PetscFree(vals);
10096d4a8577SBarry Smith   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
10106d4a8577SBarry Smith   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
101190ace30eSBarry Smith   return 0;
101290ace30eSBarry Smith }
101390ace30eSBarry Smith 
101490ace30eSBarry Smith 
101519bcc07fSBarry Smith int MatLoad_MPIDense(Viewer viewer,MatType type,Mat *newmat)
10168965ea79SLois Curfman McInnes {
10178965ea79SLois Curfman McInnes   Mat          A;
10188965ea79SLois Curfman McInnes   int          i, nz, ierr, j,rstart, rend, fd;
10198965ea79SLois Curfman McInnes   Scalar       *vals,*svals;
102019bcc07fSBarry Smith   MPI_Comm     comm = ((PetscObject)viewer)->comm;
10218965ea79SLois Curfman McInnes   MPI_Status   status;
10228965ea79SLois Curfman McInnes   int          header[4],rank,size,*rowlengths = 0,M,N,m,*rowners,maxnz,*cols;
10238965ea79SLois Curfman McInnes   int          *ourlens,*sndcounts = 0,*procsnz = 0, *offlens,jj,*mycols,*smycols;
102419bcc07fSBarry Smith   int          tag = ((PetscObject)viewer)->tag;
10258965ea79SLois Curfman McInnes 
10268965ea79SLois Curfman McInnes   MPI_Comm_size(comm,&size); MPI_Comm_rank(comm,&rank);
10278965ea79SLois Curfman McInnes   if (!rank) {
102890ace30eSBarry Smith     ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
102977c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,(char *)header,4,BINARY_INT); CHKERRQ(ierr);
103039ddd567SLois Curfman McInnes     if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_MPIDenseorMPIRow:not matrix object");
10318965ea79SLois Curfman McInnes   }
10328965ea79SLois Curfman McInnes 
10338965ea79SLois Curfman McInnes   MPI_Bcast(header+1,3,MPI_INT,0,comm);
103490ace30eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
103590ace30eSBarry Smith 
103690ace30eSBarry Smith   /*
103790ace30eSBarry Smith        Handle case where matrix is stored on disk as a dense matrix
103890ace30eSBarry Smith   */
103990ace30eSBarry Smith   if (nz == MATRIX_BINARY_FORMAT_DENSE) {
104090ace30eSBarry Smith     return MatLoad_MPIDense_DenseInFile(comm,fd,M,N,newmat);
104190ace30eSBarry Smith   }
104290ace30eSBarry Smith 
10438965ea79SLois Curfman McInnes   /* determine ownership of all rows */
10448965ea79SLois Curfman McInnes   m = M/size + ((M % size) > rank);
10450452661fSBarry Smith   rowners = (int *) PetscMalloc((size+2)*sizeof(int)); CHKPTRQ(rowners);
10468965ea79SLois Curfman McInnes   MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);
10478965ea79SLois Curfman McInnes   rowners[0] = 0;
10488965ea79SLois Curfman McInnes   for ( i=2; i<=size; i++ ) {
10498965ea79SLois Curfman McInnes     rowners[i] += rowners[i-1];
10508965ea79SLois Curfman McInnes   }
10518965ea79SLois Curfman McInnes   rstart = rowners[rank];
10528965ea79SLois Curfman McInnes   rend   = rowners[rank+1];
10538965ea79SLois Curfman McInnes 
10548965ea79SLois Curfman McInnes   /* distribute row lengths to all processors */
10550452661fSBarry Smith   ourlens = (int*) PetscMalloc( 2*(rend-rstart)*sizeof(int) ); CHKPTRQ(ourlens);
10568965ea79SLois Curfman McInnes   offlens = ourlens + (rend-rstart);
10578965ea79SLois Curfman McInnes   if (!rank) {
10580452661fSBarry Smith     rowlengths = (int*) PetscMalloc( M*sizeof(int) ); CHKPTRQ(rowlengths);
105977c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,rowlengths,M,BINARY_INT); CHKERRQ(ierr);
10600452661fSBarry Smith     sndcounts = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(sndcounts);
10618965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) sndcounts[i] = rowners[i+1] - rowners[i];
10628965ea79SLois Curfman McInnes     MPI_Scatterv(rowlengths,sndcounts,rowners,MPI_INT,ourlens,rend-rstart,MPI_INT,0,comm);
10630452661fSBarry Smith     PetscFree(sndcounts);
10648965ea79SLois Curfman McInnes   }
10658965ea79SLois Curfman McInnes   else {
10668965ea79SLois Curfman McInnes     MPI_Scatterv(0,0,0,MPI_INT,ourlens,rend-rstart,MPI_INT, 0,comm);
10678965ea79SLois Curfman McInnes   }
10688965ea79SLois Curfman McInnes 
10698965ea79SLois Curfman McInnes   if (!rank) {
10708965ea79SLois Curfman McInnes     /* calculate the number of nonzeros on each processor */
10710452661fSBarry Smith     procsnz = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(procsnz);
1072cddf8d76SBarry Smith     PetscMemzero(procsnz,size*sizeof(int));
10738965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) {
10748965ea79SLois Curfman McInnes       for ( j=rowners[i]; j< rowners[i+1]; j++ ) {
10758965ea79SLois Curfman McInnes         procsnz[i] += rowlengths[j];
10768965ea79SLois Curfman McInnes       }
10778965ea79SLois Curfman McInnes     }
10780452661fSBarry Smith     PetscFree(rowlengths);
10798965ea79SLois Curfman McInnes 
10808965ea79SLois Curfman McInnes     /* determine max buffer needed and allocate it */
10818965ea79SLois Curfman McInnes     maxnz = 0;
10828965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) {
10830452661fSBarry Smith       maxnz = PetscMax(maxnz,procsnz[i]);
10848965ea79SLois Curfman McInnes     }
10850452661fSBarry Smith     cols = (int *) PetscMalloc( maxnz*sizeof(int) ); CHKPTRQ(cols);
10868965ea79SLois Curfman McInnes 
10878965ea79SLois Curfman McInnes     /* read in my part of the matrix column indices  */
10888965ea79SLois Curfman McInnes     nz = procsnz[0];
10890452661fSBarry Smith     mycols = (int *) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(mycols);
109077c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,mycols,nz,BINARY_INT); CHKERRQ(ierr);
10918965ea79SLois Curfman McInnes 
10928965ea79SLois Curfman McInnes     /* read in every one elses and ship off */
10938965ea79SLois Curfman McInnes     for ( i=1; i<size; i++ ) {
10948965ea79SLois Curfman McInnes       nz = procsnz[i];
109577c4ece6SBarry Smith       ierr = PetscBinaryRead(fd,cols,nz,BINARY_INT); CHKERRQ(ierr);
10968965ea79SLois Curfman McInnes       MPI_Send(cols,nz,MPI_INT,i,tag,comm);
10978965ea79SLois Curfman McInnes     }
10980452661fSBarry Smith     PetscFree(cols);
10998965ea79SLois Curfman McInnes   }
11008965ea79SLois Curfman McInnes   else {
11018965ea79SLois Curfman McInnes     /* determine buffer space needed for message */
11028965ea79SLois Curfman McInnes     nz = 0;
11038965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
11048965ea79SLois Curfman McInnes       nz += ourlens[i];
11058965ea79SLois Curfman McInnes     }
11060452661fSBarry Smith     mycols = (int*) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(mycols);
11078965ea79SLois Curfman McInnes 
11088965ea79SLois Curfman McInnes     /* receive message of column indices*/
11098965ea79SLois Curfman McInnes     MPI_Recv(mycols,nz,MPI_INT,0,tag,comm,&status);
11108965ea79SLois Curfman McInnes     MPI_Get_count(&status,MPI_INT,&maxnz);
111139ddd567SLois Curfman McInnes     if (maxnz != nz) SETERRQ(1,"MatLoad_MPIDenseorMPIRow:something is wrong with file");
11128965ea79SLois Curfman McInnes   }
11138965ea79SLois Curfman McInnes 
11148965ea79SLois Curfman McInnes   /* loop over local rows, determining number of off diagonal entries */
1115cddf8d76SBarry Smith   PetscMemzero(offlens,m*sizeof(int));
11168965ea79SLois Curfman McInnes   jj = 0;
11178965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
11188965ea79SLois Curfman McInnes     for ( j=0; j<ourlens[i]; j++ ) {
11198965ea79SLois Curfman McInnes       if (mycols[jj] < rstart || mycols[jj] >= rend) offlens[i]++;
11208965ea79SLois Curfman McInnes       jj++;
11218965ea79SLois Curfman McInnes     }
11228965ea79SLois Curfman McInnes   }
11238965ea79SLois Curfman McInnes 
11248965ea79SLois Curfman McInnes   /* create our matrix */
11258965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
11268965ea79SLois Curfman McInnes     ourlens[i] -= offlens[i];
11278965ea79SLois Curfman McInnes   }
1128b4fd4287SBarry Smith   ierr = MatCreateMPIDense(comm,m,PETSC_DECIDE,M,N,PETSC_NULL,newmat);CHKERRQ(ierr);
11298965ea79SLois Curfman McInnes   A = *newmat;
11308965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
11318965ea79SLois Curfman McInnes     ourlens[i] += offlens[i];
11328965ea79SLois Curfman McInnes   }
11338965ea79SLois Curfman McInnes 
11348965ea79SLois Curfman McInnes   if (!rank) {
11350452661fSBarry Smith     vals = (Scalar *) PetscMalloc( maxnz*sizeof(Scalar) ); CHKPTRQ(vals);
11368965ea79SLois Curfman McInnes 
11378965ea79SLois Curfman McInnes     /* read in my part of the matrix numerical values  */
11388965ea79SLois Curfman McInnes     nz = procsnz[0];
113977c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,vals,nz,BINARY_SCALAR); CHKERRQ(ierr);
11408965ea79SLois Curfman McInnes 
11418965ea79SLois Curfman McInnes     /* insert into matrix */
11428965ea79SLois Curfman McInnes     jj      = rstart;
11438965ea79SLois Curfman McInnes     smycols = mycols;
11448965ea79SLois Curfman McInnes     svals   = vals;
11458965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
11468965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
11478965ea79SLois Curfman McInnes       smycols += ourlens[i];
11488965ea79SLois Curfman McInnes       svals   += ourlens[i];
11498965ea79SLois Curfman McInnes       jj++;
11508965ea79SLois Curfman McInnes     }
11518965ea79SLois Curfman McInnes 
11528965ea79SLois Curfman McInnes     /* read in other processors and ship out */
11538965ea79SLois Curfman McInnes     for ( i=1; i<size; i++ ) {
11548965ea79SLois Curfman McInnes       nz = procsnz[i];
115577c4ece6SBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,BINARY_SCALAR); CHKERRQ(ierr);
11568965ea79SLois Curfman McInnes       MPI_Send(vals,nz,MPIU_SCALAR,i,A->tag,comm);
11578965ea79SLois Curfman McInnes     }
11580452661fSBarry Smith     PetscFree(procsnz);
11598965ea79SLois Curfman McInnes   }
11608965ea79SLois Curfman McInnes   else {
11618965ea79SLois Curfman McInnes     /* receive numeric values */
11620452661fSBarry Smith     vals = (Scalar*) PetscMalloc( nz*sizeof(Scalar) ); CHKPTRQ(vals);
11638965ea79SLois Curfman McInnes 
11648965ea79SLois Curfman McInnes     /* receive message of values*/
11658965ea79SLois Curfman McInnes     MPI_Recv(vals,nz,MPIU_SCALAR,0,A->tag,comm,&status);
11668965ea79SLois Curfman McInnes     MPI_Get_count(&status,MPIU_SCALAR,&maxnz);
116739ddd567SLois Curfman McInnes     if (maxnz != nz) SETERRQ(1,"MatLoad_MPIDenseorMPIRow:something is wrong with file");
11688965ea79SLois Curfman McInnes 
11698965ea79SLois Curfman McInnes     /* insert into matrix */
11708965ea79SLois Curfman McInnes     jj      = rstart;
11718965ea79SLois Curfman McInnes     smycols = mycols;
11728965ea79SLois Curfman McInnes     svals   = vals;
11738965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
11748965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
11758965ea79SLois Curfman McInnes       smycols += ourlens[i];
11768965ea79SLois Curfman McInnes       svals   += ourlens[i];
11778965ea79SLois Curfman McInnes       jj++;
11788965ea79SLois Curfman McInnes     }
11798965ea79SLois Curfman McInnes   }
11800452661fSBarry Smith   PetscFree(ourlens); PetscFree(vals); PetscFree(mycols); PetscFree(rowners);
11818965ea79SLois Curfman McInnes 
11826d4a8577SBarry Smith   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
11836d4a8577SBarry Smith   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
11848965ea79SLois Curfman McInnes   return 0;
11858965ea79SLois Curfman McInnes }
118690ace30eSBarry Smith 
118790ace30eSBarry Smith 
118890ace30eSBarry Smith 
118990ace30eSBarry Smith 
119090ace30eSBarry Smith 
1191