xref: /petsc/src/mat/impls/dense/mpi/mpidense.c (revision 7ef1d9bd187294aa042bd52ec02f5579326131eb)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*7ef1d9bdSSatish Balay static char vcid[] = "$Id: mpidense.c,v 1.107 1999/03/11 22:30:12 balay Exp balay $";
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*7ef1d9bdSSatish Balay extern int MatSetUpMultiply_MPIDense(Mat);
13*7ef1d9bdSSatish Balay 
145615d1e5SSatish Balay #undef __FUNC__
155615d1e5SSatish Balay #define __FUNC__ "MatSetValues_MPIDense"
168f6be9afSLois Curfman McInnes int MatSetValues_MPIDense(Mat mat,int m,int *idxm,int n,int *idxn,Scalar *v,InsertMode addv)
178965ea79SLois Curfman McInnes {
1839b7565bSBarry Smith   Mat_MPIDense *A = (Mat_MPIDense *) mat->data;
1939b7565bSBarry Smith   int          ierr, i, j, rstart = A->rstart, rend = A->rend, row;
2039b7565bSBarry Smith   int          roworiented = A->roworiented;
218965ea79SLois Curfman McInnes 
223a40ed3dSBarry Smith   PetscFunctionBegin;
238965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
245ef9f2a5SBarry Smith     if (idxm[i] < 0) continue;
25a8c6a408SBarry Smith     if (idxm[i] >= A->M) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large");
268965ea79SLois Curfman McInnes     if (idxm[i] >= rstart && idxm[i] < rend) {
278965ea79SLois Curfman McInnes       row = idxm[i] - rstart;
2839b7565bSBarry Smith       if (roworiented) {
2939b7565bSBarry Smith         ierr = MatSetValues(A->A,1,&row,n,idxn,v+i*n,addv); CHKERRQ(ierr);
303a40ed3dSBarry Smith       } else {
318965ea79SLois Curfman McInnes         for ( j=0; j<n; j++ ) {
325ef9f2a5SBarry Smith           if (idxn[j] < 0) continue;
33a8c6a408SBarry Smith           if (idxn[j] >= A->N) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"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       }
373a40ed3dSBarry Smith     } else {
3839b7565bSBarry Smith       if (roworiented) {
39a2d1c673SSatish Balay         ierr = StashValues_Private(&A->stash,idxm[i],n,idxn,v+i*n); CHKERRQ(ierr);
403a40ed3dSBarry Smith       } else { /* must stash each seperately */
4139b7565bSBarry Smith         row = idxm[i];
4239b7565bSBarry Smith         for ( j=0; j<n; j++ ) {
43a2d1c673SSatish Balay           ierr = StashValues_Private(&A->stash,row,1,&idxn[j],v+i+j*m);CHKERRQ(ierr);
4439b7565bSBarry Smith         }
4539b7565bSBarry Smith       }
46b49de8d1SLois Curfman McInnes     }
47b49de8d1SLois Curfman McInnes   }
483a40ed3dSBarry Smith   PetscFunctionReturn(0);
49b49de8d1SLois Curfman McInnes }
50b49de8d1SLois Curfman McInnes 
515615d1e5SSatish Balay #undef __FUNC__
525615d1e5SSatish Balay #define __FUNC__ "MatGetValues_MPIDense"
538f6be9afSLois Curfman McInnes 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 
583a40ed3dSBarry Smith   PetscFunctionBegin;
59b49de8d1SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
60a8c6a408SBarry Smith     if (idxm[i] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative row");
61a8c6a408SBarry Smith     if (idxm[i] >= mdn->M) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Row too large");
62b49de8d1SLois Curfman McInnes     if (idxm[i] >= rstart && idxm[i] < rend) {
63b49de8d1SLois Curfman McInnes       row = idxm[i] - rstart;
64b49de8d1SLois Curfman McInnes       for ( j=0; j<n; j++ ) {
65a8c6a408SBarry Smith         if (idxn[j] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative column");
66a8c6a408SBarry Smith         if (idxn[j] >= mdn->N) {
67a8c6a408SBarry Smith           SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large");
68a8c6a408SBarry Smith         }
69b49de8d1SLois Curfman McInnes         ierr = MatGetValues(mdn->A,1,&row,1,&idxn[j],v+i*n+j); CHKERRQ(ierr);
70b49de8d1SLois Curfman McInnes       }
71a8c6a408SBarry Smith     } else {
72a8c6a408SBarry Smith       SETERRQ(PETSC_ERR_SUP,0,"Only local values currently supported");
738965ea79SLois Curfman McInnes     }
748965ea79SLois Curfman McInnes   }
753a40ed3dSBarry Smith   PetscFunctionReturn(0);
768965ea79SLois Curfman McInnes }
778965ea79SLois Curfman McInnes 
785615d1e5SSatish Balay #undef __FUNC__
795615d1e5SSatish Balay #define __FUNC__ "MatGetArray_MPIDense"
808f6be9afSLois Curfman McInnes int MatGetArray_MPIDense(Mat A,Scalar **array)
81ff14e315SSatish Balay {
82ff14e315SSatish Balay   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
83ff14e315SSatish Balay   int          ierr;
84ff14e315SSatish Balay 
853a40ed3dSBarry Smith   PetscFunctionBegin;
86ff14e315SSatish Balay   ierr = MatGetArray(a->A,array); CHKERRQ(ierr);
873a40ed3dSBarry Smith   PetscFunctionReturn(0);
88ff14e315SSatish Balay }
89ff14e315SSatish Balay 
905615d1e5SSatish Balay #undef __FUNC__
915615d1e5SSatish Balay #define __FUNC__ "MatRestoreArray_MPIDense"
928f6be9afSLois Curfman McInnes int MatRestoreArray_MPIDense(Mat A,Scalar **array)
93ff14e315SSatish Balay {
943a40ed3dSBarry Smith   PetscFunctionBegin;
953a40ed3dSBarry Smith   PetscFunctionReturn(0);
96ff14e315SSatish Balay }
97ff14e315SSatish Balay 
985615d1e5SSatish Balay #undef __FUNC__
995615d1e5SSatish Balay #define __FUNC__ "MatAssemblyBegin_MPIDense"
1008f6be9afSLois Curfman McInnes int MatAssemblyBegin_MPIDense(Mat mat,MatAssemblyType mode)
1018965ea79SLois Curfman McInnes {
10239ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
1038965ea79SLois Curfman McInnes   MPI_Comm     comm = mat->comm;
104*7ef1d9bdSSatish Balay   int          ierr;
1058965ea79SLois Curfman McInnes   InsertMode   addv;
1068965ea79SLois Curfman McInnes 
1073a40ed3dSBarry Smith   PetscFunctionBegin;
1088965ea79SLois Curfman McInnes   /* make sure all processors are either in INSERTMODE or ADDMODE */
109ca161407SBarry Smith   ierr = MPI_Allreduce(&mat->insertmode,&addv,1,MPI_INT,MPI_BOR,comm);CHKERRQ(ierr);
1107056b6fcSBarry Smith   if (addv == (ADD_VALUES|INSERT_VALUES)) {
111a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"Cannot mix adds/inserts on different procs");
1128965ea79SLois Curfman McInnes   }
113e0fa3b82SLois Curfman McInnes   mat->insertmode = addv; /* in case this processor had no cache */
1148965ea79SLois Curfman McInnes 
115*7ef1d9bdSSatish Balay   ierr =  StashScatterBegin_Private(&mdn->stash,mdn->rowners); CHKERRQ(ierr);
1163a40ed3dSBarry Smith   PetscFunctionReturn(0);
1178965ea79SLois Curfman McInnes }
1188965ea79SLois Curfman McInnes 
1195615d1e5SSatish Balay #undef __FUNC__
1205615d1e5SSatish Balay #define __FUNC__ "MatAssemblyEnd_MPIDense"
1218f6be9afSLois Curfman McInnes int MatAssemblyEnd_MPIDense(Mat mat,MatAssemblyType mode)
1228965ea79SLois Curfman McInnes {
12339ddd567SLois Curfman McInnes   Mat_MPIDense *mdn=(Mat_MPIDense*)mat->data;
124*7ef1d9bdSSatish Balay   int          i,n,ierr,*row,*col,flg,j,rstart,ncols;
125*7ef1d9bdSSatish Balay   Scalar       *val;
126e0fa3b82SLois Curfman McInnes   InsertMode   addv=mat->insertmode;
1278965ea79SLois Curfman McInnes 
1283a40ed3dSBarry Smith   PetscFunctionBegin;
1298965ea79SLois Curfman McInnes   /*  wait on receives */
130*7ef1d9bdSSatish Balay   while (1) {
131*7ef1d9bdSSatish Balay     ierr = StashScatterGetMesg_Private(&mdn->stash,&n,&row,&col,&val,&flg); CHKERRQ(ierr);
132*7ef1d9bdSSatish Balay     if (!flg) break;
1338965ea79SLois Curfman McInnes 
134*7ef1d9bdSSatish Balay     for ( i=0; i<n; ) {
135*7ef1d9bdSSatish Balay       /* Now identify the consecutive vals belonging to the same row */
136*7ef1d9bdSSatish Balay       for ( j=i,rstart=row[j]; j<n; j++ ) { if (row[j] != rstart) break; }
137*7ef1d9bdSSatish Balay       if (j < n) ncols = j-i;
138*7ef1d9bdSSatish Balay       else       ncols = n-i;
139*7ef1d9bdSSatish Balay       /* Now assemble all these values with a single function call */
140*7ef1d9bdSSatish Balay       ierr = MatSetValues_MPIDense(mat,1,row+i,ncols,col+i,val+i,addv); CHKERRQ(ierr);
141*7ef1d9bdSSatish Balay       i = j;
1428965ea79SLois Curfman McInnes     }
143*7ef1d9bdSSatish Balay   }
144*7ef1d9bdSSatish Balay   ierr = StashScatterEnd_Private(&mdn->stash); CHKERRQ(ierr);
1458965ea79SLois Curfman McInnes 
14639ddd567SLois Curfman McInnes   ierr = MatAssemblyBegin(mdn->A,mode); CHKERRQ(ierr);
14739ddd567SLois Curfman McInnes   ierr = MatAssemblyEnd(mdn->A,mode); CHKERRQ(ierr);
1488965ea79SLois Curfman McInnes 
1496d4a8577SBarry Smith   if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) {
15039ddd567SLois Curfman McInnes     ierr = MatSetUpMultiply_MPIDense(mat); CHKERRQ(ierr);
1518965ea79SLois Curfman McInnes   }
1523a40ed3dSBarry Smith   PetscFunctionReturn(0);
1538965ea79SLois Curfman McInnes }
1548965ea79SLois Curfman McInnes 
1555615d1e5SSatish Balay #undef __FUNC__
1565615d1e5SSatish Balay #define __FUNC__ "MatZeroEntries_MPIDense"
1578f6be9afSLois Curfman McInnes int MatZeroEntries_MPIDense(Mat A)
1588965ea79SLois Curfman McInnes {
1593a40ed3dSBarry Smith   int          ierr;
16039ddd567SLois Curfman McInnes   Mat_MPIDense *l = (Mat_MPIDense *) A->data;
1613a40ed3dSBarry Smith 
1623a40ed3dSBarry Smith   PetscFunctionBegin;
1633a40ed3dSBarry Smith   ierr = MatZeroEntries(l->A);CHKERRQ(ierr);
1643a40ed3dSBarry Smith   PetscFunctionReturn(0);
1658965ea79SLois Curfman McInnes }
1668965ea79SLois Curfman McInnes 
1675615d1e5SSatish Balay #undef __FUNC__
1685615d1e5SSatish Balay #define __FUNC__ "MatGetBlockSize_MPIDense"
1698f6be9afSLois Curfman McInnes int MatGetBlockSize_MPIDense(Mat A,int *bs)
1704e220ebcSLois Curfman McInnes {
1713a40ed3dSBarry Smith   PetscFunctionBegin;
1724e220ebcSLois Curfman McInnes   *bs = 1;
1733a40ed3dSBarry Smith   PetscFunctionReturn(0);
1744e220ebcSLois Curfman McInnes }
1754e220ebcSLois Curfman McInnes 
1768965ea79SLois Curfman McInnes /* the code does not do the diagonal entries correctly unless the
1778965ea79SLois Curfman McInnes    matrix is square and the column and row owerships are identical.
1788965ea79SLois Curfman McInnes    This is a BUG. The only way to fix it seems to be to access
1793501a2bdSLois Curfman McInnes    mdn->A and mdn->B directly and not through the MatZeroRows()
1808965ea79SLois Curfman McInnes    routine.
1818965ea79SLois Curfman McInnes */
1825615d1e5SSatish Balay #undef __FUNC__
1835615d1e5SSatish Balay #define __FUNC__ "MatZeroRows_MPIDense"
1848f6be9afSLois Curfman McInnes int MatZeroRows_MPIDense(Mat A,IS is,Scalar *diag)
1858965ea79SLois Curfman McInnes {
18639ddd567SLois Curfman McInnes   Mat_MPIDense   *l = (Mat_MPIDense *) A->data;
1878965ea79SLois Curfman McInnes   int            i,ierr,N, *rows,*owners = l->rowners,size = l->size;
1888965ea79SLois Curfman McInnes   int            *procs,*nprocs,j,found,idx,nsends,*work;
1898965ea79SLois Curfman McInnes   int            nmax,*svalues,*starts,*owner,nrecvs,rank = l->rank;
1908965ea79SLois Curfman McInnes   int            *rvalues,tag = A->tag,count,base,slen,n,*source;
1918965ea79SLois Curfman McInnes   int            *lens,imdex,*lrows,*values;
1928965ea79SLois Curfman McInnes   MPI_Comm       comm = A->comm;
1938965ea79SLois Curfman McInnes   MPI_Request    *send_waits,*recv_waits;
1948965ea79SLois Curfman McInnes   MPI_Status     recv_status,*send_status;
1958965ea79SLois Curfman McInnes   IS             istmp;
1968965ea79SLois Curfman McInnes 
1973a40ed3dSBarry Smith   PetscFunctionBegin;
19877c4ece6SBarry Smith   ierr = ISGetSize(is,&N); CHKERRQ(ierr);
1998965ea79SLois Curfman McInnes   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
2008965ea79SLois Curfman McInnes 
2018965ea79SLois Curfman McInnes   /*  first count number of contributors to each processor */
2020452661fSBarry Smith   nprocs = (int *) PetscMalloc( 2*size*sizeof(int) ); CHKPTRQ(nprocs);
203cddf8d76SBarry Smith   PetscMemzero(nprocs,2*size*sizeof(int)); procs = nprocs + size;
2040452661fSBarry Smith   owner = (int *) PetscMalloc((N+1)*sizeof(int)); CHKPTRQ(owner); /* see note*/
2058965ea79SLois Curfman McInnes   for ( i=0; i<N; i++ ) {
2068965ea79SLois Curfman McInnes     idx = rows[i];
2078965ea79SLois Curfman McInnes     found = 0;
2088965ea79SLois Curfman McInnes     for ( j=0; j<size; j++ ) {
2098965ea79SLois Curfman McInnes       if (idx >= owners[j] && idx < owners[j+1]) {
2108965ea79SLois Curfman McInnes         nprocs[j]++; procs[j] = 1; owner[i] = j; found = 1; break;
2118965ea79SLois Curfman McInnes       }
2128965ea79SLois Curfman McInnes     }
213a8c6a408SBarry Smith     if (!found) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Index out of range");
2148965ea79SLois Curfman McInnes   }
2158965ea79SLois Curfman McInnes   nsends = 0;  for ( i=0; i<size; i++ ) { nsends += procs[i];}
2168965ea79SLois Curfman McInnes 
2178965ea79SLois Curfman McInnes   /* inform other processors of number of messages and max length*/
2180452661fSBarry Smith   work   = (int *) PetscMalloc( size*sizeof(int) ); CHKPTRQ(work);
219ca161407SBarry Smith   ierr   = MPI_Allreduce( procs, work,size,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
2208965ea79SLois Curfman McInnes   nrecvs = work[rank];
221ca161407SBarry Smith   ierr   = MPI_Allreduce( nprocs, work,size,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
2228965ea79SLois Curfman McInnes   nmax   = work[rank];
2230452661fSBarry Smith   PetscFree(work);
2248965ea79SLois Curfman McInnes 
2258965ea79SLois Curfman McInnes   /* post receives:   */
2263a40ed3dSBarry Smith   rvalues    = (int *) PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(int));CHKPTRQ(rvalues);
2273a40ed3dSBarry Smith   recv_waits = (MPI_Request *) PetscMalloc((nrecvs+1)*sizeof(MPI_Request));CHKPTRQ(recv_waits);
2288965ea79SLois Curfman McInnes   for ( i=0; i<nrecvs; i++ ) {
229ca161407SBarry Smith     ierr = MPI_Irecv(rvalues+nmax*i,nmax,MPI_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr);
2308965ea79SLois Curfman McInnes   }
2318965ea79SLois Curfman McInnes 
2328965ea79SLois Curfman McInnes   /* do sends:
2338965ea79SLois Curfman McInnes       1) starts[i] gives the starting index in svalues for stuff going to
2348965ea79SLois Curfman McInnes          the ith processor
2358965ea79SLois Curfman McInnes   */
2360452661fSBarry Smith   svalues    = (int *) PetscMalloc( (N+1)*sizeof(int) ); CHKPTRQ(svalues);
2377056b6fcSBarry Smith   send_waits = (MPI_Request *) PetscMalloc((nsends+1)*sizeof(MPI_Request));CHKPTRQ(send_waits);
2380452661fSBarry Smith   starts     = (int *) PetscMalloc( (size+1)*sizeof(int) ); CHKPTRQ(starts);
2398965ea79SLois Curfman McInnes   starts[0]  = 0;
2408965ea79SLois Curfman McInnes   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
2418965ea79SLois Curfman McInnes   for ( i=0; i<N; i++ ) {
2428965ea79SLois Curfman McInnes     svalues[starts[owner[i]]++] = rows[i];
2438965ea79SLois Curfman McInnes   }
2448965ea79SLois Curfman McInnes   ISRestoreIndices(is,&rows);
2458965ea79SLois Curfman McInnes 
2468965ea79SLois Curfman McInnes   starts[0] = 0;
2478965ea79SLois Curfman McInnes   for ( i=1; i<size+1; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
2488965ea79SLois Curfman McInnes   count = 0;
2498965ea79SLois Curfman McInnes   for ( i=0; i<size; i++ ) {
2508965ea79SLois Curfman McInnes     if (procs[i]) {
251ca161407SBarry Smith       ierr = MPI_Isend(svalues+starts[i],nprocs[i],MPI_INT,i,tag,comm,send_waits+count++);CHKERRQ(ierr);
2528965ea79SLois Curfman McInnes     }
2538965ea79SLois Curfman McInnes   }
2540452661fSBarry Smith   PetscFree(starts);
2558965ea79SLois Curfman McInnes 
2568965ea79SLois Curfman McInnes   base = owners[rank];
2578965ea79SLois Curfman McInnes 
2588965ea79SLois Curfman McInnes   /*  wait on receives */
2590452661fSBarry Smith   lens   = (int *) PetscMalloc( 2*(nrecvs+1)*sizeof(int) ); CHKPTRQ(lens);
2608965ea79SLois Curfman McInnes   source = lens + nrecvs;
2618965ea79SLois Curfman McInnes   count  = nrecvs; slen = 0;
2628965ea79SLois Curfman McInnes   while (count) {
263ca161407SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
2648965ea79SLois Curfman McInnes     /* unpack receives into our local space */
265ca161407SBarry Smith     ierr = MPI_Get_count(&recv_status,MPI_INT,&n);CHKERRQ(ierr);
2668965ea79SLois Curfman McInnes     source[imdex]  = recv_status.MPI_SOURCE;
2678965ea79SLois Curfman McInnes     lens[imdex]  = n;
2688965ea79SLois Curfman McInnes     slen += n;
2698965ea79SLois Curfman McInnes     count--;
2708965ea79SLois Curfman McInnes   }
2710452661fSBarry Smith   PetscFree(recv_waits);
2728965ea79SLois Curfman McInnes 
2738965ea79SLois Curfman McInnes   /* move the data into the send scatter */
2740452661fSBarry Smith   lrows = (int *) PetscMalloc( (slen+1)*sizeof(int) ); CHKPTRQ(lrows);
2758965ea79SLois Curfman McInnes   count = 0;
2768965ea79SLois Curfman McInnes   for ( i=0; i<nrecvs; i++ ) {
2778965ea79SLois Curfman McInnes     values = rvalues + i*nmax;
2788965ea79SLois Curfman McInnes     for ( j=0; j<lens[i]; j++ ) {
2798965ea79SLois Curfman McInnes       lrows[count++] = values[j] - base;
2808965ea79SLois Curfman McInnes     }
2818965ea79SLois Curfman McInnes   }
2820452661fSBarry Smith   PetscFree(rvalues); PetscFree(lens);
2830452661fSBarry Smith   PetscFree(owner); PetscFree(nprocs);
2848965ea79SLois Curfman McInnes 
2858965ea79SLois Curfman McInnes   /* actually zap the local rows */
286029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,slen,lrows,&istmp);CHKERRQ(ierr);
2878965ea79SLois Curfman McInnes   PLogObjectParent(A,istmp);
2880452661fSBarry Smith   PetscFree(lrows);
2898965ea79SLois Curfman McInnes   ierr = MatZeroRows(l->A,istmp,diag); CHKERRQ(ierr);
2908965ea79SLois Curfman McInnes   ierr = ISDestroy(istmp); CHKERRQ(ierr);
2918965ea79SLois Curfman McInnes 
2928965ea79SLois Curfman McInnes   /* wait on sends */
2938965ea79SLois Curfman McInnes   if (nsends) {
2947056b6fcSBarry Smith     send_status = (MPI_Status *) PetscMalloc(nsends*sizeof(MPI_Status));CHKPTRQ(send_status);
295ca161407SBarry Smith     ierr        = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
2960452661fSBarry Smith     PetscFree(send_status);
2978965ea79SLois Curfman McInnes   }
2980452661fSBarry Smith   PetscFree(send_waits); PetscFree(svalues);
2998965ea79SLois Curfman McInnes 
3003a40ed3dSBarry Smith   PetscFunctionReturn(0);
3018965ea79SLois Curfman McInnes }
3028965ea79SLois Curfman McInnes 
3035615d1e5SSatish Balay #undef __FUNC__
3045615d1e5SSatish Balay #define __FUNC__ "MatMult_MPIDense"
3058f6be9afSLois Curfman McInnes int MatMult_MPIDense(Mat mat,Vec xx,Vec yy)
3068965ea79SLois Curfman McInnes {
30739ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3088965ea79SLois Curfman McInnes   int          ierr;
309c456f294SBarry Smith 
3103a40ed3dSBarry Smith   PetscFunctionBegin;
31143a90d84SBarry Smith   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
31243a90d84SBarry Smith   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
31344cd7ae7SLois Curfman McInnes   ierr = MatMult_SeqDense(mdn->A,mdn->lvec,yy); CHKERRQ(ierr);
3143a40ed3dSBarry Smith   PetscFunctionReturn(0);
3158965ea79SLois Curfman McInnes }
3168965ea79SLois Curfman McInnes 
3175615d1e5SSatish Balay #undef __FUNC__
3185615d1e5SSatish Balay #define __FUNC__ "MatMultAdd_MPIDense"
3198f6be9afSLois Curfman McInnes int MatMultAdd_MPIDense(Mat mat,Vec xx,Vec yy,Vec zz)
3208965ea79SLois Curfman McInnes {
32139ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3228965ea79SLois Curfman McInnes   int          ierr;
323c456f294SBarry Smith 
3243a40ed3dSBarry Smith   PetscFunctionBegin;
32543a90d84SBarry Smith   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
32643a90d84SBarry Smith   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
32744cd7ae7SLois Curfman McInnes   ierr = MatMultAdd_SeqDense(mdn->A,mdn->lvec,yy,zz); CHKERRQ(ierr);
3283a40ed3dSBarry Smith   PetscFunctionReturn(0);
3298965ea79SLois Curfman McInnes }
3308965ea79SLois Curfman McInnes 
3315615d1e5SSatish Balay #undef __FUNC__
3325615d1e5SSatish Balay #define __FUNC__ "MatMultTrans_MPIDense"
3338f6be9afSLois Curfman McInnes int MatMultTrans_MPIDense(Mat A,Vec xx,Vec yy)
334096963f5SLois Curfman McInnes {
335096963f5SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
336096963f5SLois Curfman McInnes   int          ierr;
3373501a2bdSLois Curfman McInnes   Scalar       zero = 0.0;
338096963f5SLois Curfman McInnes 
3393a40ed3dSBarry Smith   PetscFunctionBegin;
3403501a2bdSLois Curfman McInnes   ierr = VecSet(&zero,yy); CHKERRQ(ierr);
34144cd7ae7SLois Curfman McInnes   ierr = MatMultTrans_SeqDense(a->A,xx,a->lvec); CHKERRQ(ierr);
342537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
343537820f0SBarry Smith   ierr = VecScatterEnd(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
3443a40ed3dSBarry Smith   PetscFunctionReturn(0);
345096963f5SLois Curfman McInnes }
346096963f5SLois Curfman McInnes 
3475615d1e5SSatish Balay #undef __FUNC__
3485615d1e5SSatish Balay #define __FUNC__ "MatMultTransAdd_MPIDense"
3498f6be9afSLois Curfman McInnes int MatMultTransAdd_MPIDense(Mat A,Vec xx,Vec yy,Vec zz)
350096963f5SLois Curfman McInnes {
351096963f5SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
352096963f5SLois Curfman McInnes   int          ierr;
353096963f5SLois Curfman McInnes 
3543a40ed3dSBarry Smith   PetscFunctionBegin;
3553501a2bdSLois Curfman McInnes   ierr = VecCopy(yy,zz); CHKERRQ(ierr);
35644cd7ae7SLois Curfman McInnes   ierr = MatMultTrans_SeqDense(a->A,xx,a->lvec); CHKERRQ(ierr);
357537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
358537820f0SBarry Smith   ierr = VecScatterEnd(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
3593a40ed3dSBarry Smith   PetscFunctionReturn(0);
360096963f5SLois Curfman McInnes }
361096963f5SLois Curfman McInnes 
3625615d1e5SSatish Balay #undef __FUNC__
3635615d1e5SSatish Balay #define __FUNC__ "MatGetDiagonal_MPIDense"
3648f6be9afSLois Curfman McInnes int MatGetDiagonal_MPIDense(Mat A,Vec v)
3658965ea79SLois Curfman McInnes {
36639ddd567SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
367096963f5SLois Curfman McInnes   Mat_SeqDense *aloc = (Mat_SeqDense *) a->A->data;
36844cd7ae7SLois Curfman McInnes   int          ierr, len, i, n, m = a->m, radd;
36944cd7ae7SLois Curfman McInnes   Scalar       *x, zero = 0.0;
370ed3cc1f0SBarry Smith 
3713a40ed3dSBarry Smith   PetscFunctionBegin;
37244cd7ae7SLois Curfman McInnes   VecSet(&zero,v);
373096963f5SLois Curfman McInnes   ierr = VecGetArray(v,&x); CHKERRQ(ierr);
374096963f5SLois Curfman McInnes   ierr = VecGetSize(v,&n); CHKERRQ(ierr);
375a8c6a408SBarry Smith   if (n != a->M) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Nonconforming mat and vec");
37644cd7ae7SLois Curfman McInnes   len = PetscMin(aloc->m,aloc->n);
3777ddc982cSLois Curfman McInnes   radd = a->rstart*m;
37844cd7ae7SLois Curfman McInnes   for ( i=0; i<len; i++ ) {
379096963f5SLois Curfman McInnes     x[i] = aloc->v[radd + i*m + i];
380096963f5SLois Curfman McInnes   }
3813a40ed3dSBarry Smith   PetscFunctionReturn(0);
3828965ea79SLois Curfman McInnes }
3838965ea79SLois Curfman McInnes 
3845615d1e5SSatish Balay #undef __FUNC__
3855615d1e5SSatish Balay #define __FUNC__ "MatDestroy_MPIDense"
386e1311b90SBarry Smith int MatDestroy_MPIDense(Mat mat)
3878965ea79SLois Curfman McInnes {
3883501a2bdSLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3898965ea79SLois Curfman McInnes   int          ierr;
390ed3cc1f0SBarry Smith 
3913a40ed3dSBarry Smith   PetscFunctionBegin;
39294d884c6SBarry Smith   if (--mat->refct > 0) PetscFunctionReturn(0);
39394d884c6SBarry Smith 
39494d884c6SBarry Smith   if (mat->mapping) {
39594d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->mapping); CHKERRQ(ierr);
39694d884c6SBarry Smith   }
39794d884c6SBarry Smith   if (mat->bmapping) {
39894d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->bmapping); CHKERRQ(ierr);
39994d884c6SBarry Smith   }
4003a40ed3dSBarry Smith #if defined(USE_PETSC_LOG)
401e1311b90SBarry Smith   PLogObjectState((PetscObject)mat,"Rows=%d, Cols=%d",mdn->M,mdn->N);
4028965ea79SLois Curfman McInnes #endif
403bc5ccf88SSatish Balay   ierr = StashDestroy_Private(&mdn->stash); CHKERRQ(ierr);
4040452661fSBarry Smith   PetscFree(mdn->rowners);
4053501a2bdSLois Curfman McInnes   ierr = MatDestroy(mdn->A); CHKERRQ(ierr);
4063501a2bdSLois Curfman McInnes   if (mdn->lvec)   VecDestroy(mdn->lvec);
4073501a2bdSLois Curfman McInnes   if (mdn->Mvctx)  VecScatterDestroy(mdn->Mvctx);
408622d7880SLois Curfman McInnes   if (mdn->factor) {
409622d7880SLois Curfman McInnes     if (mdn->factor->temp)   PetscFree(mdn->factor->temp);
410622d7880SLois Curfman McInnes     if (mdn->factor->tag)    PetscFree(mdn->factor->tag);
411622d7880SLois Curfman McInnes     if (mdn->factor->pivots) PetscFree(mdn->factor->pivots);
412622d7880SLois Curfman McInnes     PetscFree(mdn->factor);
413622d7880SLois Curfman McInnes   }
4140452661fSBarry Smith   PetscFree(mdn);
41561b13de0SBarry Smith   if (mat->rmap) {
41661b13de0SBarry Smith     ierr = MapDestroy(mat->rmap);CHKERRQ(ierr);
41761b13de0SBarry Smith   }
41861b13de0SBarry Smith   if (mat->cmap) {
41961b13de0SBarry Smith     ierr = MapDestroy(mat->cmap);CHKERRQ(ierr);
42090f02eecSBarry Smith   }
4218965ea79SLois Curfman McInnes   PLogObjectDestroy(mat);
4220452661fSBarry Smith   PetscHeaderDestroy(mat);
4233a40ed3dSBarry Smith   PetscFunctionReturn(0);
4248965ea79SLois Curfman McInnes }
42539ddd567SLois Curfman McInnes 
4265615d1e5SSatish Balay #undef __FUNC__
4275615d1e5SSatish Balay #define __FUNC__ "MatView_MPIDense_Binary"
42839ddd567SLois Curfman McInnes static int MatView_MPIDense_Binary(Mat mat,Viewer viewer)
4298965ea79SLois Curfman McInnes {
43039ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
4318965ea79SLois Curfman McInnes   int          ierr;
4327056b6fcSBarry Smith 
4333a40ed3dSBarry Smith   PetscFunctionBegin;
43439ddd567SLois Curfman McInnes   if (mdn->size == 1) {
43539ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
4368965ea79SLois Curfman McInnes   }
437a8c6a408SBarry Smith   else SETERRQ(PETSC_ERR_SUP,0,"Only uniprocessor output supported");
4383a40ed3dSBarry Smith   PetscFunctionReturn(0);
4398965ea79SLois Curfman McInnes }
4408965ea79SLois Curfman McInnes 
4415615d1e5SSatish Balay #undef __FUNC__
4425615d1e5SSatish Balay #define __FUNC__ "MatView_MPIDense_ASCII"
44339ddd567SLois Curfman McInnes static int MatView_MPIDense_ASCII(Mat mat,Viewer viewer)
4448965ea79SLois Curfman McInnes {
44539ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
44677ed5343SBarry Smith   int          ierr, format, size = mdn->size, rank = mdn->rank;
4478965ea79SLois Curfman McInnes   FILE         *fd;
44819bcc07fSBarry Smith   ViewerType   vtype;
4498965ea79SLois Curfman McInnes 
4503a40ed3dSBarry Smith   PetscFunctionBegin;
4513a40ed3dSBarry Smith   ierr = ViewerGetType(viewer,&vtype);CHKERRQ(ierr);
45290ace30eSBarry Smith   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
45390ace30eSBarry Smith   ierr = ViewerGetFormat(viewer,&format);
454639f9d9dSBarry Smith   if (format == VIEWER_FORMAT_ASCII_INFO_LONG) {
4554e220ebcSLois Curfman McInnes     MatInfo info;
4564e220ebcSLois Curfman McInnes     ierr = MatGetInfo(mat,MAT_LOCAL,&info);
45777c4ece6SBarry Smith     PetscSequentialPhaseBegin(mat->comm,1);
4584e220ebcSLois Curfman McInnes       fprintf(fd,"  [%d] local rows %d nz %d nz alloced %d mem %d \n",rank,mdn->m,
4594e220ebcSLois Curfman McInnes          (int)info.nz_used,(int)info.nz_allocated,(int)info.memory);
460096963f5SLois Curfman McInnes       fflush(fd);
46177c4ece6SBarry Smith     PetscSequentialPhaseEnd(mat->comm,1);
4623501a2bdSLois Curfman McInnes     ierr = VecScatterView(mdn->Mvctx,viewer); CHKERRQ(ierr);
4633a40ed3dSBarry Smith     PetscFunctionReturn(0);
46496f6c058SBarry Smith   } else if (format == VIEWER_FORMAT_ASCII_INFO) {
4653a40ed3dSBarry Smith     PetscFunctionReturn(0);
4668965ea79SLois Curfman McInnes   }
46777ed5343SBarry Smith 
4688965ea79SLois Curfman McInnes   if (size == 1) {
46939ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
4703a40ed3dSBarry Smith   } else {
4718965ea79SLois Curfman McInnes     /* assemble the entire matrix onto first processor. */
4728965ea79SLois Curfman McInnes     Mat          A;
47339ddd567SLois Curfman McInnes     int          M = mdn->M, N = mdn->N,m,row,i, nz, *cols;
47439ddd567SLois Curfman McInnes     Scalar       *vals;
47539ddd567SLois Curfman McInnes     Mat_SeqDense *Amdn = (Mat_SeqDense*) mdn->A->data;
4768965ea79SLois Curfman McInnes 
4778965ea79SLois Curfman McInnes     if (!rank) {
4780513a670SBarry Smith       ierr = MatCreateMPIDense(mat->comm,M,N,M,N,PETSC_NULL,&A); CHKERRQ(ierr);
4793a40ed3dSBarry Smith     } else {
4800513a670SBarry Smith       ierr = MatCreateMPIDense(mat->comm,0,N,M,N,PETSC_NULL,&A); CHKERRQ(ierr);
4818965ea79SLois Curfman McInnes     }
4828965ea79SLois Curfman McInnes     PLogObjectParent(mat,A);
4838965ea79SLois Curfman McInnes 
48439ddd567SLois Curfman McInnes     /* Copy the matrix ... This isn't the most efficient means,
48539ddd567SLois Curfman McInnes        but it's quick for now */
48639ddd567SLois Curfman McInnes     row = mdn->rstart; m = Amdn->m;
4878965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
48839ddd567SLois Curfman McInnes       ierr = MatGetRow(mat,row,&nz,&cols,&vals); CHKERRQ(ierr);
48939ddd567SLois Curfman McInnes       ierr = MatSetValues(A,1,&row,nz,cols,vals,INSERT_VALUES); CHKERRQ(ierr);
49039ddd567SLois Curfman McInnes       ierr = MatRestoreRow(mat,row,&nz,&cols,&vals); CHKERRQ(ierr);
49139ddd567SLois Curfman McInnes       row++;
4928965ea79SLois Curfman McInnes     }
4938965ea79SLois Curfman McInnes 
4946d4a8577SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4956d4a8577SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4968965ea79SLois Curfman McInnes     if (!rank) {
49739ddd567SLois Curfman McInnes       ierr = MatView(((Mat_MPIDense*)(A->data))->A,viewer); CHKERRQ(ierr);
4988965ea79SLois Curfman McInnes     }
4998965ea79SLois Curfman McInnes     ierr = MatDestroy(A); CHKERRQ(ierr);
5008965ea79SLois Curfman McInnes   }
5013a40ed3dSBarry Smith   PetscFunctionReturn(0);
5028965ea79SLois Curfman McInnes }
5038965ea79SLois Curfman McInnes 
5045615d1e5SSatish Balay #undef __FUNC__
5055615d1e5SSatish Balay #define __FUNC__ "MatView_MPIDense"
506e1311b90SBarry Smith int MatView_MPIDense(Mat mat,Viewer viewer)
5078965ea79SLois Curfman McInnes {
50839ddd567SLois Curfman McInnes   int          ierr;
509bcd2baecSBarry Smith   ViewerType   vtype;
5108965ea79SLois Curfman McInnes 
511bcd2baecSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
5123f1db9ecSBarry Smith   if (PetscTypeCompare(vtype,ASCII_VIEWER)) {
51339ddd567SLois Curfman McInnes     ierr = MatView_MPIDense_ASCII(mat,viewer); CHKERRQ(ierr);
5143f1db9ecSBarry Smith   } else if (PetscTypeCompare(vtype,BINARY_VIEWER)) {
5153a40ed3dSBarry Smith     ierr = MatView_MPIDense_Binary(mat,viewer);CHKERRQ(ierr);
5165cd90555SBarry Smith   } else {
5175cd90555SBarry Smith     SETERRQ(1,1,"Viewer type not supported by PETSc object");
5188965ea79SLois Curfman McInnes   }
5193a40ed3dSBarry Smith   PetscFunctionReturn(0);
5208965ea79SLois Curfman McInnes }
5218965ea79SLois Curfman McInnes 
5225615d1e5SSatish Balay #undef __FUNC__
5235615d1e5SSatish Balay #define __FUNC__ "MatGetInfo_MPIDense"
5248f6be9afSLois Curfman McInnes int MatGetInfo_MPIDense(Mat A,MatInfoType flag,MatInfo *info)
5258965ea79SLois Curfman McInnes {
5263501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
5273501a2bdSLois Curfman McInnes   Mat          mdn = mat->A;
5284e220ebcSLois Curfman McInnes   int          ierr;
5294e220ebcSLois Curfman McInnes   double       isend[5], irecv[5];
5308965ea79SLois Curfman McInnes 
5313a40ed3dSBarry Smith   PetscFunctionBegin;
5324e220ebcSLois Curfman McInnes   info->rows_global    = (double)mat->M;
5334e220ebcSLois Curfman McInnes   info->columns_global = (double)mat->N;
5344e220ebcSLois Curfman McInnes   info->rows_local     = (double)mat->m;
5354e220ebcSLois Curfman McInnes   info->columns_local  = (double)mat->N;
5364e220ebcSLois Curfman McInnes   info->block_size     = 1.0;
5374e220ebcSLois Curfman McInnes   ierr = MatGetInfo(mdn,MAT_LOCAL,info); CHKERRQ(ierr);
5384e220ebcSLois Curfman McInnes   isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded;
5394e220ebcSLois Curfman McInnes   isend[3] = info->memory;  isend[4] = info->mallocs;
5408965ea79SLois Curfman McInnes   if (flag == MAT_LOCAL) {
5414e220ebcSLois Curfman McInnes     info->nz_used      = isend[0];
5424e220ebcSLois Curfman McInnes     info->nz_allocated = isend[1];
5434e220ebcSLois Curfman McInnes     info->nz_unneeded  = isend[2];
5444e220ebcSLois Curfman McInnes     info->memory       = isend[3];
5454e220ebcSLois Curfman McInnes     info->mallocs      = isend[4];
5468965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_MAX) {
547f7cdd7c9SBarry Smith     ierr = MPI_Allreduce(isend,irecv,5,MPI_DOUBLE,MPI_MAX,A->comm);CHKERRQ(ierr);
5484e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
5494e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
5504e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
5514e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
5524e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
5538965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_SUM) {
554f7cdd7c9SBarry Smith     ierr = MPI_Allreduce(isend,irecv,5,MPI_DOUBLE,MPI_SUM,A->comm);CHKERRQ(ierr);
5554e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
5564e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
5574e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
5584e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
5594e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
5608965ea79SLois Curfman McInnes   }
5614e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0; /* no parallel LU/ILU/Cholesky */
5624e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
5634e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
5643a40ed3dSBarry Smith   PetscFunctionReturn(0);
5658965ea79SLois Curfman McInnes }
5668965ea79SLois Curfman McInnes 
5678c469469SLois Curfman McInnes /* extern int MatLUFactorSymbolic_MPIDense(Mat,IS,IS,double,Mat*);
5688aaee692SLois Curfman McInnes    extern int MatLUFactorNumeric_MPIDense(Mat,Mat*);
5698aaee692SLois Curfman McInnes    extern int MatLUFactor_MPIDense(Mat,IS,IS,double);
5708aaee692SLois Curfman McInnes    extern int MatSolve_MPIDense(Mat,Vec,Vec);
5718c469469SLois Curfman McInnes    extern int MatSolveAdd_MPIDense(Mat,Vec,Vec,Vec);
5728aaee692SLois Curfman McInnes    extern int MatSolveTrans_MPIDense(Mat,Vec,Vec);
5738aaee692SLois Curfman McInnes    extern int MatSolveTransAdd_MPIDense(Mat,Vec,Vec,Vec); */
5748aaee692SLois Curfman McInnes 
5755615d1e5SSatish Balay #undef __FUNC__
5765615d1e5SSatish Balay #define __FUNC__ "MatSetOption_MPIDense"
5778f6be9afSLois Curfman McInnes int MatSetOption_MPIDense(Mat A,MatOption op)
5788965ea79SLois Curfman McInnes {
57939ddd567SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
5808965ea79SLois Curfman McInnes 
5813a40ed3dSBarry Smith   PetscFunctionBegin;
5826d4a8577SBarry Smith   if (op == MAT_NO_NEW_NONZERO_LOCATIONS ||
5836d4a8577SBarry Smith       op == MAT_YES_NEW_NONZERO_LOCATIONS ||
5844787f768SSatish Balay       op == MAT_NEW_NONZERO_LOCATION_ERR ||
5854787f768SSatish Balay       op == MAT_NEW_NONZERO_ALLOCATION_ERR ||
586219d9a1aSLois Curfman McInnes       op == MAT_COLUMNS_SORTED ||
587219d9a1aSLois Curfman McInnes       op == MAT_COLUMNS_UNSORTED) {
588b1fbbac0SLois Curfman McInnes         MatSetOption(a->A,op);
589b1fbbac0SLois Curfman McInnes   } else if (op == MAT_ROW_ORIENTED) {
590aeafbbfcSLois Curfman McInnes         a->roworiented = 1;
5918965ea79SLois Curfman McInnes         MatSetOption(a->A,op);
592b1fbbac0SLois Curfman McInnes   } else if (op == MAT_ROWS_SORTED ||
593219d9a1aSLois Curfman McInnes              op == MAT_ROWS_UNSORTED ||
5946d4a8577SBarry Smith              op == MAT_SYMMETRIC ||
5956d4a8577SBarry Smith              op == MAT_STRUCTURALLY_SYMMETRIC ||
596b51ba29fSSatish Balay              op == MAT_YES_NEW_DIAGONALS ||
597b51ba29fSSatish Balay              op == MAT_USE_HASH_TABLE) {
598981c4779SBarry Smith     PLogInfo(A,"MatSetOption_MPIDense:Option ignored\n");
5993a40ed3dSBarry Smith   } else if (op == MAT_COLUMN_ORIENTED) {
6003a40ed3dSBarry Smith     a->roworiented = 0; MatSetOption(a->A,op);
6013a40ed3dSBarry Smith   } else if (op == MAT_NO_NEW_DIAGONALS) {
6023a40ed3dSBarry Smith     SETERRQ(PETSC_ERR_SUP,0,"MAT_NO_NEW_DIAGONALS");
6033a40ed3dSBarry Smith   } else {
6043a40ed3dSBarry Smith     SETERRQ(PETSC_ERR_SUP,0,"unknown option");
6053a40ed3dSBarry Smith   }
6063a40ed3dSBarry Smith   PetscFunctionReturn(0);
6078965ea79SLois Curfman McInnes }
6088965ea79SLois Curfman McInnes 
6095615d1e5SSatish Balay #undef __FUNC__
6105615d1e5SSatish Balay #define __FUNC__ "MatGetSize_MPIDense"
6118f6be9afSLois Curfman McInnes int MatGetSize_MPIDense(Mat A,int *m,int *n)
6128965ea79SLois Curfman McInnes {
6133501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6143a40ed3dSBarry Smith 
6153a40ed3dSBarry Smith   PetscFunctionBegin;
6168965ea79SLois Curfman McInnes   *m = mat->M; *n = mat->N;
6173a40ed3dSBarry Smith   PetscFunctionReturn(0);
6188965ea79SLois Curfman McInnes }
6198965ea79SLois Curfman McInnes 
6205615d1e5SSatish Balay #undef __FUNC__
6215615d1e5SSatish Balay #define __FUNC__ "MatGetLocalSize_MPIDense"
6228f6be9afSLois Curfman McInnes int MatGetLocalSize_MPIDense(Mat A,int *m,int *n)
6238965ea79SLois Curfman McInnes {
6243501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6253a40ed3dSBarry Smith 
6263a40ed3dSBarry Smith   PetscFunctionBegin;
6278965ea79SLois Curfman McInnes   *m = mat->m; *n = mat->N;
6283a40ed3dSBarry Smith   PetscFunctionReturn(0);
6298965ea79SLois Curfman McInnes }
6308965ea79SLois Curfman McInnes 
6315615d1e5SSatish Balay #undef __FUNC__
6325615d1e5SSatish Balay #define __FUNC__ "MatGetOwnershipRange_MPIDense"
6338f6be9afSLois Curfman McInnes int MatGetOwnershipRange_MPIDense(Mat A,int *m,int *n)
6348965ea79SLois Curfman McInnes {
6353501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6363a40ed3dSBarry Smith 
6373a40ed3dSBarry Smith   PetscFunctionBegin;
6388965ea79SLois Curfman McInnes   *m = mat->rstart; *n = mat->rend;
6393a40ed3dSBarry Smith   PetscFunctionReturn(0);
6408965ea79SLois Curfman McInnes }
6418965ea79SLois Curfman McInnes 
6425615d1e5SSatish Balay #undef __FUNC__
6435615d1e5SSatish Balay #define __FUNC__ "MatGetRow_MPIDense"
6448f6be9afSLois Curfman McInnes int MatGetRow_MPIDense(Mat A,int row,int *nz,int **idx,Scalar **v)
6458965ea79SLois Curfman McInnes {
6463501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6473a40ed3dSBarry Smith   int          lrow, rstart = mat->rstart, rend = mat->rend,ierr;
6488965ea79SLois Curfman McInnes 
6493a40ed3dSBarry Smith   PetscFunctionBegin;
650a8c6a408SBarry Smith   if (row < rstart || row >= rend) SETERRQ(PETSC_ERR_SUP,0,"only local rows")
6518965ea79SLois Curfman McInnes   lrow = row - rstart;
6523a40ed3dSBarry Smith   ierr = MatGetRow(mat->A,lrow,nz,idx,v);CHKERRQ(ierr);
6533a40ed3dSBarry Smith   PetscFunctionReturn(0);
6548965ea79SLois Curfman McInnes }
6558965ea79SLois Curfman McInnes 
6565615d1e5SSatish Balay #undef __FUNC__
6575615d1e5SSatish Balay #define __FUNC__ "MatRestoreRow_MPIDense"
6588f6be9afSLois Curfman McInnes int MatRestoreRow_MPIDense(Mat mat,int row,int *nz,int **idx,Scalar **v)
6598965ea79SLois Curfman McInnes {
6603a40ed3dSBarry Smith   PetscFunctionBegin;
6610452661fSBarry Smith   if (idx) PetscFree(*idx);
6620452661fSBarry Smith   if (v) PetscFree(*v);
6633a40ed3dSBarry Smith   PetscFunctionReturn(0);
6648965ea79SLois Curfman McInnes }
6658965ea79SLois Curfman McInnes 
6665615d1e5SSatish Balay #undef __FUNC__
6675615d1e5SSatish Balay #define __FUNC__ "MatNorm_MPIDense"
6688f6be9afSLois Curfman McInnes int MatNorm_MPIDense(Mat A,NormType type,double *norm)
669096963f5SLois Curfman McInnes {
6703501a2bdSLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) A->data;
6713501a2bdSLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense*) mdn->A->data;
6723501a2bdSLois Curfman McInnes   int          ierr, i, j;
6733501a2bdSLois Curfman McInnes   double       sum = 0.0;
6743501a2bdSLois Curfman McInnes   Scalar       *v = mat->v;
6753501a2bdSLois Curfman McInnes 
6763a40ed3dSBarry Smith   PetscFunctionBegin;
6773501a2bdSLois Curfman McInnes   if (mdn->size == 1) {
6783501a2bdSLois Curfman McInnes     ierr =  MatNorm(mdn->A,type,norm); CHKERRQ(ierr);
6793501a2bdSLois Curfman McInnes   } else {
6803501a2bdSLois Curfman McInnes     if (type == NORM_FROBENIUS) {
6813501a2bdSLois Curfman McInnes       for (i=0; i<mat->n*mat->m; i++ ) {
6823a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
683e20fef11SSatish Balay         sum += PetscReal(PetscConj(*v)*(*v)); v++;
6843501a2bdSLois Curfman McInnes #else
6853501a2bdSLois Curfman McInnes         sum += (*v)*(*v); v++;
6863501a2bdSLois Curfman McInnes #endif
6873501a2bdSLois Curfman McInnes       }
688ca161407SBarry Smith       ierr = MPI_Allreduce(&sum,norm,1,MPI_DOUBLE,MPI_SUM,A->comm);CHKERRQ(ierr);
6893501a2bdSLois Curfman McInnes       *norm = sqrt(*norm);
6903501a2bdSLois Curfman McInnes       PLogFlops(2*mat->n*mat->m);
6913a40ed3dSBarry Smith     } else if (type == NORM_1) {
6923501a2bdSLois Curfman McInnes       double *tmp, *tmp2;
6930452661fSBarry Smith       tmp  = (double *) PetscMalloc( 2*mdn->N*sizeof(double) ); CHKPTRQ(tmp);
6943501a2bdSLois Curfman McInnes       tmp2 = tmp + mdn->N;
695cddf8d76SBarry Smith       PetscMemzero(tmp,2*mdn->N*sizeof(double));
696096963f5SLois Curfman McInnes       *norm = 0.0;
6973501a2bdSLois Curfman McInnes       v = mat->v;
6983501a2bdSLois Curfman McInnes       for ( j=0; j<mat->n; j++ ) {
6993501a2bdSLois Curfman McInnes         for ( i=0; i<mat->m; i++ ) {
70067e560aaSBarry Smith           tmp[j] += PetscAbsScalar(*v);  v++;
7013501a2bdSLois Curfman McInnes         }
7023501a2bdSLois Curfman McInnes       }
703ca161407SBarry Smith       ierr = MPI_Allreduce(tmp,tmp2,mdn->N,MPI_DOUBLE,MPI_SUM,A->comm);CHKERRQ(ierr);
7043501a2bdSLois Curfman McInnes       for ( j=0; j<mdn->N; j++ ) {
7053501a2bdSLois Curfman McInnes         if (tmp2[j] > *norm) *norm = tmp2[j];
7063501a2bdSLois Curfman McInnes       }
7070452661fSBarry Smith       PetscFree(tmp);
7083501a2bdSLois Curfman McInnes       PLogFlops(mat->n*mat->m);
7093a40ed3dSBarry Smith     } else if (type == NORM_INFINITY) { /* max row norm */
7103501a2bdSLois Curfman McInnes       double ntemp;
7113501a2bdSLois Curfman McInnes       ierr = MatNorm(mdn->A,type,&ntemp); CHKERRQ(ierr);
712ca161407SBarry Smith       ierr = MPI_Allreduce(&ntemp,norm,1,MPI_DOUBLE,MPI_MAX,A->comm);CHKERRQ(ierr);
7133a40ed3dSBarry Smith     } else {
714a8c6a408SBarry Smith       SETERRQ(PETSC_ERR_SUP,0,"No support for two norm");
7153501a2bdSLois Curfman McInnes     }
7163501a2bdSLois Curfman McInnes   }
7173a40ed3dSBarry Smith   PetscFunctionReturn(0);
7183501a2bdSLois Curfman McInnes }
7193501a2bdSLois Curfman McInnes 
7205615d1e5SSatish Balay #undef __FUNC__
7215615d1e5SSatish Balay #define __FUNC__ "MatTranspose_MPIDense"
7228f6be9afSLois Curfman McInnes int MatTranspose_MPIDense(Mat A,Mat *matout)
7233501a2bdSLois Curfman McInnes {
7243501a2bdSLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
7253501a2bdSLois Curfman McInnes   Mat_SeqDense *Aloc = (Mat_SeqDense *) a->A->data;
7263501a2bdSLois Curfman McInnes   Mat          B;
7273501a2bdSLois Curfman McInnes   int          M = a->M, N = a->N, m, n, *rwork, rstart = a->rstart;
7283501a2bdSLois Curfman McInnes   int          j, i, ierr;
7293501a2bdSLois Curfman McInnes   Scalar       *v;
7303501a2bdSLois Curfman McInnes 
7313a40ed3dSBarry Smith   PetscFunctionBegin;
7327056b6fcSBarry Smith   if (matout == PETSC_NULL && M != N) {
733a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_SUP,0,"Supports square matrix only in-place");
7347056b6fcSBarry Smith   }
7357056b6fcSBarry Smith   ierr = MatCreateMPIDense(A->comm,PETSC_DECIDE,PETSC_DECIDE,N,M,PETSC_NULL,&B);CHKERRQ(ierr);
7363501a2bdSLois Curfman McInnes 
7373501a2bdSLois Curfman McInnes   m = Aloc->m; n = Aloc->n; v = Aloc->v;
7380452661fSBarry Smith   rwork = (int *) PetscMalloc(n*sizeof(int)); CHKPTRQ(rwork);
7393501a2bdSLois Curfman McInnes   for ( j=0; j<n; j++ ) {
7403501a2bdSLois Curfman McInnes     for (i=0; i<m; i++) rwork[i] = rstart + i;
7413501a2bdSLois Curfman McInnes     ierr = MatSetValues(B,1,&j,m,rwork,v,INSERT_VALUES); CHKERRQ(ierr);
7423501a2bdSLois Curfman McInnes     v   += m;
7433501a2bdSLois Curfman McInnes   }
7440452661fSBarry Smith   PetscFree(rwork);
7456d4a8577SBarry Smith   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
7466d4a8577SBarry Smith   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
7473638b69dSLois Curfman McInnes   if (matout != PETSC_NULL) {
7483501a2bdSLois Curfman McInnes     *matout = B;
7493501a2bdSLois Curfman McInnes   } else {
750f830108cSBarry Smith     PetscOps *Abops;
75109dc0095SBarry Smith     MatOps   Aops;
752f830108cSBarry Smith 
7533501a2bdSLois Curfman McInnes     /* This isn't really an in-place transpose, but free data struct from a */
7540452661fSBarry Smith     PetscFree(a->rowners);
7553501a2bdSLois Curfman McInnes     ierr = MatDestroy(a->A); CHKERRQ(ierr);
7563501a2bdSLois Curfman McInnes     if (a->lvec) VecDestroy(a->lvec);
7573501a2bdSLois Curfman McInnes     if (a->Mvctx) VecScatterDestroy(a->Mvctx);
7580452661fSBarry Smith     PetscFree(a);
759f830108cSBarry Smith 
760f830108cSBarry Smith     /*
761f830108cSBarry Smith          This is horrible, horrible code. We need to keep the
762f830108cSBarry Smith       A pointers for the bops and ops but copy everything
763f830108cSBarry Smith       else from C.
764f830108cSBarry Smith     */
765f830108cSBarry Smith     Abops = A->bops;
766f830108cSBarry Smith     Aops  = A->ops;
767f09e8eb9SSatish Balay     PetscMemcpy(A,B,sizeof(struct _p_Mat));
768f830108cSBarry Smith     A->bops = Abops;
769f830108cSBarry Smith     A->ops  = Aops;
770f830108cSBarry Smith 
7710452661fSBarry Smith     PetscHeaderDestroy(B);
7723501a2bdSLois Curfman McInnes   }
7733a40ed3dSBarry Smith   PetscFunctionReturn(0);
774096963f5SLois Curfman McInnes }
775096963f5SLois Curfman McInnes 
776eadb2fb4SBarry Smith #include "pinclude/blaslapack.h"
7775615d1e5SSatish Balay #undef __FUNC__
7785615d1e5SSatish Balay #define __FUNC__ "MatScale_MPIDense"
7798f6be9afSLois Curfman McInnes int MatScale_MPIDense(Scalar *alpha,Mat inA)
78044cd7ae7SLois Curfman McInnes {
78144cd7ae7SLois Curfman McInnes   Mat_MPIDense *A = (Mat_MPIDense *) inA->data;
78244cd7ae7SLois Curfman McInnes   Mat_SeqDense *a = (Mat_SeqDense *) A->A->data;
78344cd7ae7SLois Curfman McInnes   int          one = 1, nz;
78444cd7ae7SLois Curfman McInnes 
7853a40ed3dSBarry Smith   PetscFunctionBegin;
78644cd7ae7SLois Curfman McInnes   nz = a->m*a->n;
78744cd7ae7SLois Curfman McInnes   BLscal_( &nz, alpha, a->v, &one );
78844cd7ae7SLois Curfman McInnes   PLogFlops(nz);
7893a40ed3dSBarry Smith   PetscFunctionReturn(0);
79044cd7ae7SLois Curfman McInnes }
79144cd7ae7SLois Curfman McInnes 
7925609ef8eSBarry Smith static int MatDuplicate_MPIDense(Mat,MatDuplicateOption,Mat *);
7937b2a1423SBarry Smith extern int MatGetSubMatrices_MPIDense(Mat,int,IS *,IS *,MatReuse,Mat **);
7948965ea79SLois Curfman McInnes 
7958965ea79SLois Curfman McInnes /* -------------------------------------------------------------------*/
79609dc0095SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_MPIDense,
79709dc0095SBarry Smith        MatGetRow_MPIDense,
79809dc0095SBarry Smith        MatRestoreRow_MPIDense,
79909dc0095SBarry Smith        MatMult_MPIDense,
80009dc0095SBarry Smith        MatMultAdd_MPIDense,
80109dc0095SBarry Smith        MatMultTrans_MPIDense,
80209dc0095SBarry Smith        MatMultTransAdd_MPIDense,
8038965ea79SLois Curfman McInnes        0,
80409dc0095SBarry Smith        0,
80509dc0095SBarry Smith        0,
80609dc0095SBarry Smith        0,
80709dc0095SBarry Smith        0,
80809dc0095SBarry Smith        0,
80909dc0095SBarry Smith        0,
81009dc0095SBarry Smith        MatTranspose_MPIDense,
81109dc0095SBarry Smith        MatGetInfo_MPIDense,0,
81209dc0095SBarry Smith        MatGetDiagonal_MPIDense,
81309dc0095SBarry Smith        0,
81409dc0095SBarry Smith        MatNorm_MPIDense,
81509dc0095SBarry Smith        MatAssemblyBegin_MPIDense,
81609dc0095SBarry Smith        MatAssemblyEnd_MPIDense,
81709dc0095SBarry Smith        0,
81809dc0095SBarry Smith        MatSetOption_MPIDense,
81909dc0095SBarry Smith        MatZeroEntries_MPIDense,
82009dc0095SBarry Smith        MatZeroRows_MPIDense,
82109dc0095SBarry Smith        0,
82209dc0095SBarry Smith        0,
82309dc0095SBarry Smith        0,
82409dc0095SBarry Smith        0,
82509dc0095SBarry Smith        MatGetSize_MPIDense,
82609dc0095SBarry Smith        MatGetLocalSize_MPIDense,
82739ddd567SLois Curfman McInnes        MatGetOwnershipRange_MPIDense,
82809dc0095SBarry Smith        0,
82909dc0095SBarry Smith        0,
83009dc0095SBarry Smith        MatGetArray_MPIDense,
83109dc0095SBarry Smith        MatRestoreArray_MPIDense,
8325609ef8eSBarry Smith        MatDuplicate_MPIDense,
83309dc0095SBarry Smith        0,
83409dc0095SBarry Smith        0,
83509dc0095SBarry Smith        0,
83609dc0095SBarry Smith        0,
83709dc0095SBarry Smith        0,
8382ce60cd0SSatish Balay        MatGetSubMatrices_MPIDense,
83909dc0095SBarry Smith        0,
84009dc0095SBarry Smith        MatGetValues_MPIDense,
84109dc0095SBarry Smith        0,
84209dc0095SBarry Smith        0,
84309dc0095SBarry Smith        MatScale_MPIDense,
84409dc0095SBarry Smith        0,
84509dc0095SBarry Smith        0,
84609dc0095SBarry Smith        0,
84709dc0095SBarry Smith        MatGetBlockSize_MPIDense,
84809dc0095SBarry Smith        0,
84909dc0095SBarry Smith        0,
85009dc0095SBarry Smith        0,
85109dc0095SBarry Smith        0,
85209dc0095SBarry Smith        0,
85309dc0095SBarry Smith        0,
85409dc0095SBarry Smith        0,
85509dc0095SBarry Smith        0,
85609dc0095SBarry Smith        0,
85709dc0095SBarry Smith        0,
85809dc0095SBarry Smith        0,
85909dc0095SBarry Smith        0,
86009dc0095SBarry Smith        MatGetMaps_Petsc};
8618965ea79SLois Curfman McInnes 
8625615d1e5SSatish Balay #undef __FUNC__
8635615d1e5SSatish Balay #define __FUNC__ "MatCreateMPIDense"
8648965ea79SLois Curfman McInnes /*@C
86539ddd567SLois Curfman McInnes    MatCreateMPIDense - Creates a sparse parallel matrix in dense format.
8668965ea79SLois Curfman McInnes 
867db81eaa0SLois Curfman McInnes    Collective on MPI_Comm
868db81eaa0SLois Curfman McInnes 
8698965ea79SLois Curfman McInnes    Input Parameters:
870db81eaa0SLois Curfman McInnes +  comm - MPI communicator
8718965ea79SLois Curfman McInnes .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
872db81eaa0SLois Curfman McInnes .  n - number of local columns (or PETSC_DECIDE to have calculated if N is given)
8738965ea79SLois Curfman McInnes .  M - number of global rows (or PETSC_DECIDE to have calculated if m is given)
874db81eaa0SLois Curfman McInnes .  N - number of global columns (or PETSC_DECIDE to have calculated if n is given)
875db81eaa0SLois Curfman McInnes -  data - optional location of matrix data.  Set data=PETSC_NULL for PETSc
876dfc5480cSLois Curfman McInnes    to control all matrix memory allocation.
8778965ea79SLois Curfman McInnes 
8788965ea79SLois Curfman McInnes    Output Parameter:
879477f1c0bSLois Curfman McInnes .  A - the matrix
8808965ea79SLois Curfman McInnes 
881b259b22eSLois Curfman McInnes    Notes:
88239ddd567SLois Curfman McInnes    The dense format is fully compatible with standard Fortran 77
88339ddd567SLois Curfman McInnes    storage by columns.
8848965ea79SLois Curfman McInnes 
88518f449edSLois Curfman McInnes    The data input variable is intended primarily for Fortran programmers
88618f449edSLois Curfman McInnes    who wish to allocate their own matrix memory space.  Most users should
887b4fd4287SBarry Smith    set data=PETSC_NULL.
88818f449edSLois Curfman McInnes 
8898965ea79SLois Curfman McInnes    The user MUST specify either the local or global matrix dimensions
8908965ea79SLois Curfman McInnes    (possibly both).
8918965ea79SLois Curfman McInnes 
8923501a2bdSLois Curfman McInnes    Currently, the only parallel dense matrix decomposition is by rows,
8933501a2bdSLois Curfman McInnes    so that n=N and each submatrix owns all of the global columns.
8943501a2bdSLois Curfman McInnes 
895027ccd11SLois Curfman McInnes    Level: intermediate
896027ccd11SLois Curfman McInnes 
89739ddd567SLois Curfman McInnes .keywords: matrix, dense, parallel
8988965ea79SLois Curfman McInnes 
89939ddd567SLois Curfman McInnes .seealso: MatCreate(), MatCreateSeqDense(), MatSetValues()
9008965ea79SLois Curfman McInnes @*/
901477f1c0bSLois Curfman McInnes int MatCreateMPIDense(MPI_Comm comm,int m,int n,int M,int N,Scalar *data,Mat *A)
9028965ea79SLois Curfman McInnes {
9038965ea79SLois Curfman McInnes   Mat          mat;
90439ddd567SLois Curfman McInnes   Mat_MPIDense *a;
90525cdf11fSBarry Smith   int          ierr, i,flg;
9068965ea79SLois Curfman McInnes 
9073a40ed3dSBarry Smith   PetscFunctionBegin;
908ed2daf61SLois Curfman McInnes   /* Note:  For now, when data is specified above, this assumes the user correctly
909ed2daf61SLois Curfman McInnes    allocates the local dense storage space.  We should add error checking. */
91018f449edSLois Curfman McInnes 
911477f1c0bSLois Curfman McInnes   *A = 0;
9123f1db9ecSBarry Smith   PetscHeaderCreate(mat,_p_Mat,struct _MatOps,MAT_COOKIE,MATMPIDENSE,"Mat",comm,MatDestroy,MatView);
9138965ea79SLois Curfman McInnes   PLogObjectCreate(mat);
9140452661fSBarry Smith   mat->data       = (void *) (a = PetscNew(Mat_MPIDense)); CHKPTRQ(a);
91509dc0095SBarry Smith   PetscMemcpy(mat->ops,&MatOps_Values,sizeof(struct _MatOps));
916e1311b90SBarry Smith   mat->ops->destroy    = MatDestroy_MPIDense;
917e1311b90SBarry Smith   mat->ops->view       = MatView_MPIDense;
9188965ea79SLois Curfman McInnes   mat->factor          = 0;
91990f02eecSBarry Smith   mat->mapping         = 0;
9208965ea79SLois Curfman McInnes 
921622d7880SLois Curfman McInnes   a->factor       = 0;
922e0fa3b82SLois Curfman McInnes   mat->insertmode = NOT_SET_VALUES;
9238965ea79SLois Curfman McInnes   MPI_Comm_rank(comm,&a->rank);
9248965ea79SLois Curfman McInnes   MPI_Comm_size(comm,&a->size);
9258965ea79SLois Curfman McInnes 
92696f6c058SBarry Smith   ierr = PetscSplitOwnership(comm,&m,&M);CHKERRQ(ierr);
92739ddd567SLois Curfman McInnes 
928c7fcc2eaSBarry Smith   /*
929c7fcc2eaSBarry Smith      The computation of n is wrong below, n should represent the number of local
930c7fcc2eaSBarry Smith      rows in the right (column vector)
931c7fcc2eaSBarry Smith   */
932c7fcc2eaSBarry Smith 
93339ddd567SLois Curfman McInnes   /* each row stores all columns */
93439ddd567SLois Curfman McInnes   if (N == PETSC_DECIDE) N = n;
935d7e8b826SBarry Smith   if (n == PETSC_DECIDE) {n = N/a->size + ((N % a->size) > a->rank);}
936a8c6a408SBarry Smith   /*  if (n != N) SETERRQ(PETSC_ERR_SUP,0,"For now, only n=N is supported"); */
937aca0ad90SLois Curfman McInnes   a->N = mat->N = N;
938aca0ad90SLois Curfman McInnes   a->M = mat->M = M;
939aca0ad90SLois Curfman McInnes   a->m = mat->m = m;
940aca0ad90SLois Curfman McInnes   a->n = mat->n = n;
9418965ea79SLois Curfman McInnes 
942c7fcc2eaSBarry Smith   /* the information in the maps duplicates the information computed below, eventually
943c7fcc2eaSBarry Smith      we should remove the duplicate information that is not contained in the maps */
944488ecbafSBarry Smith   ierr = MapCreateMPI(comm,m,M,&mat->rmap);CHKERRQ(ierr);
94596f6c058SBarry Smith   ierr = MapCreateMPI(comm,PETSC_DECIDE,N,&mat->cmap);CHKERRQ(ierr);
946c7fcc2eaSBarry Smith 
9478965ea79SLois Curfman McInnes   /* build local table of row and column ownerships */
948d7e8b826SBarry Smith   a->rowners = (int *) PetscMalloc(2*(a->size+2)*sizeof(int)); CHKPTRQ(a->rowners);
949d7e8b826SBarry Smith   a->cowners = a->rowners + a->size + 1;
950f09e8eb9SSatish Balay   PLogObjectMemory(mat,2*(a->size+2)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_MPIDense));
951ca161407SBarry Smith   ierr = MPI_Allgather(&m,1,MPI_INT,a->rowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
9528965ea79SLois Curfman McInnes   a->rowners[0] = 0;
9538965ea79SLois Curfman McInnes   for ( i=2; i<=a->size; i++ ) {
9548965ea79SLois Curfman McInnes     a->rowners[i] += a->rowners[i-1];
9558965ea79SLois Curfman McInnes   }
9568965ea79SLois Curfman McInnes   a->rstart = a->rowners[a->rank];
9578965ea79SLois Curfman McInnes   a->rend   = a->rowners[a->rank+1];
958ca161407SBarry Smith   ierr      = MPI_Allgather(&n,1,MPI_INT,a->cowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
959d7e8b826SBarry Smith   a->cowners[0] = 0;
960d7e8b826SBarry Smith   for ( i=2; i<=a->size; i++ ) {
961d7e8b826SBarry Smith     a->cowners[i] += a->cowners[i-1];
962d7e8b826SBarry Smith   }
9638965ea79SLois Curfman McInnes 
964029af93fSBarry Smith   ierr = MatCreateSeqDense(PETSC_COMM_SELF,m,N,data,&a->A); CHKERRQ(ierr);
9658965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->A);
9668965ea79SLois Curfman McInnes 
9678965ea79SLois Curfman McInnes   /* build cache for off array entries formed */
968a2d1c673SSatish Balay   ierr = StashCreate_Private(comm,1,1,&a->stash); CHKERRQ(ierr);
9698965ea79SLois Curfman McInnes 
9708965ea79SLois Curfman McInnes   /* stuff used for matrix vector multiply */
9718965ea79SLois Curfman McInnes   a->lvec        = 0;
9728965ea79SLois Curfman McInnes   a->Mvctx       = 0;
97339b7565bSBarry Smith   a->roworiented = 1;
9748965ea79SLois Curfman McInnes 
975477f1c0bSLois Curfman McInnes   *A = mat;
97625cdf11fSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-help",&flg); CHKERRQ(ierr);
97725cdf11fSBarry Smith   if (flg) {
9788c469469SLois Curfman McInnes     ierr = MatPrintHelp(mat); CHKERRQ(ierr);
9798c469469SLois Curfman McInnes   }
9803a40ed3dSBarry Smith   PetscFunctionReturn(0);
9818965ea79SLois Curfman McInnes }
9828965ea79SLois Curfman McInnes 
9835615d1e5SSatish Balay #undef __FUNC__
9845609ef8eSBarry Smith #define __FUNC__ "MatDuplicate_MPIDense"
9855609ef8eSBarry Smith static int MatDuplicate_MPIDense(Mat A,MatDuplicateOption cpvalues,Mat *newmat)
9868965ea79SLois Curfman McInnes {
9878965ea79SLois Curfman McInnes   Mat          mat;
9883501a2bdSLois Curfman McInnes   Mat_MPIDense *a,*oldmat = (Mat_MPIDense *) A->data;
98939ddd567SLois Curfman McInnes   int          ierr;
9902ba99913SLois Curfman McInnes   FactorCtx    *factor;
9918965ea79SLois Curfman McInnes 
9923a40ed3dSBarry Smith   PetscFunctionBegin;
9938965ea79SLois Curfman McInnes   *newmat       = 0;
9943f1db9ecSBarry Smith   PetscHeaderCreate(mat,_p_Mat,struct _MatOps,MAT_COOKIE,MATMPIDENSE,"Mat",A->comm,MatDestroy,MatView);
9958965ea79SLois Curfman McInnes   PLogObjectCreate(mat);
9960452661fSBarry Smith   mat->data      = (void *) (a = PetscNew(Mat_MPIDense)); CHKPTRQ(a);
99709dc0095SBarry Smith   PetscMemcpy(mat->ops,&MatOps_Values,sizeof(struct _MatOps));
998e1311b90SBarry Smith   mat->ops->destroy   = MatDestroy_MPIDense;
999e1311b90SBarry Smith   mat->ops->view      = MatView_MPIDense;
10003501a2bdSLois Curfman McInnes   mat->factor         = A->factor;
1001c456f294SBarry Smith   mat->assembled      = PETSC_TRUE;
10028965ea79SLois Curfman McInnes 
100344cd7ae7SLois Curfman McInnes   a->m = mat->m = oldmat->m;
100444cd7ae7SLois Curfman McInnes   a->n = mat->n = oldmat->n;
100544cd7ae7SLois Curfman McInnes   a->M = mat->M = oldmat->M;
100644cd7ae7SLois Curfman McInnes   a->N = mat->N = oldmat->N;
10072ba99913SLois Curfman McInnes   if (oldmat->factor) {
10082ba99913SLois Curfman McInnes     a->factor = (FactorCtx *) (factor = PetscNew(FactorCtx)); CHKPTRQ(factor);
10092ba99913SLois Curfman McInnes     /* copy factor contents ... add this code! */
10102ba99913SLois Curfman McInnes   } else a->factor = 0;
10118965ea79SLois Curfman McInnes 
10128965ea79SLois Curfman McInnes   a->rstart       = oldmat->rstart;
10138965ea79SLois Curfman McInnes   a->rend         = oldmat->rend;
10148965ea79SLois Curfman McInnes   a->size         = oldmat->size;
10158965ea79SLois Curfman McInnes   a->rank         = oldmat->rank;
1016e0fa3b82SLois Curfman McInnes   mat->insertmode = NOT_SET_VALUES;
10178965ea79SLois Curfman McInnes 
10180452661fSBarry Smith   a->rowners = (int *) PetscMalloc((a->size+1)*sizeof(int)); CHKPTRQ(a->rowners);
1019f09e8eb9SSatish Balay   PLogObjectMemory(mat,(a->size+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_MPIDense));
10208965ea79SLois Curfman McInnes   PetscMemcpy(a->rowners,oldmat->rowners,(a->size+1)*sizeof(int));
1021a2d1c673SSatish Balay   ierr = StashCreate_Private(A->comm,1,1,&a->stash); CHKERRQ(ierr);
10228965ea79SLois Curfman McInnes 
10238965ea79SLois Curfman McInnes   ierr =  VecDuplicate(oldmat->lvec,&a->lvec); CHKERRQ(ierr);
10248965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->lvec);
102555659b69SBarry Smith   ierr =  VecScatterCopy(oldmat->Mvctx,&a->Mvctx); CHKERRQ(ierr);
10268965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->Mvctx);
10275609ef8eSBarry Smith   ierr =  MatDuplicate(oldmat->A,cpvalues,&a->A); CHKERRQ(ierr);
10288965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->A);
10298965ea79SLois Curfman McInnes   *newmat = mat;
10303a40ed3dSBarry Smith   PetscFunctionReturn(0);
10318965ea79SLois Curfman McInnes }
10328965ea79SLois Curfman McInnes 
103377c4ece6SBarry Smith #include "sys.h"
10348965ea79SLois Curfman McInnes 
10355615d1e5SSatish Balay #undef __FUNC__
10365615d1e5SSatish Balay #define __FUNC__ "MatLoad_MPIDense_DenseInFile"
103790ace30eSBarry Smith int MatLoad_MPIDense_DenseInFile(MPI_Comm comm,int fd,int M, int N, Mat *newmat)
103890ace30eSBarry Smith {
103940011551SBarry Smith   int        *rowners, i,size,rank,m,ierr,nz,j;
104090ace30eSBarry Smith   Scalar     *array,*vals,*vals_ptr;
104190ace30eSBarry Smith   MPI_Status status;
104290ace30eSBarry Smith 
10433a40ed3dSBarry Smith   PetscFunctionBegin;
104490ace30eSBarry Smith   MPI_Comm_rank(comm,&rank);
104590ace30eSBarry Smith   MPI_Comm_size(comm,&size);
104690ace30eSBarry Smith 
104790ace30eSBarry Smith   /* determine ownership of all rows */
104890ace30eSBarry Smith   m          = M/size + ((M % size) > rank);
104990ace30eSBarry Smith   rowners    = (int *) PetscMalloc((size+2)*sizeof(int)); CHKPTRQ(rowners);
1050ca161407SBarry Smith   ierr       = MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
105190ace30eSBarry Smith   rowners[0] = 0;
105290ace30eSBarry Smith   for ( i=2; i<=size; i++ ) {
105390ace30eSBarry Smith     rowners[i] += rowners[i-1];
105490ace30eSBarry Smith   }
105590ace30eSBarry Smith 
105690ace30eSBarry Smith   ierr = MatCreateMPIDense(comm,m,PETSC_DECIDE,M,N,PETSC_NULL,newmat);CHKERRQ(ierr);
105790ace30eSBarry Smith   ierr = MatGetArray(*newmat,&array); CHKERRQ(ierr);
105890ace30eSBarry Smith 
105990ace30eSBarry Smith   if (!rank) {
106090ace30eSBarry Smith     vals = (Scalar *) PetscMalloc( m*N*sizeof(Scalar) ); CHKPTRQ(vals);
106190ace30eSBarry Smith 
106290ace30eSBarry Smith     /* read in my part of the matrix numerical values  */
10630752156aSBarry Smith     ierr = PetscBinaryRead(fd,vals,m*N,PETSC_SCALAR); CHKERRQ(ierr);
106490ace30eSBarry Smith 
106590ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
106690ace30eSBarry Smith     vals_ptr = vals;
106790ace30eSBarry Smith     for ( i=0; i<m; i++ ) {
106890ace30eSBarry Smith       for ( j=0; j<N; j++ ) {
106990ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
107090ace30eSBarry Smith       }
107190ace30eSBarry Smith     }
107290ace30eSBarry Smith 
107390ace30eSBarry Smith     /* read in other processors and ship out */
107490ace30eSBarry Smith     for ( i=1; i<size; i++ ) {
107590ace30eSBarry Smith       nz   = (rowners[i+1] - rowners[i])*N;
10760752156aSBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR); CHKERRQ(ierr);
1077ca161407SBarry Smith       ierr = MPI_Send(vals,nz,MPIU_SCALAR,i,(*newmat)->tag,comm);CHKERRQ(ierr);
107890ace30eSBarry Smith     }
10793a40ed3dSBarry Smith   } else {
108090ace30eSBarry Smith     /* receive numeric values */
108190ace30eSBarry Smith     vals = (Scalar*) PetscMalloc( m*N*sizeof(Scalar) ); CHKPTRQ(vals);
108290ace30eSBarry Smith 
108390ace30eSBarry Smith     /* receive message of values*/
1084ca161407SBarry Smith     ierr = MPI_Recv(vals,m*N,MPIU_SCALAR,0,(*newmat)->tag,comm,&status);CHKERRQ(ierr);
108590ace30eSBarry Smith 
108690ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
108790ace30eSBarry Smith     vals_ptr = vals;
108890ace30eSBarry Smith     for ( i=0; i<m; i++ ) {
108990ace30eSBarry Smith       for ( j=0; j<N; j++ ) {
109090ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
109190ace30eSBarry Smith       }
109290ace30eSBarry Smith     }
109390ace30eSBarry Smith   }
109490ace30eSBarry Smith   PetscFree(rowners);
109590ace30eSBarry Smith   PetscFree(vals);
10966d4a8577SBarry Smith   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
10976d4a8577SBarry Smith   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
10983a40ed3dSBarry Smith   PetscFunctionReturn(0);
109990ace30eSBarry Smith }
110090ace30eSBarry Smith 
110190ace30eSBarry Smith 
11025615d1e5SSatish Balay #undef __FUNC__
11035615d1e5SSatish Balay #define __FUNC__ "MatLoad_MPIDense"
110419bcc07fSBarry Smith int MatLoad_MPIDense(Viewer viewer,MatType type,Mat *newmat)
11058965ea79SLois Curfman McInnes {
11068965ea79SLois Curfman McInnes   Mat          A;
11078965ea79SLois Curfman McInnes   Scalar       *vals,*svals;
110819bcc07fSBarry Smith   MPI_Comm     comm = ((PetscObject)viewer)->comm;
11098965ea79SLois Curfman McInnes   MPI_Status   status;
11108965ea79SLois Curfman McInnes   int          header[4],rank,size,*rowlengths = 0,M,N,m,*rowners,maxnz,*cols;
11118965ea79SLois Curfman McInnes   int          *ourlens,*sndcounts = 0,*procsnz = 0, *offlens,jj,*mycols,*smycols;
111219bcc07fSBarry Smith   int          tag = ((PetscObject)viewer)->tag;
11133a40ed3dSBarry Smith   int          i, nz, ierr, j,rstart, rend, fd;
11148965ea79SLois Curfman McInnes 
11153a40ed3dSBarry Smith   PetscFunctionBegin;
11168965ea79SLois Curfman McInnes   MPI_Comm_size(comm,&size); MPI_Comm_rank(comm,&rank);
11178965ea79SLois Curfman McInnes   if (!rank) {
111890ace30eSBarry Smith     ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
11190752156aSBarry Smith     ierr = PetscBinaryRead(fd,(char *)header,4,PETSC_INT); CHKERRQ(ierr);
1120a8c6a408SBarry Smith     if (header[0] != MAT_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"not matrix object");
11218965ea79SLois Curfman McInnes   }
11228965ea79SLois Curfman McInnes 
1123ca161407SBarry Smith   ierr = MPI_Bcast(header+1,3,MPI_INT,0,comm);CHKERRQ(ierr);
112490ace30eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
112590ace30eSBarry Smith 
112690ace30eSBarry Smith   /*
112790ace30eSBarry Smith        Handle case where matrix is stored on disk as a dense matrix
112890ace30eSBarry Smith   */
112990ace30eSBarry Smith   if (nz == MATRIX_BINARY_FORMAT_DENSE) {
11303a40ed3dSBarry Smith     ierr = MatLoad_MPIDense_DenseInFile(comm,fd,M,N,newmat);CHKERRQ(ierr);
11313a40ed3dSBarry Smith     PetscFunctionReturn(0);
113290ace30eSBarry Smith   }
113390ace30eSBarry Smith 
11348965ea79SLois Curfman McInnes   /* determine ownership of all rows */
11358965ea79SLois Curfman McInnes   m          = M/size + ((M % size) > rank);
11360452661fSBarry Smith   rowners    = (int *) PetscMalloc((size+2)*sizeof(int)); CHKPTRQ(rowners);
1137ca161407SBarry Smith   ierr       = MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
11388965ea79SLois Curfman McInnes   rowners[0] = 0;
11398965ea79SLois Curfman McInnes   for ( i=2; i<=size; i++ ) {
11408965ea79SLois Curfman McInnes     rowners[i] += rowners[i-1];
11418965ea79SLois Curfman McInnes   }
11428965ea79SLois Curfman McInnes   rstart = rowners[rank];
11438965ea79SLois Curfman McInnes   rend   = rowners[rank+1];
11448965ea79SLois Curfman McInnes 
11458965ea79SLois Curfman McInnes   /* distribute row lengths to all processors */
11460452661fSBarry Smith   ourlens = (int*) PetscMalloc( 2*(rend-rstart)*sizeof(int) ); CHKPTRQ(ourlens);
11478965ea79SLois Curfman McInnes   offlens = ourlens + (rend-rstart);
11488965ea79SLois Curfman McInnes   if (!rank) {
11490452661fSBarry Smith     rowlengths = (int*) PetscMalloc( M*sizeof(int) ); CHKPTRQ(rowlengths);
11500752156aSBarry Smith     ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT); CHKERRQ(ierr);
11510452661fSBarry Smith     sndcounts = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(sndcounts);
11528965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) sndcounts[i] = rowners[i+1] - rowners[i];
1153ca161407SBarry Smith     ierr = MPI_Scatterv(rowlengths,sndcounts,rowners,MPI_INT,ourlens,rend-rstart,MPI_INT,0,comm);CHKERRQ(ierr);
11540452661fSBarry Smith     PetscFree(sndcounts);
1155ca161407SBarry Smith   } else {
1156ca161407SBarry Smith     ierr = MPI_Scatterv(0,0,0,MPI_INT,ourlens,rend-rstart,MPI_INT, 0,comm);CHKERRQ(ierr);
11578965ea79SLois Curfman McInnes   }
11588965ea79SLois Curfman McInnes 
11598965ea79SLois Curfman McInnes   if (!rank) {
11608965ea79SLois Curfman McInnes     /* calculate the number of nonzeros on each processor */
11610452661fSBarry Smith     procsnz = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(procsnz);
1162cddf8d76SBarry Smith     PetscMemzero(procsnz,size*sizeof(int));
11638965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) {
11648965ea79SLois Curfman McInnes       for ( j=rowners[i]; j< rowners[i+1]; j++ ) {
11658965ea79SLois Curfman McInnes         procsnz[i] += rowlengths[j];
11668965ea79SLois Curfman McInnes       }
11678965ea79SLois Curfman McInnes     }
11680452661fSBarry Smith     PetscFree(rowlengths);
11698965ea79SLois Curfman McInnes 
11708965ea79SLois Curfman McInnes     /* determine max buffer needed and allocate it */
11718965ea79SLois Curfman McInnes     maxnz = 0;
11728965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) {
11730452661fSBarry Smith       maxnz = PetscMax(maxnz,procsnz[i]);
11748965ea79SLois Curfman McInnes     }
11750452661fSBarry Smith     cols = (int *) PetscMalloc( maxnz*sizeof(int) ); CHKPTRQ(cols);
11768965ea79SLois Curfman McInnes 
11778965ea79SLois Curfman McInnes     /* read in my part of the matrix column indices  */
11788965ea79SLois Curfman McInnes     nz = procsnz[0];
11790452661fSBarry Smith     mycols = (int *) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(mycols);
11800752156aSBarry Smith     ierr = PetscBinaryRead(fd,mycols,nz,PETSC_INT); CHKERRQ(ierr);
11818965ea79SLois Curfman McInnes 
11828965ea79SLois Curfman McInnes     /* read in every one elses and ship off */
11838965ea79SLois Curfman McInnes     for ( i=1; i<size; i++ ) {
11848965ea79SLois Curfman McInnes       nz   = procsnz[i];
11850752156aSBarry Smith       ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT); CHKERRQ(ierr);
1186ca161407SBarry Smith       ierr = MPI_Send(cols,nz,MPI_INT,i,tag,comm);CHKERRQ(ierr);
11878965ea79SLois Curfman McInnes     }
11880452661fSBarry Smith     PetscFree(cols);
11893a40ed3dSBarry Smith   } else {
11908965ea79SLois Curfman McInnes     /* determine buffer space needed for message */
11918965ea79SLois Curfman McInnes     nz = 0;
11928965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
11938965ea79SLois Curfman McInnes       nz += ourlens[i];
11948965ea79SLois Curfman McInnes     }
11950452661fSBarry Smith     mycols = (int*) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(mycols);
11968965ea79SLois Curfman McInnes 
11978965ea79SLois Curfman McInnes     /* receive message of column indices*/
1198ca161407SBarry Smith     ierr = MPI_Recv(mycols,nz,MPI_INT,0,tag,comm,&status);CHKERRQ(ierr);
1199ca161407SBarry Smith     ierr = MPI_Get_count(&status,MPI_INT,&maxnz);CHKERRQ(ierr);
1200a8c6a408SBarry Smith     if (maxnz != nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"something is wrong with file");
12018965ea79SLois Curfman McInnes   }
12028965ea79SLois Curfman McInnes 
12038965ea79SLois Curfman McInnes   /* loop over local rows, determining number of off diagonal entries */
1204cddf8d76SBarry Smith   PetscMemzero(offlens,m*sizeof(int));
12058965ea79SLois Curfman McInnes   jj = 0;
12068965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
12078965ea79SLois Curfman McInnes     for ( j=0; j<ourlens[i]; j++ ) {
12088965ea79SLois Curfman McInnes       if (mycols[jj] < rstart || mycols[jj] >= rend) offlens[i]++;
12098965ea79SLois Curfman McInnes       jj++;
12108965ea79SLois Curfman McInnes     }
12118965ea79SLois Curfman McInnes   }
12128965ea79SLois Curfman McInnes 
12138965ea79SLois Curfman McInnes   /* create our matrix */
12148965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
12158965ea79SLois Curfman McInnes     ourlens[i] -= offlens[i];
12168965ea79SLois Curfman McInnes   }
1217b4fd4287SBarry Smith   ierr = MatCreateMPIDense(comm,m,PETSC_DECIDE,M,N,PETSC_NULL,newmat);CHKERRQ(ierr);
12188965ea79SLois Curfman McInnes   A = *newmat;
12198965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
12208965ea79SLois Curfman McInnes     ourlens[i] += offlens[i];
12218965ea79SLois Curfman McInnes   }
12228965ea79SLois Curfman McInnes 
12238965ea79SLois Curfman McInnes   if (!rank) {
12240452661fSBarry Smith     vals = (Scalar *) PetscMalloc( maxnz*sizeof(Scalar) ); CHKPTRQ(vals);
12258965ea79SLois Curfman McInnes 
12268965ea79SLois Curfman McInnes     /* read in my part of the matrix numerical values  */
12278965ea79SLois Curfman McInnes     nz = procsnz[0];
12280752156aSBarry Smith     ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR); CHKERRQ(ierr);
12298965ea79SLois Curfman McInnes 
12308965ea79SLois Curfman McInnes     /* insert into matrix */
12318965ea79SLois Curfman McInnes     jj      = rstart;
12328965ea79SLois Curfman McInnes     smycols = mycols;
12338965ea79SLois Curfman McInnes     svals   = vals;
12348965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
12358965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
12368965ea79SLois Curfman McInnes       smycols += ourlens[i];
12378965ea79SLois Curfman McInnes       svals   += ourlens[i];
12388965ea79SLois Curfman McInnes       jj++;
12398965ea79SLois Curfman McInnes     }
12408965ea79SLois Curfman McInnes 
12418965ea79SLois Curfman McInnes     /* read in other processors and ship out */
12428965ea79SLois Curfman McInnes     for ( i=1; i<size; i++ ) {
12438965ea79SLois Curfman McInnes       nz   = procsnz[i];
12440752156aSBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR); CHKERRQ(ierr);
1245ca161407SBarry Smith       ierr = MPI_Send(vals,nz,MPIU_SCALAR,i,A->tag,comm);CHKERRQ(ierr);
12468965ea79SLois Curfman McInnes     }
12470452661fSBarry Smith     PetscFree(procsnz);
12483a40ed3dSBarry Smith   } else {
12498965ea79SLois Curfman McInnes     /* receive numeric values */
12500452661fSBarry Smith     vals = (Scalar*) PetscMalloc( nz*sizeof(Scalar) ); CHKPTRQ(vals);
12518965ea79SLois Curfman McInnes 
12528965ea79SLois Curfman McInnes     /* receive message of values*/
1253ca161407SBarry Smith     ierr = MPI_Recv(vals,nz,MPIU_SCALAR,0,A->tag,comm,&status);CHKERRQ(ierr);
1254ca161407SBarry Smith     ierr = MPI_Get_count(&status,MPIU_SCALAR,&maxnz);CHKERRQ(ierr);
1255a8c6a408SBarry Smith     if (maxnz != nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"something is wrong with file");
12568965ea79SLois Curfman McInnes 
12578965ea79SLois Curfman McInnes     /* insert into matrix */
12588965ea79SLois Curfman McInnes     jj      = rstart;
12598965ea79SLois Curfman McInnes     smycols = mycols;
12608965ea79SLois Curfman McInnes     svals   = vals;
12618965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
12628965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
12638965ea79SLois Curfman McInnes       smycols += ourlens[i];
12648965ea79SLois Curfman McInnes       svals   += ourlens[i];
12658965ea79SLois Curfman McInnes       jj++;
12668965ea79SLois Curfman McInnes     }
12678965ea79SLois Curfman McInnes   }
12680452661fSBarry Smith   PetscFree(ourlens); PetscFree(vals); PetscFree(mycols); PetscFree(rowners);
12698965ea79SLois Curfman McInnes 
12706d4a8577SBarry Smith   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
12716d4a8577SBarry Smith   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
12723a40ed3dSBarry Smith   PetscFunctionReturn(0);
12738965ea79SLois Curfman McInnes }
127490ace30eSBarry Smith 
127590ace30eSBarry Smith 
127690ace30eSBarry Smith 
127790ace30eSBarry Smith 
127890ace30eSBarry Smith 
1279