xref: /petsc/src/mat/impls/dense/mpi/mpidense.c (revision d2dc9b8121104b1db9679e59ba84d70adb08ea70)
18965ea79SLois Curfman McInnes #ifndef lint
2*d2dc9b81SLois Curfman McInnes static char vcid[] = "$Id: mpidense.c,v 1.57 1996/11/30 21:47:49 curfman Exp curfman $";
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 
127056b6fcSBarry 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++ ) {
457056b6fcSBarry 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);
1047056b6fcSBarry Smith   if (addv == (ADD_VALUES|INSERT_VALUES)) {
1057056b6fcSBarry 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];
1273b2fbd54SBarry Smith   if (nreceives > size) SETERRQ(1,"MatAssemblyBegin_MPIDense:Internal PETSc error");
1286d84be18SBarry Smith   MPI_Allreduce(nprocs,work,size,MPI_INT,MPI_MAX,comm);
1298965ea79SLois Curfman McInnes   nmax = work[rank];
1300452661fSBarry Smith   PetscFree(work);
1318965ea79SLois Curfman McInnes 
1328965ea79SLois Curfman McInnes   /* post receives:
1338965ea79SLois Curfman McInnes        1) each message will consist of ordered pairs
1348965ea79SLois Curfman McInnes      (global index,value) we store the global index as a double
1358965ea79SLois Curfman McInnes      to simplify the message passing.
1368965ea79SLois Curfman McInnes        2) since we don't know how long each individual message is we
1378965ea79SLois Curfman McInnes      allocate the largest needed buffer for each receive. Potentially
1388965ea79SLois Curfman McInnes      this is a lot of wasted space.
1398965ea79SLois Curfman McInnes 
1408965ea79SLois Curfman McInnes        This could be done better.
1418965ea79SLois Curfman McInnes   */
1423b2fbd54SBarry Smith   rvalues = (Scalar *) PetscMalloc(3*(nreceives+1)*(nmax+1)*sizeof(Scalar));CHKPTRQ(rvalues);
1433b2fbd54SBarry Smith   recv_waits = (MPI_Request *) PetscMalloc((nreceives+1)*sizeof(MPI_Request));CHKPTRQ(recv_waits);
1448965ea79SLois Curfman McInnes   for ( i=0; i<nreceives; i++ ) {
1457056b6fcSBarry Smith     MPI_Irecv(rvalues+3*nmax*i,3*nmax,MPIU_SCALAR,MPI_ANY_SOURCE,tag,comm,recv_waits+i);
1468965ea79SLois Curfman McInnes   }
1478965ea79SLois Curfman McInnes 
1488965ea79SLois Curfman McInnes   /* do sends:
1498965ea79SLois Curfman McInnes       1) starts[i] gives the starting index in svalues for stuff going to
1508965ea79SLois Curfman McInnes          the ith processor
1518965ea79SLois Curfman McInnes   */
1523b2fbd54SBarry Smith   svalues = (Scalar *) PetscMalloc( 3*(mdn->stash.n+1)*sizeof(Scalar));CHKPTRQ(svalues);
1533b2fbd54SBarry Smith   send_waits = (MPI_Request *) PetscMalloc((nsends+1)*sizeof(MPI_Request));CHKPTRQ(send_waits);
1540452661fSBarry Smith   starts = (int *) PetscMalloc( size*sizeof(int) ); CHKPTRQ(starts);
1558965ea79SLois Curfman McInnes   starts[0] = 0;
1568965ea79SLois Curfman McInnes   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
15739ddd567SLois Curfman McInnes   for ( i=0; i<mdn->stash.n; i++ ) {
15839ddd567SLois Curfman McInnes     svalues[3*starts[owner[i]]]       = (Scalar)  mdn->stash.idx[i];
15939ddd567SLois Curfman McInnes     svalues[3*starts[owner[i]]+1]     = (Scalar)  mdn->stash.idy[i];
16039ddd567SLois Curfman McInnes     svalues[3*(starts[owner[i]]++)+2] =  mdn->stash.array[i];
1618965ea79SLois Curfman McInnes   }
1620452661fSBarry Smith   PetscFree(owner);
1638965ea79SLois Curfman McInnes   starts[0] = 0;
1648965ea79SLois Curfman McInnes   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
1658965ea79SLois Curfman McInnes   count = 0;
1668965ea79SLois Curfman McInnes   for ( i=0; i<size; i++ ) {
1678965ea79SLois Curfman McInnes     if (procs[i]) {
1687056b6fcSBarry Smith       MPI_Isend(svalues+3*starts[i],3*nprocs[i],MPIU_SCALAR,i,tag,comm,send_waits+count++);
1698965ea79SLois Curfman McInnes     }
1708965ea79SLois Curfman McInnes   }
1710452661fSBarry Smith   PetscFree(starts); PetscFree(nprocs);
1728965ea79SLois Curfman McInnes 
1738965ea79SLois Curfman McInnes   /* Free cache space */
174*d2dc9b81SLois Curfman McInnes   PLogInfo(mat,"MatAssemblyBegin_MPIDense:Number of off-processor values %d\n",mdn->stash.n);
17539ddd567SLois Curfman McInnes   ierr = StashDestroy_Private(&mdn->stash); CHKERRQ(ierr);
1768965ea79SLois Curfman McInnes 
17739ddd567SLois Curfman McInnes   mdn->svalues    = svalues;    mdn->rvalues = rvalues;
17839ddd567SLois Curfman McInnes   mdn->nsends     = nsends;     mdn->nrecvs = nreceives;
17939ddd567SLois Curfman McInnes   mdn->send_waits = send_waits; mdn->recv_waits = recv_waits;
18039ddd567SLois Curfman McInnes   mdn->rmax       = nmax;
1818965ea79SLois Curfman McInnes 
1828965ea79SLois Curfman McInnes   return 0;
1838965ea79SLois Curfman McInnes }
18439ddd567SLois Curfman McInnes extern int MatSetUpMultiply_MPIDense(Mat);
1858965ea79SLois Curfman McInnes 
18639ddd567SLois Curfman McInnes static int MatAssemblyEnd_MPIDense(Mat mat,MatAssemblyType mode)
1878965ea79SLois Curfman McInnes {
18839ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
1898965ea79SLois Curfman McInnes   MPI_Status   *send_status,recv_status;
19039ddd567SLois Curfman McInnes   int          imdex, nrecvs=mdn->nrecvs, count=nrecvs, i, n, ierr, row, col;
1918965ea79SLois Curfman McInnes   Scalar       *values,val;
19239ddd567SLois Curfman McInnes   InsertMode   addv = mdn->insertmode;
1938965ea79SLois Curfman McInnes 
1948965ea79SLois Curfman McInnes   /*  wait on receives */
1958965ea79SLois Curfman McInnes   while (count) {
19639ddd567SLois Curfman McInnes     MPI_Waitany(nrecvs,mdn->recv_waits,&imdex,&recv_status);
1978965ea79SLois Curfman McInnes     /* unpack receives into our local space */
19839ddd567SLois Curfman McInnes     values = mdn->rvalues + 3*imdex*mdn->rmax;
1998965ea79SLois Curfman McInnes     MPI_Get_count(&recv_status,MPIU_SCALAR,&n);
2008965ea79SLois Curfman McInnes     n = n/3;
2018965ea79SLois Curfman McInnes     for ( i=0; i<n; i++ ) {
202227d817aSBarry Smith       row = (int) PetscReal(values[3*i]) - mdn->rstart;
203227d817aSBarry Smith       col = (int) PetscReal(values[3*i+1]);
2048965ea79SLois Curfman McInnes       val = values[3*i+2];
20539ddd567SLois Curfman McInnes       if (col >= 0 && col < mdn->N) {
20639ddd567SLois Curfman McInnes         MatSetValues(mdn->A,1,&row,1,&col,&val,addv);
2078965ea79SLois Curfman McInnes       }
20839ddd567SLois Curfman McInnes       else {SETERRQ(1,"MatAssemblyEnd_MPIDense:Invalid column");}
2098965ea79SLois Curfman McInnes     }
2108965ea79SLois Curfman McInnes     count--;
2118965ea79SLois Curfman McInnes   }
2120452661fSBarry Smith   PetscFree(mdn->recv_waits); PetscFree(mdn->rvalues);
2138965ea79SLois Curfman McInnes 
2148965ea79SLois Curfman McInnes   /* wait on sends */
21539ddd567SLois Curfman McInnes   if (mdn->nsends) {
2167056b6fcSBarry Smith     send_status = (MPI_Status *) PetscMalloc(mdn->nsends*sizeof(MPI_Status));CHKPTRQ(send_status);
21739ddd567SLois Curfman McInnes     MPI_Waitall(mdn->nsends,mdn->send_waits,send_status);
2180452661fSBarry Smith     PetscFree(send_status);
2198965ea79SLois Curfman McInnes   }
2200452661fSBarry Smith   PetscFree(mdn->send_waits); PetscFree(mdn->svalues);
2218965ea79SLois Curfman McInnes 
22239ddd567SLois Curfman McInnes   mdn->insertmode = NOT_SET_VALUES;
22339ddd567SLois Curfman McInnes   ierr = MatAssemblyBegin(mdn->A,mode); CHKERRQ(ierr);
22439ddd567SLois Curfman McInnes   ierr = MatAssemblyEnd(mdn->A,mode); CHKERRQ(ierr);
2258965ea79SLois Curfman McInnes 
2266d4a8577SBarry Smith   if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) {
22739ddd567SLois Curfman McInnes     ierr = MatSetUpMultiply_MPIDense(mat); CHKERRQ(ierr);
2288965ea79SLois Curfman McInnes   }
2298965ea79SLois Curfman McInnes   return 0;
2308965ea79SLois Curfman McInnes }
2318965ea79SLois Curfman McInnes 
23239ddd567SLois Curfman McInnes static int MatZeroEntries_MPIDense(Mat A)
2338965ea79SLois Curfman McInnes {
23439ddd567SLois Curfman McInnes   Mat_MPIDense *l = (Mat_MPIDense *) A->data;
23539ddd567SLois Curfman McInnes   return MatZeroEntries(l->A);
2368965ea79SLois Curfman McInnes }
2378965ea79SLois Curfman McInnes 
2384e220ebcSLois Curfman McInnes static int MatGetBlockSize_MPIDense(Mat A,int *bs)
2394e220ebcSLois Curfman McInnes {
2404e220ebcSLois Curfman McInnes   *bs = 1;
2414e220ebcSLois Curfman McInnes   return 0;
2424e220ebcSLois Curfman McInnes }
2434e220ebcSLois Curfman McInnes 
2448965ea79SLois Curfman McInnes /* the code does not do the diagonal entries correctly unless the
2458965ea79SLois Curfman McInnes    matrix is square and the column and row owerships are identical.
2468965ea79SLois Curfman McInnes    This is a BUG. The only way to fix it seems to be to access
2473501a2bdSLois Curfman McInnes    mdn->A and mdn->B directly and not through the MatZeroRows()
2488965ea79SLois Curfman McInnes    routine.
2498965ea79SLois Curfman McInnes */
25039ddd567SLois Curfman McInnes static int MatZeroRows_MPIDense(Mat A,IS is,Scalar *diag)
2518965ea79SLois Curfman McInnes {
25239ddd567SLois Curfman McInnes   Mat_MPIDense   *l = (Mat_MPIDense *) A->data;
2538965ea79SLois Curfman McInnes   int            i,ierr,N, *rows,*owners = l->rowners,size = l->size;
2548965ea79SLois Curfman McInnes   int            *procs,*nprocs,j,found,idx,nsends,*work;
2558965ea79SLois Curfman McInnes   int            nmax,*svalues,*starts,*owner,nrecvs,rank = l->rank;
2568965ea79SLois Curfman McInnes   int            *rvalues,tag = A->tag,count,base,slen,n,*source;
2578965ea79SLois Curfman McInnes   int            *lens,imdex,*lrows,*values;
2588965ea79SLois Curfman McInnes   MPI_Comm       comm = A->comm;
2598965ea79SLois Curfman McInnes   MPI_Request    *send_waits,*recv_waits;
2608965ea79SLois Curfman McInnes   MPI_Status     recv_status,*send_status;
2618965ea79SLois Curfman McInnes   IS             istmp;
2628965ea79SLois Curfman McInnes 
26377c4ece6SBarry Smith   ierr = ISGetSize(is,&N); CHKERRQ(ierr);
2648965ea79SLois Curfman McInnes   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
2658965ea79SLois Curfman McInnes 
2668965ea79SLois Curfman McInnes   /*  first count number of contributors to each processor */
2670452661fSBarry Smith   nprocs = (int *) PetscMalloc( 2*size*sizeof(int) ); CHKPTRQ(nprocs);
268cddf8d76SBarry Smith   PetscMemzero(nprocs,2*size*sizeof(int)); procs = nprocs + size;
2690452661fSBarry Smith   owner = (int *) PetscMalloc((N+1)*sizeof(int)); CHKPTRQ(owner); /* see note*/
2708965ea79SLois Curfman McInnes   for ( i=0; i<N; i++ ) {
2718965ea79SLois Curfman McInnes     idx = rows[i];
2728965ea79SLois Curfman McInnes     found = 0;
2738965ea79SLois Curfman McInnes     for ( j=0; j<size; j++ ) {
2748965ea79SLois Curfman McInnes       if (idx >= owners[j] && idx < owners[j+1]) {
2758965ea79SLois Curfman McInnes         nprocs[j]++; procs[j] = 1; owner[i] = j; found = 1; break;
2768965ea79SLois Curfman McInnes       }
2778965ea79SLois Curfman McInnes     }
27839ddd567SLois Curfman McInnes     if (!found) SETERRQ(1,"MatZeroRows_MPIDense:Index out of range");
2798965ea79SLois Curfman McInnes   }
2808965ea79SLois Curfman McInnes   nsends = 0;  for ( i=0; i<size; i++ ) { nsends += procs[i];}
2818965ea79SLois Curfman McInnes 
2828965ea79SLois Curfman McInnes   /* inform other processors of number of messages and max length*/
2830452661fSBarry Smith   work = (int *) PetscMalloc( size*sizeof(int) ); CHKPTRQ(work);
2848965ea79SLois Curfman McInnes   MPI_Allreduce( procs, work,size,MPI_INT,MPI_SUM,comm);
2858965ea79SLois Curfman McInnes   nrecvs = work[rank];
2868965ea79SLois Curfman McInnes   MPI_Allreduce( nprocs, work,size,MPI_INT,MPI_MAX,comm);
2878965ea79SLois Curfman McInnes   nmax = work[rank];
2880452661fSBarry Smith   PetscFree(work);
2898965ea79SLois Curfman McInnes 
2908965ea79SLois Curfman McInnes   /* post receives:   */
2910452661fSBarry Smith   rvalues = (int *) PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(int)); /*see note */
2928965ea79SLois Curfman McInnes   CHKPTRQ(rvalues);
2930452661fSBarry Smith   recv_waits = (MPI_Request *) PetscMalloc((nrecvs+1)*sizeof(MPI_Request));
2948965ea79SLois Curfman McInnes   CHKPTRQ(recv_waits);
2958965ea79SLois Curfman McInnes   for ( i=0; i<nrecvs; i++ ) {
2968965ea79SLois Curfman McInnes     MPI_Irecv(rvalues+nmax*i,nmax,MPI_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);
2978965ea79SLois Curfman McInnes   }
2988965ea79SLois Curfman McInnes 
2998965ea79SLois Curfman McInnes   /* do sends:
3008965ea79SLois Curfman McInnes       1) starts[i] gives the starting index in svalues for stuff going to
3018965ea79SLois Curfman McInnes          the ith processor
3028965ea79SLois Curfman McInnes   */
3030452661fSBarry Smith   svalues    = (int *) PetscMalloc( (N+1)*sizeof(int) ); CHKPTRQ(svalues);
3047056b6fcSBarry Smith   send_waits = (MPI_Request *) PetscMalloc((nsends+1)*sizeof(MPI_Request));CHKPTRQ(send_waits);
3050452661fSBarry Smith   starts     = (int *) PetscMalloc( (size+1)*sizeof(int) ); CHKPTRQ(starts);
3068965ea79SLois Curfman McInnes   starts[0]  = 0;
3078965ea79SLois Curfman McInnes   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
3088965ea79SLois Curfman McInnes   for ( i=0; i<N; i++ ) {
3098965ea79SLois Curfman McInnes     svalues[starts[owner[i]]++] = rows[i];
3108965ea79SLois Curfman McInnes   }
3118965ea79SLois Curfman McInnes   ISRestoreIndices(is,&rows);
3128965ea79SLois Curfman McInnes 
3138965ea79SLois Curfman McInnes   starts[0] = 0;
3148965ea79SLois Curfman McInnes   for ( i=1; i<size+1; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
3158965ea79SLois Curfman McInnes   count = 0;
3168965ea79SLois Curfman McInnes   for ( i=0; i<size; i++ ) {
3178965ea79SLois Curfman McInnes     if (procs[i]) {
3188965ea79SLois Curfman McInnes       MPI_Isend(svalues+starts[i],nprocs[i],MPI_INT,i,tag,comm,send_waits+count++);
3198965ea79SLois Curfman McInnes     }
3208965ea79SLois Curfman McInnes   }
3210452661fSBarry Smith   PetscFree(starts);
3228965ea79SLois Curfman McInnes 
3238965ea79SLois Curfman McInnes   base = owners[rank];
3248965ea79SLois Curfman McInnes 
3258965ea79SLois Curfman McInnes   /*  wait on receives */
3260452661fSBarry Smith   lens   = (int *) PetscMalloc( 2*(nrecvs+1)*sizeof(int) ); CHKPTRQ(lens);
3278965ea79SLois Curfman McInnes   source = lens + nrecvs;
3288965ea79SLois Curfman McInnes   count  = nrecvs; slen = 0;
3298965ea79SLois Curfman McInnes   while (count) {
3308965ea79SLois Curfman McInnes     MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);
3318965ea79SLois Curfman McInnes     /* unpack receives into our local space */
3328965ea79SLois Curfman McInnes     MPI_Get_count(&recv_status,MPI_INT,&n);
3338965ea79SLois Curfman McInnes     source[imdex]  = recv_status.MPI_SOURCE;
3348965ea79SLois Curfman McInnes     lens[imdex]  = n;
3358965ea79SLois Curfman McInnes     slen += n;
3368965ea79SLois Curfman McInnes     count--;
3378965ea79SLois Curfman McInnes   }
3380452661fSBarry Smith   PetscFree(recv_waits);
3398965ea79SLois Curfman McInnes 
3408965ea79SLois Curfman McInnes   /* move the data into the send scatter */
3410452661fSBarry Smith   lrows = (int *) PetscMalloc( (slen+1)*sizeof(int) ); CHKPTRQ(lrows);
3428965ea79SLois Curfman McInnes   count = 0;
3438965ea79SLois Curfman McInnes   for ( i=0; i<nrecvs; i++ ) {
3448965ea79SLois Curfman McInnes     values = rvalues + i*nmax;
3458965ea79SLois Curfman McInnes     for ( j=0; j<lens[i]; j++ ) {
3468965ea79SLois Curfman McInnes       lrows[count++] = values[j] - base;
3478965ea79SLois Curfman McInnes     }
3488965ea79SLois Curfman McInnes   }
3490452661fSBarry Smith   PetscFree(rvalues); PetscFree(lens);
3500452661fSBarry Smith   PetscFree(owner); PetscFree(nprocs);
3518965ea79SLois Curfman McInnes 
3528965ea79SLois Curfman McInnes   /* actually zap the local rows */
353537820f0SBarry Smith   ierr = ISCreateGeneral(MPI_COMM_SELF,slen,lrows,&istmp);CHKERRQ(ierr);
3548965ea79SLois Curfman McInnes   PLogObjectParent(A,istmp);
3550452661fSBarry Smith   PetscFree(lrows);
3568965ea79SLois Curfman McInnes   ierr = MatZeroRows(l->A,istmp,diag); CHKERRQ(ierr);
3578965ea79SLois Curfman McInnes   ierr = ISDestroy(istmp); CHKERRQ(ierr);
3588965ea79SLois Curfman McInnes 
3598965ea79SLois Curfman McInnes   /* wait on sends */
3608965ea79SLois Curfman McInnes   if (nsends) {
3617056b6fcSBarry Smith     send_status = (MPI_Status *) PetscMalloc(nsends*sizeof(MPI_Status));CHKPTRQ(send_status);
3628965ea79SLois Curfman McInnes     MPI_Waitall(nsends,send_waits,send_status);
3630452661fSBarry Smith     PetscFree(send_status);
3648965ea79SLois Curfman McInnes   }
3650452661fSBarry Smith   PetscFree(send_waits); PetscFree(svalues);
3668965ea79SLois Curfman McInnes 
3678965ea79SLois Curfman McInnes   return 0;
3688965ea79SLois Curfman McInnes }
3698965ea79SLois Curfman McInnes 
37039ddd567SLois Curfman McInnes static int MatMult_MPIDense(Mat mat,Vec xx,Vec yy)
3718965ea79SLois Curfman McInnes {
37239ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3738965ea79SLois Curfman McInnes   int          ierr;
374c456f294SBarry Smith 
37543a90d84SBarry Smith   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
37643a90d84SBarry Smith   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
37744cd7ae7SLois Curfman McInnes   ierr = MatMult_SeqDense(mdn->A,mdn->lvec,yy); CHKERRQ(ierr);
3788965ea79SLois Curfman McInnes   return 0;
3798965ea79SLois Curfman McInnes }
3808965ea79SLois Curfman McInnes 
38139ddd567SLois Curfman McInnes static int MatMultAdd_MPIDense(Mat mat,Vec xx,Vec yy,Vec zz)
3828965ea79SLois Curfman McInnes {
38339ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3848965ea79SLois Curfman McInnes   int          ierr;
385c456f294SBarry Smith 
38643a90d84SBarry Smith   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
38743a90d84SBarry Smith   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
38844cd7ae7SLois Curfman McInnes   ierr = MatMultAdd_SeqDense(mdn->A,mdn->lvec,yy,zz); CHKERRQ(ierr);
3898965ea79SLois Curfman McInnes   return 0;
3908965ea79SLois Curfman McInnes }
3918965ea79SLois Curfman McInnes 
392096963f5SLois Curfman McInnes static int MatMultTrans_MPIDense(Mat A,Vec xx,Vec yy)
393096963f5SLois Curfman McInnes {
394096963f5SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
395096963f5SLois Curfman McInnes   int          ierr;
3963501a2bdSLois Curfman McInnes   Scalar       zero = 0.0;
397096963f5SLois Curfman McInnes 
3983501a2bdSLois Curfman McInnes   ierr = VecSet(&zero,yy); CHKERRQ(ierr);
39944cd7ae7SLois Curfman McInnes   ierr = MatMultTrans_SeqDense(a->A,xx,a->lvec); CHKERRQ(ierr);
400537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
401537820f0SBarry Smith   ierr = VecScatterEnd(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
402096963f5SLois Curfman McInnes   return 0;
403096963f5SLois Curfman McInnes }
404096963f5SLois Curfman McInnes 
405096963f5SLois Curfman McInnes static int MatMultTransAdd_MPIDense(Mat A,Vec xx,Vec yy,Vec zz)
406096963f5SLois Curfman McInnes {
407096963f5SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
408096963f5SLois Curfman McInnes   int          ierr;
409096963f5SLois Curfman McInnes 
4103501a2bdSLois Curfman McInnes   ierr = VecCopy(yy,zz); CHKERRQ(ierr);
41144cd7ae7SLois Curfman McInnes   ierr = MatMultTrans_SeqDense(a->A,xx,a->lvec); CHKERRQ(ierr);
412537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
413537820f0SBarry Smith   ierr = VecScatterEnd(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
414096963f5SLois Curfman McInnes   return 0;
415096963f5SLois Curfman McInnes }
416096963f5SLois Curfman McInnes 
41739ddd567SLois Curfman McInnes static int MatGetDiagonal_MPIDense(Mat A,Vec v)
4188965ea79SLois Curfman McInnes {
41939ddd567SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
420096963f5SLois Curfman McInnes   Mat_SeqDense *aloc = (Mat_SeqDense *) a->A->data;
42144cd7ae7SLois Curfman McInnes   int          ierr, len, i, n, m = a->m, radd;
42244cd7ae7SLois Curfman McInnes   Scalar       *x, zero = 0.0;
423ed3cc1f0SBarry Smith 
42444cd7ae7SLois Curfman McInnes   VecSet(&zero,v);
425096963f5SLois Curfman McInnes   ierr = VecGetArray(v,&x); CHKERRQ(ierr);
426096963f5SLois Curfman McInnes   ierr = VecGetSize(v,&n); CHKERRQ(ierr);
427096963f5SLois Curfman McInnes   if (n != a->M) SETERRQ(1,"MatGetDiagonal_SeqDense:Nonconforming mat and vec");
42844cd7ae7SLois Curfman McInnes   len = PetscMin(aloc->m,aloc->n);
4297ddc982cSLois Curfman McInnes   radd = a->rstart*m;
43044cd7ae7SLois Curfman McInnes   for ( i=0; i<len; i++ ) {
431096963f5SLois Curfman McInnes     x[i] = aloc->v[radd + i*m + i];
432096963f5SLois Curfman McInnes   }
433096963f5SLois Curfman McInnes   return 0;
4348965ea79SLois Curfman McInnes }
4358965ea79SLois Curfman McInnes 
43639ddd567SLois Curfman McInnes static int MatDestroy_MPIDense(PetscObject obj)
4378965ea79SLois Curfman McInnes {
4388965ea79SLois Curfman McInnes   Mat          mat = (Mat) obj;
4393501a2bdSLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
4408965ea79SLois Curfman McInnes   int          ierr;
441ed3cc1f0SBarry Smith 
4428965ea79SLois Curfman McInnes #if defined(PETSC_LOG)
4433501a2bdSLois Curfman McInnes   PLogObjectState(obj,"Rows=%d, Cols=%d",mdn->M,mdn->N);
4448965ea79SLois Curfman McInnes #endif
4450452661fSBarry Smith   PetscFree(mdn->rowners);
4463501a2bdSLois Curfman McInnes   ierr = MatDestroy(mdn->A); CHKERRQ(ierr);
4473501a2bdSLois Curfman McInnes   if (mdn->lvec)   VecDestroy(mdn->lvec);
4483501a2bdSLois Curfman McInnes   if (mdn->Mvctx)  VecScatterDestroy(mdn->Mvctx);
449622d7880SLois Curfman McInnes   if (mdn->factor) {
450622d7880SLois Curfman McInnes     if (mdn->factor->temp)   PetscFree(mdn->factor->temp);
451622d7880SLois Curfman McInnes     if (mdn->factor->tag)    PetscFree(mdn->factor->tag);
452622d7880SLois Curfman McInnes     if (mdn->factor->pivots) PetscFree(mdn->factor->pivots);
453622d7880SLois Curfman McInnes     PetscFree(mdn->factor);
454622d7880SLois Curfman McInnes   }
4550452661fSBarry Smith   PetscFree(mdn);
45690f02eecSBarry Smith   if (mat->mapping) {
45790f02eecSBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->mapping); CHKERRQ(ierr);
45890f02eecSBarry Smith   }
4598965ea79SLois Curfman McInnes   PLogObjectDestroy(mat);
4600452661fSBarry Smith   PetscHeaderDestroy(mat);
4618965ea79SLois Curfman McInnes   return 0;
4628965ea79SLois Curfman McInnes }
46339ddd567SLois Curfman McInnes 
4648965ea79SLois Curfman McInnes #include "pinclude/pviewer.h"
4658965ea79SLois Curfman McInnes 
46639ddd567SLois Curfman McInnes static int MatView_MPIDense_Binary(Mat mat,Viewer viewer)
4678965ea79SLois Curfman McInnes {
46839ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
4698965ea79SLois Curfman McInnes   int          ierr;
4707056b6fcSBarry Smith 
47139ddd567SLois Curfman McInnes   if (mdn->size == 1) {
47239ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
4738965ea79SLois Curfman McInnes   }
47439ddd567SLois Curfman McInnes   else SETERRQ(1,"MatView_MPIDense_Binary:Only uniprocessor output supported");
4758965ea79SLois Curfman McInnes   return 0;
4768965ea79SLois Curfman McInnes }
4778965ea79SLois Curfman McInnes 
47839ddd567SLois Curfman McInnes static int MatView_MPIDense_ASCII(Mat mat,Viewer viewer)
4798965ea79SLois Curfman McInnes {
48039ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
48139ddd567SLois Curfman McInnes   int          ierr, format;
4828965ea79SLois Curfman McInnes   FILE         *fd;
48319bcc07fSBarry Smith   ViewerType   vtype;
4848965ea79SLois Curfman McInnes 
48519bcc07fSBarry Smith   ViewerGetType(viewer,&vtype);
48690ace30eSBarry Smith   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
48790ace30eSBarry Smith   ierr = ViewerGetFormat(viewer,&format);
488639f9d9dSBarry Smith   if (format == VIEWER_FORMAT_ASCII_INFO_LONG) {
4894e220ebcSLois Curfman McInnes     int rank;
4904e220ebcSLois Curfman McInnes     MatInfo info;
491096963f5SLois Curfman McInnes     MPI_Comm_rank(mat->comm,&rank);
4924e220ebcSLois Curfman McInnes     ierr = MatGetInfo(mat,MAT_LOCAL,&info);
49377c4ece6SBarry Smith     PetscSequentialPhaseBegin(mat->comm,1);
4944e220ebcSLois Curfman McInnes       fprintf(fd,"  [%d] local rows %d nz %d nz alloced %d mem %d \n",rank,mdn->m,
4954e220ebcSLois Curfman McInnes          (int)info.nz_used,(int)info.nz_allocated,(int)info.memory);
496096963f5SLois Curfman McInnes       fflush(fd);
49777c4ece6SBarry Smith     PetscSequentialPhaseEnd(mat->comm,1);
4983501a2bdSLois Curfman McInnes     ierr = VecScatterView(mdn->Mvctx,viewer); CHKERRQ(ierr);
4993501a2bdSLois Curfman McInnes     return 0;
5003501a2bdSLois Curfman McInnes   }
50102cad45dSBarry Smith   else if (format == VIEWER_FORMAT_ASCII_INFO) {
502096963f5SLois Curfman McInnes     return 0;
5038965ea79SLois Curfman McInnes   }
50419bcc07fSBarry Smith   if (vtype == ASCII_FILE_VIEWER) {
50577c4ece6SBarry Smith     PetscSequentialPhaseBegin(mat->comm,1);
50639ddd567SLois Curfman McInnes     fprintf(fd,"[%d] rows %d starts %d ends %d cols %d\n",
50739ddd567SLois Curfman McInnes              mdn->rank,mdn->m,mdn->rstart,mdn->rend,mdn->n);
50839ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
5098965ea79SLois Curfman McInnes     fflush(fd);
51077c4ece6SBarry Smith     PetscSequentialPhaseEnd(mat->comm,1);
5118965ea79SLois Curfman McInnes   }
5128965ea79SLois Curfman McInnes   else {
51339ddd567SLois Curfman McInnes     int size = mdn->size, rank = mdn->rank;
5148965ea79SLois Curfman McInnes     if (size == 1) {
51539ddd567SLois Curfman McInnes       ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
5168965ea79SLois Curfman McInnes     }
5178965ea79SLois Curfman McInnes     else {
5188965ea79SLois Curfman McInnes       /* assemble the entire matrix onto first processor. */
5198965ea79SLois Curfman McInnes       Mat          A;
52039ddd567SLois Curfman McInnes       int          M = mdn->M, N = mdn->N,m,row,i, nz, *cols;
52139ddd567SLois Curfman McInnes       Scalar       *vals;
52239ddd567SLois Curfman McInnes       Mat_SeqDense *Amdn = (Mat_SeqDense*) mdn->A->data;
5238965ea79SLois Curfman McInnes 
5248965ea79SLois Curfman McInnes       if (!rank) {
525b4fd4287SBarry Smith         ierr = MatCreateMPIDense(mat->comm,M,M,N,N,PETSC_NULL,&A); CHKERRQ(ierr);
5268965ea79SLois Curfman McInnes       }
5278965ea79SLois Curfman McInnes       else {
528b4fd4287SBarry Smith         ierr = MatCreateMPIDense(mat->comm,0,M,N,N,PETSC_NULL,&A); CHKERRQ(ierr);
5298965ea79SLois Curfman McInnes       }
5308965ea79SLois Curfman McInnes       PLogObjectParent(mat,A);
5318965ea79SLois Curfman McInnes 
53239ddd567SLois Curfman McInnes       /* Copy the matrix ... This isn't the most efficient means,
53339ddd567SLois Curfman McInnes          but it's quick for now */
53439ddd567SLois Curfman McInnes       row = mdn->rstart; m = Amdn->m;
5358965ea79SLois Curfman McInnes       for ( i=0; i<m; i++ ) {
53639ddd567SLois Curfman McInnes         ierr = MatGetRow(mat,row,&nz,&cols,&vals); CHKERRQ(ierr);
53739ddd567SLois Curfman McInnes         ierr = MatSetValues(A,1,&row,nz,cols,vals,INSERT_VALUES); CHKERRQ(ierr);
53839ddd567SLois Curfman McInnes         ierr = MatRestoreRow(mat,row,&nz,&cols,&vals); CHKERRQ(ierr);
53939ddd567SLois Curfman McInnes         row++;
5408965ea79SLois Curfman McInnes       }
5418965ea79SLois Curfman McInnes 
5426d4a8577SBarry Smith       ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
5436d4a8577SBarry Smith       ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
5448965ea79SLois Curfman McInnes       if (!rank) {
54539ddd567SLois Curfman McInnes         ierr = MatView(((Mat_MPIDense*)(A->data))->A,viewer); CHKERRQ(ierr);
5468965ea79SLois Curfman McInnes       }
5478965ea79SLois Curfman McInnes       ierr = MatDestroy(A); CHKERRQ(ierr);
5488965ea79SLois Curfman McInnes     }
5498965ea79SLois Curfman McInnes   }
5508965ea79SLois Curfman McInnes   return 0;
5518965ea79SLois Curfman McInnes }
5528965ea79SLois Curfman McInnes 
55339ddd567SLois Curfman McInnes static int MatView_MPIDense(PetscObject obj,Viewer viewer)
5548965ea79SLois Curfman McInnes {
5558965ea79SLois Curfman McInnes   Mat          mat = (Mat) obj;
55639ddd567SLois Curfman McInnes   int          ierr;
557bcd2baecSBarry Smith   ViewerType   vtype;
5588965ea79SLois Curfman McInnes 
559bcd2baecSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
560bcd2baecSBarry Smith   if (vtype == ASCII_FILE_VIEWER) {
56139ddd567SLois Curfman McInnes     ierr = MatView_MPIDense_ASCII(mat,viewer); CHKERRQ(ierr);
5628965ea79SLois Curfman McInnes   }
563bcd2baecSBarry Smith   else if (vtype == ASCII_FILES_VIEWER) {
56439ddd567SLois Curfman McInnes     ierr = MatView_MPIDense_ASCII(mat,viewer); CHKERRQ(ierr);
5658965ea79SLois Curfman McInnes   }
566bcd2baecSBarry Smith   else if (vtype == BINARY_FILE_VIEWER) {
56739ddd567SLois Curfman McInnes     return MatView_MPIDense_Binary(mat,viewer);
5688965ea79SLois Curfman McInnes   }
5698965ea79SLois Curfman McInnes   return 0;
5708965ea79SLois Curfman McInnes }
5718965ea79SLois Curfman McInnes 
5724e220ebcSLois Curfman McInnes static int MatGetInfo_MPIDense(Mat A,MatInfoType flag,MatInfo *info)
5738965ea79SLois Curfman McInnes {
5743501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
5753501a2bdSLois Curfman McInnes   Mat          mdn = mat->A;
5764e220ebcSLois Curfman McInnes   int          ierr;
5774e220ebcSLois Curfman McInnes   double       isend[5], irecv[5];
5788965ea79SLois Curfman McInnes 
5794e220ebcSLois Curfman McInnes   info->rows_global    = (double)mat->M;
5804e220ebcSLois Curfman McInnes   info->columns_global = (double)mat->N;
5814e220ebcSLois Curfman McInnes   info->rows_local     = (double)mat->m;
5824e220ebcSLois Curfman McInnes   info->columns_local  = (double)mat->N;
5834e220ebcSLois Curfman McInnes   info->block_size     = 1.0;
5844e220ebcSLois Curfman McInnes   ierr = MatGetInfo(mdn,MAT_LOCAL,info); CHKERRQ(ierr);
5854e220ebcSLois Curfman McInnes   isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded;
5864e220ebcSLois Curfman McInnes   isend[3] = info->memory;  isend[4] = info->mallocs;
5878965ea79SLois Curfman McInnes   if (flag == MAT_LOCAL) {
5884e220ebcSLois Curfman McInnes     info->nz_used      = isend[0];
5894e220ebcSLois Curfman McInnes     info->nz_allocated = isend[1];
5904e220ebcSLois Curfman McInnes     info->nz_unneeded  = isend[2];
5914e220ebcSLois Curfman McInnes     info->memory       = isend[3];
5924e220ebcSLois Curfman McInnes     info->mallocs      = isend[4];
5938965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_MAX) {
5943501a2bdSLois Curfman McInnes     MPI_Allreduce(isend,irecv,3,MPI_INT,MPI_MAX,A->comm);
5954e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
5964e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
5974e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
5984e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
5994e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
6008965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_SUM) {
6013501a2bdSLois Curfman McInnes     MPI_Allreduce(isend,irecv,3,MPI_INT,MPI_SUM,A->comm);
6024e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
6034e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
6044e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
6054e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
6064e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
6078965ea79SLois Curfman McInnes   }
6084e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0; /* no parallel LU/ILU/Cholesky */
6094e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
6104e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
6118965ea79SLois Curfman McInnes   return 0;
6128965ea79SLois Curfman McInnes }
6138965ea79SLois Curfman McInnes 
6148c469469SLois Curfman McInnes /* extern int MatLUFactorSymbolic_MPIDense(Mat,IS,IS,double,Mat*);
6158aaee692SLois Curfman McInnes    extern int MatLUFactorNumeric_MPIDense(Mat,Mat*);
6168aaee692SLois Curfman McInnes    extern int MatLUFactor_MPIDense(Mat,IS,IS,double);
6178aaee692SLois Curfman McInnes    extern int MatSolve_MPIDense(Mat,Vec,Vec);
6188c469469SLois Curfman McInnes    extern int MatSolveAdd_MPIDense(Mat,Vec,Vec,Vec);
6198aaee692SLois Curfman McInnes    extern int MatSolveTrans_MPIDense(Mat,Vec,Vec);
6208aaee692SLois Curfman McInnes    extern int MatSolveTransAdd_MPIDense(Mat,Vec,Vec,Vec); */
6218aaee692SLois Curfman McInnes 
62239ddd567SLois Curfman McInnes static int MatSetOption_MPIDense(Mat A,MatOption op)
6238965ea79SLois Curfman McInnes {
62439ddd567SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
6258965ea79SLois Curfman McInnes 
6266d4a8577SBarry Smith   if (op == MAT_NO_NEW_NONZERO_LOCATIONS ||
6276d4a8577SBarry Smith       op == MAT_YES_NEW_NONZERO_LOCATIONS ||
628219d9a1aSLois Curfman McInnes       op == MAT_COLUMNS_SORTED ||
629219d9a1aSLois Curfman McInnes       op == MAT_COLUMNS_UNSORTED) {
630b1fbbac0SLois Curfman McInnes         MatSetOption(a->A,op);
631b1fbbac0SLois Curfman McInnes   } else if (op == MAT_ROW_ORIENTED) {
632aeafbbfcSLois Curfman McInnes         a->roworiented = 1;
6338965ea79SLois Curfman McInnes         MatSetOption(a->A,op);
634b1fbbac0SLois Curfman McInnes   } else if (op == MAT_ROWS_SORTED ||
635219d9a1aSLois Curfman McInnes              op == MAT_ROWS_UNSORTED ||
6366d4a8577SBarry Smith              op == MAT_SYMMETRIC ||
6376d4a8577SBarry Smith              op == MAT_STRUCTURALLY_SYMMETRIC ||
6386d4a8577SBarry Smith              op == MAT_YES_NEW_DIAGONALS)
63994a424c1SBarry Smith     PLogInfo(A,"Info:MatSetOption_MPIDense:Option ignored\n");
6406d4a8577SBarry Smith   else if (op == MAT_COLUMN_ORIENTED)
64139b7565bSBarry Smith     {a->roworiented = 0; MatSetOption(a->A,op);}
6426d4a8577SBarry Smith   else if (op == MAT_NO_NEW_DIAGONALS)
6436d4a8577SBarry Smith     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_MPIDense:MAT_NO_NEW_DIAGONALS");}
6448965ea79SLois Curfman McInnes   else
64539ddd567SLois Curfman McInnes     {SETERRQ(PETSC_ERR_SUP,"MatSetOption_MPIDense:unknown option");}
6468965ea79SLois Curfman McInnes   return 0;
6478965ea79SLois Curfman McInnes }
6488965ea79SLois Curfman McInnes 
6493501a2bdSLois Curfman McInnes static int MatGetSize_MPIDense(Mat A,int *m,int *n)
6508965ea79SLois Curfman McInnes {
6513501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6528965ea79SLois Curfman McInnes   *m = mat->M; *n = mat->N;
6538965ea79SLois Curfman McInnes   return 0;
6548965ea79SLois Curfman McInnes }
6558965ea79SLois Curfman McInnes 
6563501a2bdSLois Curfman McInnes static int MatGetLocalSize_MPIDense(Mat A,int *m,int *n)
6578965ea79SLois Curfman McInnes {
6583501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6598965ea79SLois Curfman McInnes   *m = mat->m; *n = mat->N;
6608965ea79SLois Curfman McInnes   return 0;
6618965ea79SLois Curfman McInnes }
6628965ea79SLois Curfman McInnes 
6633501a2bdSLois Curfman McInnes static int MatGetOwnershipRange_MPIDense(Mat A,int *m,int *n)
6648965ea79SLois Curfman McInnes {
6653501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6668965ea79SLois Curfman McInnes   *m = mat->rstart; *n = mat->rend;
6678965ea79SLois Curfman McInnes   return 0;
6688965ea79SLois Curfman McInnes }
6698965ea79SLois Curfman McInnes 
6703501a2bdSLois Curfman McInnes static int MatGetRow_MPIDense(Mat A,int row,int *nz,int **idx,Scalar **v)
6718965ea79SLois Curfman McInnes {
6723501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
67339ddd567SLois Curfman McInnes   int          lrow, rstart = mat->rstart, rend = mat->rend;
6748965ea79SLois Curfman McInnes 
67539ddd567SLois Curfman McInnes   if (row < rstart || row >= rend) SETERRQ(1,"MatGetRow_MPIDense:only local rows")
6768965ea79SLois Curfman McInnes   lrow = row - rstart;
67739ddd567SLois Curfman McInnes   return MatGetRow(mat->A,lrow,nz,idx,v);
6788965ea79SLois Curfman McInnes }
6798965ea79SLois Curfman McInnes 
68039ddd567SLois Curfman McInnes static int MatRestoreRow_MPIDense(Mat mat,int row,int *nz,int **idx,Scalar **v)
6818965ea79SLois Curfman McInnes {
6820452661fSBarry Smith   if (idx) PetscFree(*idx);
6830452661fSBarry Smith   if (v) PetscFree(*v);
6848965ea79SLois Curfman McInnes   return 0;
6858965ea79SLois Curfman McInnes }
6868965ea79SLois Curfman McInnes 
687cddf8d76SBarry Smith static int MatNorm_MPIDense(Mat A,NormType type,double *norm)
688096963f5SLois Curfman McInnes {
6893501a2bdSLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) A->data;
6903501a2bdSLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense*) mdn->A->data;
6913501a2bdSLois Curfman McInnes   int          ierr, i, j;
6923501a2bdSLois Curfman McInnes   double       sum = 0.0;
6933501a2bdSLois Curfman McInnes   Scalar       *v = mat->v;
6943501a2bdSLois Curfman McInnes 
6953501a2bdSLois Curfman McInnes   if (mdn->size == 1) {
6963501a2bdSLois Curfman McInnes     ierr =  MatNorm(mdn->A,type,norm); CHKERRQ(ierr);
6973501a2bdSLois Curfman McInnes   } else {
6983501a2bdSLois Curfman McInnes     if (type == NORM_FROBENIUS) {
6993501a2bdSLois Curfman McInnes       for (i=0; i<mat->n*mat->m; i++ ) {
7003501a2bdSLois Curfman McInnes #if defined(PETSC_COMPLEX)
7013501a2bdSLois Curfman McInnes         sum += real(conj(*v)*(*v)); v++;
7023501a2bdSLois Curfman McInnes #else
7033501a2bdSLois Curfman McInnes         sum += (*v)*(*v); v++;
7043501a2bdSLois Curfman McInnes #endif
7053501a2bdSLois Curfman McInnes       }
7066d84be18SBarry Smith       MPI_Allreduce(&sum,norm,1,MPI_DOUBLE,MPI_SUM,A->comm);
7073501a2bdSLois Curfman McInnes       *norm = sqrt(*norm);
7083501a2bdSLois Curfman McInnes       PLogFlops(2*mat->n*mat->m);
7093501a2bdSLois Curfman McInnes     }
7103501a2bdSLois Curfman McInnes     else if (type == NORM_1) {
7113501a2bdSLois Curfman McInnes       double *tmp, *tmp2;
7120452661fSBarry Smith       tmp  = (double *) PetscMalloc( 2*mdn->N*sizeof(double) ); CHKPTRQ(tmp);
7133501a2bdSLois Curfman McInnes       tmp2 = tmp + mdn->N;
714cddf8d76SBarry Smith       PetscMemzero(tmp,2*mdn->N*sizeof(double));
715096963f5SLois Curfman McInnes       *norm = 0.0;
7163501a2bdSLois Curfman McInnes       v = mat->v;
7173501a2bdSLois Curfman McInnes       for ( j=0; j<mat->n; j++ ) {
7183501a2bdSLois Curfman McInnes         for ( i=0; i<mat->m; i++ ) {
71967e560aaSBarry Smith           tmp[j] += PetscAbsScalar(*v);  v++;
7203501a2bdSLois Curfman McInnes         }
7213501a2bdSLois Curfman McInnes       }
7226d84be18SBarry Smith       MPI_Allreduce(tmp,tmp2,mdn->N,MPI_DOUBLE,MPI_SUM,A->comm);
7233501a2bdSLois Curfman McInnes       for ( j=0; j<mdn->N; j++ ) {
7243501a2bdSLois Curfman McInnes         if (tmp2[j] > *norm) *norm = tmp2[j];
7253501a2bdSLois Curfman McInnes       }
7260452661fSBarry Smith       PetscFree(tmp);
7273501a2bdSLois Curfman McInnes       PLogFlops(mat->n*mat->m);
7283501a2bdSLois Curfman McInnes     }
7293501a2bdSLois Curfman McInnes     else if (type == NORM_INFINITY) { /* max row norm */
7303501a2bdSLois Curfman McInnes       double ntemp;
7313501a2bdSLois Curfman McInnes       ierr = MatNorm(mdn->A,type,&ntemp); CHKERRQ(ierr);
7326d84be18SBarry Smith       MPI_Allreduce(&ntemp,norm,1,MPI_DOUBLE,MPI_MAX,A->comm);
7333501a2bdSLois Curfman McInnes     }
7343501a2bdSLois Curfman McInnes     else {
7353501a2bdSLois Curfman McInnes       SETERRQ(1,"MatNorm_MPIDense:No support for two norm");
7363501a2bdSLois Curfman McInnes     }
7373501a2bdSLois Curfman McInnes   }
7383501a2bdSLois Curfman McInnes   return 0;
7393501a2bdSLois Curfman McInnes }
7403501a2bdSLois Curfman McInnes 
7413501a2bdSLois Curfman McInnes static int MatTranspose_MPIDense(Mat A,Mat *matout)
7423501a2bdSLois Curfman McInnes {
7433501a2bdSLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
7443501a2bdSLois Curfman McInnes   Mat_SeqDense *Aloc = (Mat_SeqDense *) a->A->data;
7453501a2bdSLois Curfman McInnes   Mat          B;
7463501a2bdSLois Curfman McInnes   int          M = a->M, N = a->N, m, n, *rwork, rstart = a->rstart;
7473501a2bdSLois Curfman McInnes   int          j, i, ierr;
7483501a2bdSLois Curfman McInnes   Scalar       *v;
7493501a2bdSLois Curfman McInnes 
7507056b6fcSBarry Smith   if (matout == PETSC_NULL && M != N) {
7513501a2bdSLois Curfman McInnes     SETERRQ(1,"MatTranspose_MPIDense:Supports square matrix only in-place");
7527056b6fcSBarry Smith   }
7537056b6fcSBarry Smith   ierr = MatCreateMPIDense(A->comm,PETSC_DECIDE,PETSC_DECIDE,N,M,PETSC_NULL,&B);CHKERRQ(ierr);
7543501a2bdSLois Curfman McInnes 
7553501a2bdSLois Curfman McInnes   m = Aloc->m; n = Aloc->n; v = Aloc->v;
7560452661fSBarry Smith   rwork = (int *) PetscMalloc(n*sizeof(int)); CHKPTRQ(rwork);
7573501a2bdSLois Curfman McInnes   for ( j=0; j<n; j++ ) {
7583501a2bdSLois Curfman McInnes     for (i=0; i<m; i++) rwork[i] = rstart + i;
7593501a2bdSLois Curfman McInnes     ierr = MatSetValues(B,1,&j,m,rwork,v,INSERT_VALUES); CHKERRQ(ierr);
7603501a2bdSLois Curfman McInnes     v   += m;
7613501a2bdSLois Curfman McInnes   }
7620452661fSBarry Smith   PetscFree(rwork);
7636d4a8577SBarry Smith   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
7646d4a8577SBarry Smith   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
7653638b69dSLois Curfman McInnes   if (matout != PETSC_NULL) {
7663501a2bdSLois Curfman McInnes     *matout = B;
7673501a2bdSLois Curfman McInnes   } else {
7683501a2bdSLois Curfman McInnes     /* This isn't really an in-place transpose, but free data struct from a */
7690452661fSBarry Smith     PetscFree(a->rowners);
7703501a2bdSLois Curfman McInnes     ierr = MatDestroy(a->A); CHKERRQ(ierr);
7713501a2bdSLois Curfman McInnes     if (a->lvec) VecDestroy(a->lvec);
7723501a2bdSLois Curfman McInnes     if (a->Mvctx) VecScatterDestroy(a->Mvctx);
7730452661fSBarry Smith     PetscFree(a);
7743501a2bdSLois Curfman McInnes     PetscMemcpy(A,B,sizeof(struct _Mat));
7750452661fSBarry Smith     PetscHeaderDestroy(B);
7763501a2bdSLois Curfman McInnes   }
777096963f5SLois Curfman McInnes   return 0;
778096963f5SLois Curfman McInnes }
779096963f5SLois Curfman McInnes 
78044cd7ae7SLois Curfman McInnes #include "pinclude/plapack.h"
78144cd7ae7SLois Curfman McInnes static int MatScale_MPIDense(Scalar *alpha,Mat inA)
78244cd7ae7SLois Curfman McInnes {
78344cd7ae7SLois Curfman McInnes   Mat_MPIDense *A = (Mat_MPIDense *) inA->data;
78444cd7ae7SLois Curfman McInnes   Mat_SeqDense *a = (Mat_SeqDense *) A->A->data;
78544cd7ae7SLois Curfman McInnes   int          one = 1, nz;
78644cd7ae7SLois Curfman McInnes 
78744cd7ae7SLois Curfman McInnes   nz = a->m*a->n;
78844cd7ae7SLois Curfman McInnes   BLscal_( &nz, alpha, a->v, &one );
78944cd7ae7SLois Curfman McInnes   PLogFlops(nz);
79044cd7ae7SLois Curfman McInnes   return 0;
79144cd7ae7SLois Curfman McInnes }
79244cd7ae7SLois Curfman McInnes 
7933d1612f7SBarry Smith static int MatConvertSameType_MPIDense(Mat,Mat *,int);
7948965ea79SLois Curfman McInnes 
7958965ea79SLois Curfman McInnes /* -------------------------------------------------------------------*/
79639ddd567SLois Curfman McInnes static struct _MatOps MatOps = {MatSetValues_MPIDense,
79739ddd567SLois Curfman McInnes        MatGetRow_MPIDense,MatRestoreRow_MPIDense,
79839ddd567SLois Curfman McInnes        MatMult_MPIDense,MatMultAdd_MPIDense,
799096963f5SLois Curfman McInnes        MatMultTrans_MPIDense,MatMultTransAdd_MPIDense,
800e7ca0642SLois Curfman McInnes /*       MatSolve_MPIDense,0, */
801e7ca0642SLois Curfman McInnes        0,0,
80239ddd567SLois Curfman McInnes        0,0,
8038c469469SLois Curfman McInnes        0,0,
8048c469469SLois Curfman McInnes /*       MatLUFactor_MPIDense,0, */
8058aaee692SLois Curfman McInnes        0,MatTranspose_MPIDense,
80639ddd567SLois Curfman McInnes        MatGetInfo_MPIDense,0,
807096963f5SLois Curfman McInnes        MatGetDiagonal_MPIDense,0,MatNorm_MPIDense,
80839ddd567SLois Curfman McInnes        MatAssemblyBegin_MPIDense,MatAssemblyEnd_MPIDense,
8098965ea79SLois Curfman McInnes        0,
81039ddd567SLois Curfman McInnes        MatSetOption_MPIDense,MatZeroEntries_MPIDense,MatZeroRows_MPIDense,
8113b2fbd54SBarry Smith        0,0,
8128c469469SLois Curfman McInnes /*       0,MatLUFactorSymbolic_MPIDense,MatLUFactorNumeric_MPIDense, */
8138aaee692SLois Curfman McInnes        0,0,
81439ddd567SLois Curfman McInnes        MatGetSize_MPIDense,MatGetLocalSize_MPIDense,
81539ddd567SLois Curfman McInnes        MatGetOwnershipRange_MPIDense,
816ff14e315SSatish Balay        0,0, MatGetArray_MPIDense, MatRestoreArray_MPIDense,
817905e6a2fSBarry Smith        0,MatConvertSameType_MPIDense,
818b49de8d1SLois Curfman McInnes        0,0,0,0,0,
8194e220ebcSLois Curfman McInnes        0,0,MatGetValues_MPIDense,0,0,MatScale_MPIDense,
8204e220ebcSLois Curfman McInnes        0,0,0,MatGetBlockSize_MPIDense};
8218965ea79SLois Curfman McInnes 
8228965ea79SLois Curfman McInnes /*@C
82339ddd567SLois Curfman McInnes    MatCreateMPIDense - Creates a sparse parallel matrix in dense format.
8248965ea79SLois Curfman McInnes 
8258965ea79SLois Curfman McInnes    Input Parameters:
8268965ea79SLois Curfman McInnes .  comm - MPI communicator
8278965ea79SLois Curfman McInnes .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
8288965ea79SLois Curfman McInnes .  n - number of local columns (or PETSC_DECIDE to have calculated
8298965ea79SLois Curfman McInnes            if N is given)
8308965ea79SLois Curfman McInnes .  M - number of global rows (or PETSC_DECIDE to have calculated if m is given)
8318965ea79SLois Curfman McInnes .  N - number of global columns (or PETSC_DECIDE to have calculated
8328965ea79SLois Curfman McInnes            if n is given)
833b4fd4287SBarry Smith .  data - optional location of matrix data.  Set data=PETSC_NULL for PETSc
834dfc5480cSLois Curfman McInnes    to control all matrix memory allocation.
8358965ea79SLois Curfman McInnes 
8368965ea79SLois Curfman McInnes    Output Parameter:
837477f1c0bSLois Curfman McInnes .  A - the matrix
8388965ea79SLois Curfman McInnes 
8398965ea79SLois Curfman McInnes    Notes:
84039ddd567SLois Curfman McInnes    The dense format is fully compatible with standard Fortran 77
84139ddd567SLois Curfman McInnes    storage by columns.
8428965ea79SLois Curfman McInnes 
84318f449edSLois Curfman McInnes    The data input variable is intended primarily for Fortran programmers
84418f449edSLois Curfman McInnes    who wish to allocate their own matrix memory space.  Most users should
845b4fd4287SBarry Smith    set data=PETSC_NULL.
84618f449edSLois Curfman McInnes 
8478965ea79SLois Curfman McInnes    The user MUST specify either the local or global matrix dimensions
8488965ea79SLois Curfman McInnes    (possibly both).
8498965ea79SLois Curfman McInnes 
8503501a2bdSLois Curfman McInnes    Currently, the only parallel dense matrix decomposition is by rows,
8513501a2bdSLois Curfman McInnes    so that n=N and each submatrix owns all of the global columns.
8523501a2bdSLois Curfman McInnes 
85339ddd567SLois Curfman McInnes .keywords: matrix, dense, parallel
8548965ea79SLois Curfman McInnes 
85539ddd567SLois Curfman McInnes .seealso: MatCreate(), MatCreateSeqDense(), MatSetValues()
8568965ea79SLois Curfman McInnes @*/
857477f1c0bSLois Curfman McInnes int MatCreateMPIDense(MPI_Comm comm,int m,int n,int M,int N,Scalar *data,Mat *A)
8588965ea79SLois Curfman McInnes {
8598965ea79SLois Curfman McInnes   Mat          mat;
86039ddd567SLois Curfman McInnes   Mat_MPIDense *a;
86125cdf11fSBarry Smith   int          ierr, i,flg;
8628965ea79SLois Curfman McInnes 
863ed2daf61SLois Curfman McInnes   /* Note:  For now, when data is specified above, this assumes the user correctly
864ed2daf61SLois Curfman McInnes    allocates the local dense storage space.  We should add error checking. */
86518f449edSLois Curfman McInnes 
866477f1c0bSLois Curfman McInnes   *A = 0;
8670452661fSBarry Smith   PetscHeaderCreate(mat,_Mat,MAT_COOKIE,MATMPIDENSE,comm);
8688965ea79SLois Curfman McInnes   PLogObjectCreate(mat);
8690452661fSBarry Smith   mat->data       = (void *) (a = PetscNew(Mat_MPIDense)); CHKPTRQ(a);
8708965ea79SLois Curfman McInnes   PetscMemcpy(&mat->ops,&MatOps,sizeof(struct _MatOps));
87139ddd567SLois Curfman McInnes   mat->destroy    = MatDestroy_MPIDense;
87239ddd567SLois Curfman McInnes   mat->view       = MatView_MPIDense;
8738965ea79SLois Curfman McInnes   mat->factor     = 0;
87490f02eecSBarry Smith   mat->mapping    = 0;
8758965ea79SLois Curfman McInnes 
876622d7880SLois Curfman McInnes   a->factor       = 0;
8778965ea79SLois Curfman McInnes   a->insertmode   = NOT_SET_VALUES;
8788965ea79SLois Curfman McInnes   MPI_Comm_rank(comm,&a->rank);
8798965ea79SLois Curfman McInnes   MPI_Comm_size(comm,&a->size);
8808965ea79SLois Curfman McInnes 
88139ddd567SLois Curfman McInnes   if (M == PETSC_DECIDE) MPI_Allreduce(&m,&M,1,MPI_INT,MPI_SUM,comm);
8828965ea79SLois Curfman McInnes   if (m == PETSC_DECIDE) {m = M/a->size + ((M % a->size) > a->rank);}
88339ddd567SLois Curfman McInnes 
88439ddd567SLois Curfman McInnes   /* each row stores all columns */
88539ddd567SLois Curfman McInnes   if (N == PETSC_DECIDE) N = n;
886d7e8b826SBarry Smith   if (n == PETSC_DECIDE) {n = N/a->size + ((N % a->size) > a->rank);}
887d7e8b826SBarry Smith   /*  if (n != N) SETERRQ(1,"MatCreateMPIDense:For now, only n=N is supported"); */
888aca0ad90SLois Curfman McInnes   a->N = mat->N = N;
889aca0ad90SLois Curfman McInnes   a->M = mat->M = M;
890aca0ad90SLois Curfman McInnes   a->m = mat->m = m;
891aca0ad90SLois Curfman McInnes   a->n = mat->n = n;
8928965ea79SLois Curfman McInnes 
8938965ea79SLois Curfman McInnes   /* build local table of row and column ownerships */
894d7e8b826SBarry Smith   a->rowners = (int *) PetscMalloc(2*(a->size+2)*sizeof(int)); CHKPTRQ(a->rowners);
895d7e8b826SBarry Smith   a->cowners = a->rowners + a->size + 1;
8967056b6fcSBarry Smith   PLogObjectMemory(mat,2*(a->size+2)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_MPIDense));
8978965ea79SLois Curfman McInnes   MPI_Allgather(&m,1,MPI_INT,a->rowners+1,1,MPI_INT,comm);
8988965ea79SLois Curfman McInnes   a->rowners[0] = 0;
8998965ea79SLois Curfman McInnes   for ( i=2; i<=a->size; i++ ) {
9008965ea79SLois Curfman McInnes     a->rowners[i] += a->rowners[i-1];
9018965ea79SLois Curfman McInnes   }
9028965ea79SLois Curfman McInnes   a->rstart = a->rowners[a->rank];
9038965ea79SLois Curfman McInnes   a->rend   = a->rowners[a->rank+1];
904d7e8b826SBarry Smith   MPI_Allgather(&n,1,MPI_INT,a->cowners+1,1,MPI_INT,comm);
905d7e8b826SBarry Smith   a->cowners[0] = 0;
906d7e8b826SBarry Smith   for ( i=2; i<=a->size; i++ ) {
907d7e8b826SBarry Smith     a->cowners[i] += a->cowners[i-1];
908d7e8b826SBarry Smith   }
9098965ea79SLois Curfman McInnes 
91018f449edSLois Curfman McInnes   ierr = MatCreateSeqDense(MPI_COMM_SELF,m,N,data,&a->A); CHKERRQ(ierr);
9118965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->A);
9128965ea79SLois Curfman McInnes 
9138965ea79SLois Curfman McInnes   /* build cache for off array entries formed */
9148965ea79SLois Curfman McInnes   ierr = StashBuild_Private(&a->stash); CHKERRQ(ierr);
9158965ea79SLois Curfman McInnes 
9168965ea79SLois Curfman McInnes   /* stuff used for matrix vector multiply */
9178965ea79SLois Curfman McInnes   a->lvec        = 0;
9188965ea79SLois Curfman McInnes   a->Mvctx       = 0;
91939b7565bSBarry Smith   a->roworiented = 1;
9208965ea79SLois Curfman McInnes 
921477f1c0bSLois Curfman McInnes   *A = mat;
92225cdf11fSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-help",&flg); CHKERRQ(ierr);
92325cdf11fSBarry Smith   if (flg) {
9248c469469SLois Curfman McInnes     ierr = MatPrintHelp(mat); CHKERRQ(ierr);
9258c469469SLois Curfman McInnes   }
9268965ea79SLois Curfman McInnes   return 0;
9278965ea79SLois Curfman McInnes }
9288965ea79SLois Curfman McInnes 
9293d1612f7SBarry Smith static int MatConvertSameType_MPIDense(Mat A,Mat *newmat,int cpvalues)
9308965ea79SLois Curfman McInnes {
9318965ea79SLois Curfman McInnes   Mat          mat;
9323501a2bdSLois Curfman McInnes   Mat_MPIDense *a,*oldmat = (Mat_MPIDense *) A->data;
93339ddd567SLois Curfman McInnes   int          ierr;
9342ba99913SLois Curfman McInnes   FactorCtx    *factor;
9358965ea79SLois Curfman McInnes 
9368965ea79SLois Curfman McInnes   *newmat       = 0;
9370452661fSBarry Smith   PetscHeaderCreate(mat,_Mat,MAT_COOKIE,MATMPIDENSE,A->comm);
9388965ea79SLois Curfman McInnes   PLogObjectCreate(mat);
9390452661fSBarry Smith   mat->data      = (void *) (a = PetscNew(Mat_MPIDense)); CHKPTRQ(a);
9408965ea79SLois Curfman McInnes   PetscMemcpy(&mat->ops,&MatOps,sizeof(struct _MatOps));
94139ddd567SLois Curfman McInnes   mat->destroy   = MatDestroy_MPIDense;
94239ddd567SLois Curfman McInnes   mat->view      = MatView_MPIDense;
9433501a2bdSLois Curfman McInnes   mat->factor    = A->factor;
944c456f294SBarry Smith   mat->assembled = PETSC_TRUE;
9458965ea79SLois Curfman McInnes 
94644cd7ae7SLois Curfman McInnes   a->m = mat->m = oldmat->m;
94744cd7ae7SLois Curfman McInnes   a->n = mat->n = oldmat->n;
94844cd7ae7SLois Curfman McInnes   a->M = mat->M = oldmat->M;
94944cd7ae7SLois Curfman McInnes   a->N = mat->N = oldmat->N;
9502ba99913SLois Curfman McInnes   if (oldmat->factor) {
9512ba99913SLois Curfman McInnes     a->factor = (FactorCtx *) (factor = PetscNew(FactorCtx)); CHKPTRQ(factor);
9522ba99913SLois Curfman McInnes     /* copy factor contents ... add this code! */
9532ba99913SLois Curfman McInnes   } else a->factor = 0;
9548965ea79SLois Curfman McInnes 
9558965ea79SLois Curfman McInnes   a->rstart     = oldmat->rstart;
9568965ea79SLois Curfman McInnes   a->rend       = oldmat->rend;
9578965ea79SLois Curfman McInnes   a->size       = oldmat->size;
9588965ea79SLois Curfman McInnes   a->rank       = oldmat->rank;
9598965ea79SLois Curfman McInnes   a->insertmode = NOT_SET_VALUES;
9608965ea79SLois Curfman McInnes 
9610452661fSBarry Smith   a->rowners = (int *) PetscMalloc((a->size+1)*sizeof(int)); CHKPTRQ(a->rowners);
96239ddd567SLois Curfman McInnes   PLogObjectMemory(mat,(a->size+1)*sizeof(int)+sizeof(struct _Mat)+sizeof(Mat_MPIDense));
9638965ea79SLois Curfman McInnes   PetscMemcpy(a->rowners,oldmat->rowners,(a->size+1)*sizeof(int));
9648965ea79SLois Curfman McInnes   ierr = StashInitialize_Private(&a->stash); CHKERRQ(ierr);
9658965ea79SLois Curfman McInnes 
9668965ea79SLois Curfman McInnes   ierr =  VecDuplicate(oldmat->lvec,&a->lvec); CHKERRQ(ierr);
9678965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->lvec);
96855659b69SBarry Smith   ierr =  VecScatterCopy(oldmat->Mvctx,&a->Mvctx); CHKERRQ(ierr);
9698965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->Mvctx);
9708965ea79SLois Curfman McInnes   ierr =  MatConvert(oldmat->A,MATSAME,&a->A); CHKERRQ(ierr);
9718965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->A);
9728965ea79SLois Curfman McInnes   *newmat = mat;
9738965ea79SLois Curfman McInnes   return 0;
9748965ea79SLois Curfman McInnes }
9758965ea79SLois Curfman McInnes 
97677c4ece6SBarry Smith #include "sys.h"
9778965ea79SLois Curfman McInnes 
97890ace30eSBarry Smith int MatLoad_MPIDense_DenseInFile(MPI_Comm comm,int fd,int M, int N, Mat *newmat)
97990ace30eSBarry Smith {
98090ace30eSBarry Smith   int        *rowners, i,size,rank,m,rstart,rend,ierr,nz,j;
98190ace30eSBarry Smith   Scalar     *array,*vals,*vals_ptr;
98290ace30eSBarry Smith   MPI_Status status;
98390ace30eSBarry Smith 
98490ace30eSBarry Smith   MPI_Comm_rank(comm,&rank);
98590ace30eSBarry Smith   MPI_Comm_size(comm,&size);
98690ace30eSBarry Smith 
98790ace30eSBarry Smith   /* determine ownership of all rows */
98890ace30eSBarry Smith   m = M/size + ((M % size) > rank);
98990ace30eSBarry Smith   rowners = (int *) PetscMalloc((size+2)*sizeof(int)); CHKPTRQ(rowners);
99090ace30eSBarry Smith   MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);
99190ace30eSBarry Smith   rowners[0] = 0;
99290ace30eSBarry Smith   for ( i=2; i<=size; i++ ) {
99390ace30eSBarry Smith     rowners[i] += rowners[i-1];
99490ace30eSBarry Smith   }
99590ace30eSBarry Smith   rstart = rowners[rank];
99690ace30eSBarry Smith   rend   = rowners[rank+1];
99790ace30eSBarry Smith 
99890ace30eSBarry Smith   ierr = MatCreateMPIDense(comm,m,PETSC_DECIDE,M,N,PETSC_NULL,newmat);CHKERRQ(ierr);
99990ace30eSBarry Smith   ierr = MatGetArray(*newmat,&array); CHKERRQ(ierr);
100090ace30eSBarry Smith 
100190ace30eSBarry Smith   if (!rank) {
100290ace30eSBarry Smith     vals = (Scalar *) PetscMalloc( m*N*sizeof(Scalar) ); CHKPTRQ(vals);
100390ace30eSBarry Smith 
100490ace30eSBarry Smith     /* read in my part of the matrix numerical values  */
100577c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,vals,m*N,BINARY_SCALAR); CHKERRQ(ierr);
100690ace30eSBarry Smith 
100790ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
100890ace30eSBarry Smith     vals_ptr = vals;
100990ace30eSBarry Smith     for ( i=0; i<m; i++ ) {
101090ace30eSBarry Smith       for ( j=0; j<N; j++ ) {
101190ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
101290ace30eSBarry Smith       }
101390ace30eSBarry Smith     }
101490ace30eSBarry Smith 
101590ace30eSBarry Smith     /* read in other processors and ship out */
101690ace30eSBarry Smith     for ( i=1; i<size; i++ ) {
101790ace30eSBarry Smith       nz   = (rowners[i+1] - rowners[i])*N;
101877c4ece6SBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,BINARY_SCALAR); CHKERRQ(ierr);
101990ace30eSBarry Smith       MPI_Send(vals,nz,MPIU_SCALAR,i,(*newmat)->tag,comm);
102090ace30eSBarry Smith     }
102190ace30eSBarry Smith   }
102290ace30eSBarry Smith   else {
102390ace30eSBarry Smith     /* receive numeric values */
102490ace30eSBarry Smith     vals = (Scalar*) PetscMalloc( m*N*sizeof(Scalar) ); CHKPTRQ(vals);
102590ace30eSBarry Smith 
102690ace30eSBarry Smith     /* receive message of values*/
102790ace30eSBarry Smith     MPI_Recv(vals,m*N,MPIU_SCALAR,0,(*newmat)->tag,comm,&status);
102890ace30eSBarry Smith 
102990ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
103090ace30eSBarry Smith     vals_ptr = vals;
103190ace30eSBarry Smith     for ( i=0; i<m; i++ ) {
103290ace30eSBarry Smith       for ( j=0; j<N; j++ ) {
103390ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
103490ace30eSBarry Smith       }
103590ace30eSBarry Smith     }
103690ace30eSBarry Smith   }
103790ace30eSBarry Smith   PetscFree(rowners);
103890ace30eSBarry Smith   PetscFree(vals);
10396d4a8577SBarry Smith   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
10406d4a8577SBarry Smith   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
104190ace30eSBarry Smith   return 0;
104290ace30eSBarry Smith }
104390ace30eSBarry Smith 
104490ace30eSBarry Smith 
104519bcc07fSBarry Smith int MatLoad_MPIDense(Viewer viewer,MatType type,Mat *newmat)
10468965ea79SLois Curfman McInnes {
10478965ea79SLois Curfman McInnes   Mat          A;
10488965ea79SLois Curfman McInnes   int          i, nz, ierr, j,rstart, rend, fd;
10498965ea79SLois Curfman McInnes   Scalar       *vals,*svals;
105019bcc07fSBarry Smith   MPI_Comm     comm = ((PetscObject)viewer)->comm;
10518965ea79SLois Curfman McInnes   MPI_Status   status;
10528965ea79SLois Curfman McInnes   int          header[4],rank,size,*rowlengths = 0,M,N,m,*rowners,maxnz,*cols;
10538965ea79SLois Curfman McInnes   int          *ourlens,*sndcounts = 0,*procsnz = 0, *offlens,jj,*mycols,*smycols;
105419bcc07fSBarry Smith   int          tag = ((PetscObject)viewer)->tag;
10558965ea79SLois Curfman McInnes 
10568965ea79SLois Curfman McInnes   MPI_Comm_size(comm,&size); MPI_Comm_rank(comm,&rank);
10578965ea79SLois Curfman McInnes   if (!rank) {
105890ace30eSBarry Smith     ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
105977c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,(char *)header,4,BINARY_INT); CHKERRQ(ierr);
106039ddd567SLois Curfman McInnes     if (header[0] != MAT_COOKIE) SETERRQ(1,"MatLoad_MPIDenseorMPIRow:not matrix object");
10618965ea79SLois Curfman McInnes   }
10628965ea79SLois Curfman McInnes 
10638965ea79SLois Curfman McInnes   MPI_Bcast(header+1,3,MPI_INT,0,comm);
106490ace30eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
106590ace30eSBarry Smith 
106690ace30eSBarry Smith   /*
106790ace30eSBarry Smith        Handle case where matrix is stored on disk as a dense matrix
106890ace30eSBarry Smith   */
106990ace30eSBarry Smith   if (nz == MATRIX_BINARY_FORMAT_DENSE) {
107090ace30eSBarry Smith     return MatLoad_MPIDense_DenseInFile(comm,fd,M,N,newmat);
107190ace30eSBarry Smith   }
107290ace30eSBarry Smith 
10738965ea79SLois Curfman McInnes   /* determine ownership of all rows */
10748965ea79SLois Curfman McInnes   m = M/size + ((M % size) > rank);
10750452661fSBarry Smith   rowners = (int *) PetscMalloc((size+2)*sizeof(int)); CHKPTRQ(rowners);
10768965ea79SLois Curfman McInnes   MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);
10778965ea79SLois Curfman McInnes   rowners[0] = 0;
10788965ea79SLois Curfman McInnes   for ( i=2; i<=size; i++ ) {
10798965ea79SLois Curfman McInnes     rowners[i] += rowners[i-1];
10808965ea79SLois Curfman McInnes   }
10818965ea79SLois Curfman McInnes   rstart = rowners[rank];
10828965ea79SLois Curfman McInnes   rend   = rowners[rank+1];
10838965ea79SLois Curfman McInnes 
10848965ea79SLois Curfman McInnes   /* distribute row lengths to all processors */
10850452661fSBarry Smith   ourlens = (int*) PetscMalloc( 2*(rend-rstart)*sizeof(int) ); CHKPTRQ(ourlens);
10868965ea79SLois Curfman McInnes   offlens = ourlens + (rend-rstart);
10878965ea79SLois Curfman McInnes   if (!rank) {
10880452661fSBarry Smith     rowlengths = (int*) PetscMalloc( M*sizeof(int) ); CHKPTRQ(rowlengths);
108977c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,rowlengths,M,BINARY_INT); CHKERRQ(ierr);
10900452661fSBarry Smith     sndcounts = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(sndcounts);
10918965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) sndcounts[i] = rowners[i+1] - rowners[i];
10928965ea79SLois Curfman McInnes     MPI_Scatterv(rowlengths,sndcounts,rowners,MPI_INT,ourlens,rend-rstart,MPI_INT,0,comm);
10930452661fSBarry Smith     PetscFree(sndcounts);
10948965ea79SLois Curfman McInnes   }
10958965ea79SLois Curfman McInnes   else {
10968965ea79SLois Curfman McInnes     MPI_Scatterv(0,0,0,MPI_INT,ourlens,rend-rstart,MPI_INT, 0,comm);
10978965ea79SLois Curfman McInnes   }
10988965ea79SLois Curfman McInnes 
10998965ea79SLois Curfman McInnes   if (!rank) {
11008965ea79SLois Curfman McInnes     /* calculate the number of nonzeros on each processor */
11010452661fSBarry Smith     procsnz = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(procsnz);
1102cddf8d76SBarry Smith     PetscMemzero(procsnz,size*sizeof(int));
11038965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) {
11048965ea79SLois Curfman McInnes       for ( j=rowners[i]; j< rowners[i+1]; j++ ) {
11058965ea79SLois Curfman McInnes         procsnz[i] += rowlengths[j];
11068965ea79SLois Curfman McInnes       }
11078965ea79SLois Curfman McInnes     }
11080452661fSBarry Smith     PetscFree(rowlengths);
11098965ea79SLois Curfman McInnes 
11108965ea79SLois Curfman McInnes     /* determine max buffer needed and allocate it */
11118965ea79SLois Curfman McInnes     maxnz = 0;
11128965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) {
11130452661fSBarry Smith       maxnz = PetscMax(maxnz,procsnz[i]);
11148965ea79SLois Curfman McInnes     }
11150452661fSBarry Smith     cols = (int *) PetscMalloc( maxnz*sizeof(int) ); CHKPTRQ(cols);
11168965ea79SLois Curfman McInnes 
11178965ea79SLois Curfman McInnes     /* read in my part of the matrix column indices  */
11188965ea79SLois Curfman McInnes     nz = procsnz[0];
11190452661fSBarry Smith     mycols = (int *) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(mycols);
112077c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,mycols,nz,BINARY_INT); CHKERRQ(ierr);
11218965ea79SLois Curfman McInnes 
11228965ea79SLois Curfman McInnes     /* read in every one elses and ship off */
11238965ea79SLois Curfman McInnes     for ( i=1; i<size; i++ ) {
11248965ea79SLois Curfman McInnes       nz = procsnz[i];
112577c4ece6SBarry Smith       ierr = PetscBinaryRead(fd,cols,nz,BINARY_INT); CHKERRQ(ierr);
11268965ea79SLois Curfman McInnes       MPI_Send(cols,nz,MPI_INT,i,tag,comm);
11278965ea79SLois Curfman McInnes     }
11280452661fSBarry Smith     PetscFree(cols);
11298965ea79SLois Curfman McInnes   }
11308965ea79SLois Curfman McInnes   else {
11318965ea79SLois Curfman McInnes     /* determine buffer space needed for message */
11328965ea79SLois Curfman McInnes     nz = 0;
11338965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
11348965ea79SLois Curfman McInnes       nz += ourlens[i];
11358965ea79SLois Curfman McInnes     }
11360452661fSBarry Smith     mycols = (int*) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(mycols);
11378965ea79SLois Curfman McInnes 
11388965ea79SLois Curfman McInnes     /* receive message of column indices*/
11398965ea79SLois Curfman McInnes     MPI_Recv(mycols,nz,MPI_INT,0,tag,comm,&status);
11408965ea79SLois Curfman McInnes     MPI_Get_count(&status,MPI_INT,&maxnz);
114139ddd567SLois Curfman McInnes     if (maxnz != nz) SETERRQ(1,"MatLoad_MPIDenseorMPIRow:something is wrong with file");
11428965ea79SLois Curfman McInnes   }
11438965ea79SLois Curfman McInnes 
11448965ea79SLois Curfman McInnes   /* loop over local rows, determining number of off diagonal entries */
1145cddf8d76SBarry Smith   PetscMemzero(offlens,m*sizeof(int));
11468965ea79SLois Curfman McInnes   jj = 0;
11478965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
11488965ea79SLois Curfman McInnes     for ( j=0; j<ourlens[i]; j++ ) {
11498965ea79SLois Curfman McInnes       if (mycols[jj] < rstart || mycols[jj] >= rend) offlens[i]++;
11508965ea79SLois Curfman McInnes       jj++;
11518965ea79SLois Curfman McInnes     }
11528965ea79SLois Curfman McInnes   }
11538965ea79SLois Curfman McInnes 
11548965ea79SLois Curfman McInnes   /* create our matrix */
11558965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
11568965ea79SLois Curfman McInnes     ourlens[i] -= offlens[i];
11578965ea79SLois Curfman McInnes   }
1158b4fd4287SBarry Smith   ierr = MatCreateMPIDense(comm,m,PETSC_DECIDE,M,N,PETSC_NULL,newmat);CHKERRQ(ierr);
11598965ea79SLois Curfman McInnes   A = *newmat;
11608965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
11618965ea79SLois Curfman McInnes     ourlens[i] += offlens[i];
11628965ea79SLois Curfman McInnes   }
11638965ea79SLois Curfman McInnes 
11648965ea79SLois Curfman McInnes   if (!rank) {
11650452661fSBarry Smith     vals = (Scalar *) PetscMalloc( maxnz*sizeof(Scalar) ); CHKPTRQ(vals);
11668965ea79SLois Curfman McInnes 
11678965ea79SLois Curfman McInnes     /* read in my part of the matrix numerical values  */
11688965ea79SLois Curfman McInnes     nz = procsnz[0];
116977c4ece6SBarry Smith     ierr = PetscBinaryRead(fd,vals,nz,BINARY_SCALAR); CHKERRQ(ierr);
11708965ea79SLois Curfman McInnes 
11718965ea79SLois Curfman McInnes     /* insert into matrix */
11728965ea79SLois Curfman McInnes     jj      = rstart;
11738965ea79SLois Curfman McInnes     smycols = mycols;
11748965ea79SLois Curfman McInnes     svals   = vals;
11758965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
11768965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
11778965ea79SLois Curfman McInnes       smycols += ourlens[i];
11788965ea79SLois Curfman McInnes       svals   += ourlens[i];
11798965ea79SLois Curfman McInnes       jj++;
11808965ea79SLois Curfman McInnes     }
11818965ea79SLois Curfman McInnes 
11828965ea79SLois Curfman McInnes     /* read in other processors and ship out */
11838965ea79SLois Curfman McInnes     for ( i=1; i<size; i++ ) {
11848965ea79SLois Curfman McInnes       nz = procsnz[i];
118577c4ece6SBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,BINARY_SCALAR); CHKERRQ(ierr);
11868965ea79SLois Curfman McInnes       MPI_Send(vals,nz,MPIU_SCALAR,i,A->tag,comm);
11878965ea79SLois Curfman McInnes     }
11880452661fSBarry Smith     PetscFree(procsnz);
11898965ea79SLois Curfman McInnes   }
11908965ea79SLois Curfman McInnes   else {
11918965ea79SLois Curfman McInnes     /* receive numeric values */
11920452661fSBarry Smith     vals = (Scalar*) PetscMalloc( nz*sizeof(Scalar) ); CHKPTRQ(vals);
11938965ea79SLois Curfman McInnes 
11948965ea79SLois Curfman McInnes     /* receive message of values*/
11958965ea79SLois Curfman McInnes     MPI_Recv(vals,nz,MPIU_SCALAR,0,A->tag,comm,&status);
11968965ea79SLois Curfman McInnes     MPI_Get_count(&status,MPIU_SCALAR,&maxnz);
119739ddd567SLois Curfman McInnes     if (maxnz != nz) SETERRQ(1,"MatLoad_MPIDenseorMPIRow:something is wrong with file");
11988965ea79SLois Curfman McInnes 
11998965ea79SLois Curfman McInnes     /* insert into matrix */
12008965ea79SLois Curfman McInnes     jj      = rstart;
12018965ea79SLois Curfman McInnes     smycols = mycols;
12028965ea79SLois Curfman McInnes     svals   = vals;
12038965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
12048965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
12058965ea79SLois Curfman McInnes       smycols += ourlens[i];
12068965ea79SLois Curfman McInnes       svals   += ourlens[i];
12078965ea79SLois Curfman McInnes       jj++;
12088965ea79SLois Curfman McInnes     }
12098965ea79SLois Curfman McInnes   }
12100452661fSBarry Smith   PetscFree(ourlens); PetscFree(vals); PetscFree(mycols); PetscFree(rowners);
12118965ea79SLois Curfman McInnes 
12126d4a8577SBarry Smith   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
12136d4a8577SBarry Smith   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
12148965ea79SLois Curfman McInnes   return 0;
12158965ea79SLois Curfman McInnes }
121690ace30eSBarry Smith 
121790ace30eSBarry Smith 
121890ace30eSBarry Smith 
121990ace30eSBarry Smith 
122090ace30eSBarry Smith 
1221