xref: /petsc/src/mat/impls/dense/mpi/mpidense.c (revision d132466e10dddff923c4add9c18d7fc5c6003d46)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*d132466eSBarry Smith static char vcid[] = "$Id: mpidense.c,v 1.111 1999/03/25 21:23:03 balay Exp bsmith $";
38965ea79SLois Curfman McInnes #endif
48965ea79SLois Curfman McInnes 
5ed3cc1f0SBarry Smith /*
6ed3cc1f0SBarry Smith    Basic functions for basic parallel dense matrices.
7ed3cc1f0SBarry Smith */
8ed3cc1f0SBarry Smith 
970f55243SBarry Smith #include "src/mat/impls/dense/mpi/mpidense.h"
10f5eb4b81SSatish Balay #include "src/vec/vecimpl.h"
118965ea79SLois Curfman McInnes 
127ef1d9bdSSatish Balay extern int MatSetUpMultiply_MPIDense(Mat);
137ef1d9bdSSatish 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 {
383782ba37SSatish Balay       if ( !A->donotstash) {
3939b7565bSBarry Smith         if (roworiented) {
408798bf22SSatish Balay           ierr = MatStashValuesRow_Private(&mat->stash,idxm[i],n,idxn,v+i*n); CHKERRQ(ierr);
41d36fbae8SSatish Balay         } else {
428798bf22SSatish Balay           ierr = MatStashValuesCol_Private(&mat->stash,idxm[i],n,idxn,v+i,m);CHKERRQ(ierr);
4339b7565bSBarry Smith         }
44b49de8d1SLois Curfman McInnes       }
45b49de8d1SLois Curfman McInnes     }
463782ba37SSatish Balay   }
473a40ed3dSBarry Smith   PetscFunctionReturn(0);
48b49de8d1SLois Curfman McInnes }
49b49de8d1SLois Curfman McInnes 
505615d1e5SSatish Balay #undef __FUNC__
515615d1e5SSatish Balay #define __FUNC__ "MatGetValues_MPIDense"
528f6be9afSLois Curfman McInnes int MatGetValues_MPIDense(Mat mat,int m,int *idxm,int n,int *idxn,Scalar *v)
53b49de8d1SLois Curfman McInnes {
54b49de8d1SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
55b49de8d1SLois Curfman McInnes   int          ierr, i, j, rstart = mdn->rstart, rend = mdn->rend, row;
56b49de8d1SLois Curfman McInnes 
573a40ed3dSBarry Smith   PetscFunctionBegin;
58b49de8d1SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
59a8c6a408SBarry Smith     if (idxm[i] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative row");
60a8c6a408SBarry Smith     if (idxm[i] >= mdn->M) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"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++ ) {
64a8c6a408SBarry Smith         if (idxn[j] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Negative column");
65a8c6a408SBarry Smith         if (idxn[j] >= mdn->N) {
66a8c6a408SBarry Smith           SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Column too large");
67a8c6a408SBarry Smith         }
68b49de8d1SLois Curfman McInnes         ierr = MatGetValues(mdn->A,1,&row,1,&idxn[j],v+i*n+j); CHKERRQ(ierr);
69b49de8d1SLois Curfman McInnes       }
70a8c6a408SBarry Smith     } else {
71a8c6a408SBarry Smith       SETERRQ(PETSC_ERR_SUP,0,"Only local values currently supported");
728965ea79SLois Curfman McInnes     }
738965ea79SLois Curfman McInnes   }
743a40ed3dSBarry Smith   PetscFunctionReturn(0);
758965ea79SLois Curfman McInnes }
768965ea79SLois Curfman McInnes 
775615d1e5SSatish Balay #undef __FUNC__
785615d1e5SSatish Balay #define __FUNC__ "MatGetArray_MPIDense"
798f6be9afSLois Curfman McInnes int MatGetArray_MPIDense(Mat A,Scalar **array)
80ff14e315SSatish Balay {
81ff14e315SSatish Balay   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
82ff14e315SSatish Balay   int          ierr;
83ff14e315SSatish Balay 
843a40ed3dSBarry Smith   PetscFunctionBegin;
85ff14e315SSatish Balay   ierr = MatGetArray(a->A,array); CHKERRQ(ierr);
863a40ed3dSBarry Smith   PetscFunctionReturn(0);
87ff14e315SSatish Balay }
88ff14e315SSatish Balay 
895615d1e5SSatish Balay #undef __FUNC__
905615d1e5SSatish Balay #define __FUNC__ "MatRestoreArray_MPIDense"
918f6be9afSLois Curfman McInnes int MatRestoreArray_MPIDense(Mat A,Scalar **array)
92ff14e315SSatish Balay {
933a40ed3dSBarry Smith   PetscFunctionBegin;
943a40ed3dSBarry Smith   PetscFunctionReturn(0);
95ff14e315SSatish Balay }
96ff14e315SSatish Balay 
975615d1e5SSatish Balay #undef __FUNC__
985615d1e5SSatish Balay #define __FUNC__ "MatAssemblyBegin_MPIDense"
998f6be9afSLois Curfman McInnes int MatAssemblyBegin_MPIDense(Mat mat,MatAssemblyType mode)
1008965ea79SLois Curfman McInnes {
10139ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
1028965ea79SLois Curfman McInnes   MPI_Comm     comm = mat->comm;
103d36fbae8SSatish Balay   int          ierr,nstash,reallocs;
1048965ea79SLois Curfman McInnes   InsertMode   addv;
1058965ea79SLois Curfman McInnes 
1063a40ed3dSBarry Smith   PetscFunctionBegin;
1078965ea79SLois Curfman McInnes   /* make sure all processors are either in INSERTMODE or ADDMODE */
108ca161407SBarry Smith   ierr = MPI_Allreduce(&mat->insertmode,&addv,1,MPI_INT,MPI_BOR,comm);CHKERRQ(ierr);
1097056b6fcSBarry Smith   if (addv == (ADD_VALUES|INSERT_VALUES)) {
110a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"Cannot mix adds/inserts on different procs");
1118965ea79SLois Curfman McInnes   }
112e0fa3b82SLois Curfman McInnes   mat->insertmode = addv; /* in case this processor had no cache */
1138965ea79SLois Curfman McInnes 
1148798bf22SSatish Balay   ierr = MatStashScatterBegin_Private(&mat->stash,mdn->rowners); CHKERRQ(ierr);
1158798bf22SSatish Balay   ierr = MatStashGetInfo_Private(&mat->stash,&nstash,&reallocs); CHKERRQ(ierr);
116d36fbae8SSatish Balay   PLogInfo(mdn->A,"MatAssemblyBegin_MPIDense:Stash has %d entries, uses %d mallocs.\n",
117d36fbae8SSatish Balay            nstash,reallocs);
1183a40ed3dSBarry Smith   PetscFunctionReturn(0);
1198965ea79SLois Curfman McInnes }
1208965ea79SLois Curfman McInnes 
1215615d1e5SSatish Balay #undef __FUNC__
1225615d1e5SSatish Balay #define __FUNC__ "MatAssemblyEnd_MPIDense"
1238f6be9afSLois Curfman McInnes int MatAssemblyEnd_MPIDense(Mat mat,MatAssemblyType mode)
1248965ea79SLois Curfman McInnes {
12539ddd567SLois Curfman McInnes   Mat_MPIDense *mdn=(Mat_MPIDense*)mat->data;
1267ef1d9bdSSatish Balay   int          i,n,ierr,*row,*col,flg,j,rstart,ncols;
1277ef1d9bdSSatish Balay   Scalar       *val;
128e0fa3b82SLois Curfman McInnes   InsertMode   addv=mat->insertmode;
1298965ea79SLois Curfman McInnes 
1303a40ed3dSBarry Smith   PetscFunctionBegin;
1318965ea79SLois Curfman McInnes   /*  wait on receives */
1327ef1d9bdSSatish Balay   while (1) {
1338798bf22SSatish Balay     ierr = MatStashScatterGetMesg_Private(&mat->stash,&n,&row,&col,&val,&flg); CHKERRQ(ierr);
1347ef1d9bdSSatish Balay     if (!flg) break;
1358965ea79SLois Curfman McInnes 
1367ef1d9bdSSatish Balay     for ( i=0; i<n; ) {
1377ef1d9bdSSatish Balay       /* Now identify the consecutive vals belonging to the same row */
1387ef1d9bdSSatish Balay       for ( j=i,rstart=row[j]; j<n; j++ ) { if (row[j] != rstart) break; }
1397ef1d9bdSSatish Balay       if (j < n) ncols = j-i;
1407ef1d9bdSSatish Balay       else       ncols = n-i;
1417ef1d9bdSSatish Balay       /* Now assemble all these values with a single function call */
1427ef1d9bdSSatish Balay       ierr = MatSetValues_MPIDense(mat,1,row+i,ncols,col+i,val+i,addv); CHKERRQ(ierr);
1437ef1d9bdSSatish Balay       i = j;
1448965ea79SLois Curfman McInnes     }
1457ef1d9bdSSatish Balay   }
1468798bf22SSatish Balay   ierr = MatStashScatterEnd_Private(&mat->stash); CHKERRQ(ierr);
1478965ea79SLois Curfman McInnes 
14839ddd567SLois Curfman McInnes   ierr = MatAssemblyBegin(mdn->A,mode); CHKERRQ(ierr);
14939ddd567SLois Curfman McInnes   ierr = MatAssemblyEnd(mdn->A,mode); CHKERRQ(ierr);
1508965ea79SLois Curfman McInnes 
1516d4a8577SBarry Smith   if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) {
15239ddd567SLois Curfman McInnes     ierr = MatSetUpMultiply_MPIDense(mat); CHKERRQ(ierr);
1538965ea79SLois Curfman McInnes   }
1543a40ed3dSBarry Smith   PetscFunctionReturn(0);
1558965ea79SLois Curfman McInnes }
1568965ea79SLois Curfman McInnes 
1575615d1e5SSatish Balay #undef __FUNC__
1585615d1e5SSatish Balay #define __FUNC__ "MatZeroEntries_MPIDense"
1598f6be9afSLois Curfman McInnes int MatZeroEntries_MPIDense(Mat A)
1608965ea79SLois Curfman McInnes {
1613a40ed3dSBarry Smith   int          ierr;
16239ddd567SLois Curfman McInnes   Mat_MPIDense *l = (Mat_MPIDense *) A->data;
1633a40ed3dSBarry Smith 
1643a40ed3dSBarry Smith   PetscFunctionBegin;
1653a40ed3dSBarry Smith   ierr = MatZeroEntries(l->A);CHKERRQ(ierr);
1663a40ed3dSBarry Smith   PetscFunctionReturn(0);
1678965ea79SLois Curfman McInnes }
1688965ea79SLois Curfman McInnes 
1695615d1e5SSatish Balay #undef __FUNC__
1705615d1e5SSatish Balay #define __FUNC__ "MatGetBlockSize_MPIDense"
1718f6be9afSLois Curfman McInnes int MatGetBlockSize_MPIDense(Mat A,int *bs)
1724e220ebcSLois Curfman McInnes {
1733a40ed3dSBarry Smith   PetscFunctionBegin;
1744e220ebcSLois Curfman McInnes   *bs = 1;
1753a40ed3dSBarry Smith   PetscFunctionReturn(0);
1764e220ebcSLois Curfman McInnes }
1774e220ebcSLois Curfman McInnes 
1788965ea79SLois Curfman McInnes /* the code does not do the diagonal entries correctly unless the
1798965ea79SLois Curfman McInnes    matrix is square and the column and row owerships are identical.
1808965ea79SLois Curfman McInnes    This is a BUG. The only way to fix it seems to be to access
1813501a2bdSLois Curfman McInnes    mdn->A and mdn->B directly and not through the MatZeroRows()
1828965ea79SLois Curfman McInnes    routine.
1838965ea79SLois Curfman McInnes */
1845615d1e5SSatish Balay #undef __FUNC__
1855615d1e5SSatish Balay #define __FUNC__ "MatZeroRows_MPIDense"
1868f6be9afSLois Curfman McInnes int MatZeroRows_MPIDense(Mat A,IS is,Scalar *diag)
1878965ea79SLois Curfman McInnes {
18839ddd567SLois Curfman McInnes   Mat_MPIDense   *l = (Mat_MPIDense *) A->data;
1898965ea79SLois Curfman McInnes   int            i,ierr,N, *rows,*owners = l->rowners,size = l->size;
1908965ea79SLois Curfman McInnes   int            *procs,*nprocs,j,found,idx,nsends,*work;
1918965ea79SLois Curfman McInnes   int            nmax,*svalues,*starts,*owner,nrecvs,rank = l->rank;
1928965ea79SLois Curfman McInnes   int            *rvalues,tag = A->tag,count,base,slen,n,*source;
1938965ea79SLois Curfman McInnes   int            *lens,imdex,*lrows,*values;
1948965ea79SLois Curfman McInnes   MPI_Comm       comm = A->comm;
1958965ea79SLois Curfman McInnes   MPI_Request    *send_waits,*recv_waits;
1968965ea79SLois Curfman McInnes   MPI_Status     recv_status,*send_status;
1978965ea79SLois Curfman McInnes   IS             istmp;
1988965ea79SLois Curfman McInnes 
1993a40ed3dSBarry Smith   PetscFunctionBegin;
20077c4ece6SBarry Smith   ierr = ISGetSize(is,&N); CHKERRQ(ierr);
2018965ea79SLois Curfman McInnes   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
2028965ea79SLois Curfman McInnes 
2038965ea79SLois Curfman McInnes   /*  first count number of contributors to each processor */
2040452661fSBarry Smith   nprocs = (int *) PetscMalloc( 2*size*sizeof(int) ); CHKPTRQ(nprocs);
205cddf8d76SBarry Smith   PetscMemzero(nprocs,2*size*sizeof(int)); procs = nprocs + size;
2060452661fSBarry Smith   owner = (int *) PetscMalloc((N+1)*sizeof(int)); CHKPTRQ(owner); /* see note*/
2078965ea79SLois Curfman McInnes   for ( i=0; i<N; i++ ) {
2088965ea79SLois Curfman McInnes     idx = rows[i];
2098965ea79SLois Curfman McInnes     found = 0;
2108965ea79SLois Curfman McInnes     for ( j=0; j<size; j++ ) {
2118965ea79SLois Curfman McInnes       if (idx >= owners[j] && idx < owners[j+1]) {
2128965ea79SLois Curfman McInnes         nprocs[j]++; procs[j] = 1; owner[i] = j; found = 1; break;
2138965ea79SLois Curfman McInnes       }
2148965ea79SLois Curfman McInnes     }
215a8c6a408SBarry Smith     if (!found) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Index out of range");
2168965ea79SLois Curfman McInnes   }
2178965ea79SLois Curfman McInnes   nsends = 0;  for ( i=0; i<size; i++ ) { nsends += procs[i];}
2188965ea79SLois Curfman McInnes 
2198965ea79SLois Curfman McInnes   /* inform other processors of number of messages and max length*/
2200452661fSBarry Smith   work   = (int *) PetscMalloc( size*sizeof(int) ); CHKPTRQ(work);
221ca161407SBarry Smith   ierr   = MPI_Allreduce( procs, work,size,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
2228965ea79SLois Curfman McInnes   nrecvs = work[rank];
223ca161407SBarry Smith   ierr   = MPI_Allreduce( nprocs, work,size,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
2248965ea79SLois Curfman McInnes   nmax   = work[rank];
2250452661fSBarry Smith   PetscFree(work);
2268965ea79SLois Curfman McInnes 
2278965ea79SLois Curfman McInnes   /* post receives:   */
2283a40ed3dSBarry Smith   rvalues    = (int *) PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(int));CHKPTRQ(rvalues);
2293a40ed3dSBarry Smith   recv_waits = (MPI_Request *) PetscMalloc((nrecvs+1)*sizeof(MPI_Request));CHKPTRQ(recv_waits);
2308965ea79SLois Curfman McInnes   for ( i=0; i<nrecvs; i++ ) {
231ca161407SBarry Smith     ierr = MPI_Irecv(rvalues+nmax*i,nmax,MPI_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr);
2328965ea79SLois Curfman McInnes   }
2338965ea79SLois Curfman McInnes 
2348965ea79SLois Curfman McInnes   /* do sends:
2358965ea79SLois Curfman McInnes       1) starts[i] gives the starting index in svalues for stuff going to
2368965ea79SLois Curfman McInnes          the ith processor
2378965ea79SLois Curfman McInnes   */
2380452661fSBarry Smith   svalues    = (int *) PetscMalloc( (N+1)*sizeof(int) ); CHKPTRQ(svalues);
2397056b6fcSBarry Smith   send_waits = (MPI_Request *) PetscMalloc((nsends+1)*sizeof(MPI_Request));CHKPTRQ(send_waits);
2400452661fSBarry Smith   starts     = (int *) PetscMalloc( (size+1)*sizeof(int) ); CHKPTRQ(starts);
2418965ea79SLois Curfman McInnes   starts[0]  = 0;
2428965ea79SLois Curfman McInnes   for ( i=1; i<size; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
2438965ea79SLois Curfman McInnes   for ( i=0; i<N; i++ ) {
2448965ea79SLois Curfman McInnes     svalues[starts[owner[i]]++] = rows[i];
2458965ea79SLois Curfman McInnes   }
2468965ea79SLois Curfman McInnes   ISRestoreIndices(is,&rows);
2478965ea79SLois Curfman McInnes 
2488965ea79SLois Curfman McInnes   starts[0] = 0;
2498965ea79SLois Curfman McInnes   for ( i=1; i<size+1; i++ ) { starts[i] = starts[i-1] + nprocs[i-1];}
2508965ea79SLois Curfman McInnes   count = 0;
2518965ea79SLois Curfman McInnes   for ( i=0; i<size; i++ ) {
2528965ea79SLois Curfman McInnes     if (procs[i]) {
253ca161407SBarry Smith       ierr = MPI_Isend(svalues+starts[i],nprocs[i],MPI_INT,i,tag,comm,send_waits+count++);CHKERRQ(ierr);
2548965ea79SLois Curfman McInnes     }
2558965ea79SLois Curfman McInnes   }
2560452661fSBarry Smith   PetscFree(starts);
2578965ea79SLois Curfman McInnes 
2588965ea79SLois Curfman McInnes   base = owners[rank];
2598965ea79SLois Curfman McInnes 
2608965ea79SLois Curfman McInnes   /*  wait on receives */
2610452661fSBarry Smith   lens   = (int *) PetscMalloc( 2*(nrecvs+1)*sizeof(int) ); CHKPTRQ(lens);
2628965ea79SLois Curfman McInnes   source = lens + nrecvs;
2638965ea79SLois Curfman McInnes   count  = nrecvs; slen = 0;
2648965ea79SLois Curfman McInnes   while (count) {
265ca161407SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
2668965ea79SLois Curfman McInnes     /* unpack receives into our local space */
267ca161407SBarry Smith     ierr = MPI_Get_count(&recv_status,MPI_INT,&n);CHKERRQ(ierr);
2688965ea79SLois Curfman McInnes     source[imdex]  = recv_status.MPI_SOURCE;
2698965ea79SLois Curfman McInnes     lens[imdex]  = n;
2708965ea79SLois Curfman McInnes     slen += n;
2718965ea79SLois Curfman McInnes     count--;
2728965ea79SLois Curfman McInnes   }
2730452661fSBarry Smith   PetscFree(recv_waits);
2748965ea79SLois Curfman McInnes 
2758965ea79SLois Curfman McInnes   /* move the data into the send scatter */
2760452661fSBarry Smith   lrows = (int *) PetscMalloc( (slen+1)*sizeof(int) ); CHKPTRQ(lrows);
2778965ea79SLois Curfman McInnes   count = 0;
2788965ea79SLois Curfman McInnes   for ( i=0; i<nrecvs; i++ ) {
2798965ea79SLois Curfman McInnes     values = rvalues + i*nmax;
2808965ea79SLois Curfman McInnes     for ( j=0; j<lens[i]; j++ ) {
2818965ea79SLois Curfman McInnes       lrows[count++] = values[j] - base;
2828965ea79SLois Curfman McInnes     }
2838965ea79SLois Curfman McInnes   }
2840452661fSBarry Smith   PetscFree(rvalues); PetscFree(lens);
2850452661fSBarry Smith   PetscFree(owner); PetscFree(nprocs);
2868965ea79SLois Curfman McInnes 
2878965ea79SLois Curfman McInnes   /* actually zap the local rows */
288029af93fSBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,slen,lrows,&istmp);CHKERRQ(ierr);
2898965ea79SLois Curfman McInnes   PLogObjectParent(A,istmp);
2900452661fSBarry Smith   PetscFree(lrows);
2918965ea79SLois Curfman McInnes   ierr = MatZeroRows(l->A,istmp,diag); CHKERRQ(ierr);
2928965ea79SLois Curfman McInnes   ierr = ISDestroy(istmp); CHKERRQ(ierr);
2938965ea79SLois Curfman McInnes 
2948965ea79SLois Curfman McInnes   /* wait on sends */
2958965ea79SLois Curfman McInnes   if (nsends) {
2967056b6fcSBarry Smith     send_status = (MPI_Status *) PetscMalloc(nsends*sizeof(MPI_Status));CHKPTRQ(send_status);
297ca161407SBarry Smith     ierr        = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
2980452661fSBarry Smith     PetscFree(send_status);
2998965ea79SLois Curfman McInnes   }
3000452661fSBarry Smith   PetscFree(send_waits); PetscFree(svalues);
3018965ea79SLois Curfman McInnes 
3023a40ed3dSBarry Smith   PetscFunctionReturn(0);
3038965ea79SLois Curfman McInnes }
3048965ea79SLois Curfman McInnes 
3055615d1e5SSatish Balay #undef __FUNC__
3065615d1e5SSatish Balay #define __FUNC__ "MatMult_MPIDense"
3078f6be9afSLois Curfman McInnes int MatMult_MPIDense(Mat mat,Vec xx,Vec yy)
3088965ea79SLois Curfman McInnes {
30939ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3108965ea79SLois Curfman McInnes   int          ierr;
311c456f294SBarry Smith 
3123a40ed3dSBarry Smith   PetscFunctionBegin;
31343a90d84SBarry Smith   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
31443a90d84SBarry Smith   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
31544cd7ae7SLois Curfman McInnes   ierr = MatMult_SeqDense(mdn->A,mdn->lvec,yy); CHKERRQ(ierr);
3163a40ed3dSBarry Smith   PetscFunctionReturn(0);
3178965ea79SLois Curfman McInnes }
3188965ea79SLois Curfman McInnes 
3195615d1e5SSatish Balay #undef __FUNC__
3205615d1e5SSatish Balay #define __FUNC__ "MatMultAdd_MPIDense"
3218f6be9afSLois Curfman McInnes int MatMultAdd_MPIDense(Mat mat,Vec xx,Vec yy,Vec zz)
3228965ea79SLois Curfman McInnes {
32339ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3248965ea79SLois Curfman McInnes   int          ierr;
325c456f294SBarry Smith 
3263a40ed3dSBarry Smith   PetscFunctionBegin;
32743a90d84SBarry Smith   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
32843a90d84SBarry Smith   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
32944cd7ae7SLois Curfman McInnes   ierr = MatMultAdd_SeqDense(mdn->A,mdn->lvec,yy,zz); CHKERRQ(ierr);
3303a40ed3dSBarry Smith   PetscFunctionReturn(0);
3318965ea79SLois Curfman McInnes }
3328965ea79SLois Curfman McInnes 
3335615d1e5SSatish Balay #undef __FUNC__
3345615d1e5SSatish Balay #define __FUNC__ "MatMultTrans_MPIDense"
3358f6be9afSLois Curfman McInnes int MatMultTrans_MPIDense(Mat A,Vec xx,Vec yy)
336096963f5SLois Curfman McInnes {
337096963f5SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
338096963f5SLois Curfman McInnes   int          ierr;
3393501a2bdSLois Curfman McInnes   Scalar       zero = 0.0;
340096963f5SLois Curfman McInnes 
3413a40ed3dSBarry Smith   PetscFunctionBegin;
3423501a2bdSLois Curfman McInnes   ierr = VecSet(&zero,yy); CHKERRQ(ierr);
34344cd7ae7SLois Curfman McInnes   ierr = MatMultTrans_SeqDense(a->A,xx,a->lvec); CHKERRQ(ierr);
344537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
345537820f0SBarry Smith   ierr = VecScatterEnd(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
3463a40ed3dSBarry Smith   PetscFunctionReturn(0);
347096963f5SLois Curfman McInnes }
348096963f5SLois Curfman McInnes 
3495615d1e5SSatish Balay #undef __FUNC__
3505615d1e5SSatish Balay #define __FUNC__ "MatMultTransAdd_MPIDense"
3518f6be9afSLois Curfman McInnes int MatMultTransAdd_MPIDense(Mat A,Vec xx,Vec yy,Vec zz)
352096963f5SLois Curfman McInnes {
353096963f5SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
354096963f5SLois Curfman McInnes   int          ierr;
355096963f5SLois Curfman McInnes 
3563a40ed3dSBarry Smith   PetscFunctionBegin;
3573501a2bdSLois Curfman McInnes   ierr = VecCopy(yy,zz); CHKERRQ(ierr);
35844cd7ae7SLois Curfman McInnes   ierr = MatMultTrans_SeqDense(a->A,xx,a->lvec); CHKERRQ(ierr);
359537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
360537820f0SBarry Smith   ierr = VecScatterEnd(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx); CHKERRQ(ierr);
3613a40ed3dSBarry Smith   PetscFunctionReturn(0);
362096963f5SLois Curfman McInnes }
363096963f5SLois Curfman McInnes 
3645615d1e5SSatish Balay #undef __FUNC__
3655615d1e5SSatish Balay #define __FUNC__ "MatGetDiagonal_MPIDense"
3668f6be9afSLois Curfman McInnes int MatGetDiagonal_MPIDense(Mat A,Vec v)
3678965ea79SLois Curfman McInnes {
36839ddd567SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
369096963f5SLois Curfman McInnes   Mat_SeqDense *aloc = (Mat_SeqDense *) a->A->data;
37044cd7ae7SLois Curfman McInnes   int          ierr, len, i, n, m = a->m, radd;
37144cd7ae7SLois Curfman McInnes   Scalar       *x, zero = 0.0;
372ed3cc1f0SBarry Smith 
3733a40ed3dSBarry Smith   PetscFunctionBegin;
37444cd7ae7SLois Curfman McInnes   VecSet(&zero,v);
375096963f5SLois Curfman McInnes   ierr = VecGetArray(v,&x); CHKERRQ(ierr);
376096963f5SLois Curfman McInnes   ierr = VecGetSize(v,&n); CHKERRQ(ierr);
377a8c6a408SBarry Smith   if (n != a->M) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Nonconforming mat and vec");
37844cd7ae7SLois Curfman McInnes   len = PetscMin(aloc->m,aloc->n);
3797ddc982cSLois Curfman McInnes   radd = a->rstart*m;
38044cd7ae7SLois Curfman McInnes   for ( i=0; i<len; i++ ) {
381096963f5SLois Curfman McInnes     x[i] = aloc->v[radd + i*m + i];
382096963f5SLois Curfman McInnes   }
3833a40ed3dSBarry Smith   PetscFunctionReturn(0);
3848965ea79SLois Curfman McInnes }
3858965ea79SLois Curfman McInnes 
3865615d1e5SSatish Balay #undef __FUNC__
3875615d1e5SSatish Balay #define __FUNC__ "MatDestroy_MPIDense"
388e1311b90SBarry Smith int MatDestroy_MPIDense(Mat mat)
3898965ea79SLois Curfman McInnes {
3903501a2bdSLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
3918965ea79SLois Curfman McInnes   int          ierr;
392ed3cc1f0SBarry Smith 
3933a40ed3dSBarry Smith   PetscFunctionBegin;
39494d884c6SBarry Smith   if (--mat->refct > 0) PetscFunctionReturn(0);
39594d884c6SBarry Smith 
39694d884c6SBarry Smith   if (mat->mapping) {
39794d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->mapping); CHKERRQ(ierr);
39894d884c6SBarry Smith   }
39994d884c6SBarry Smith   if (mat->bmapping) {
40094d884c6SBarry Smith     ierr = ISLocalToGlobalMappingDestroy(mat->bmapping); CHKERRQ(ierr);
40194d884c6SBarry Smith   }
4023a40ed3dSBarry Smith #if defined(USE_PETSC_LOG)
403e1311b90SBarry Smith   PLogObjectState((PetscObject)mat,"Rows=%d, Cols=%d",mdn->M,mdn->N);
4048965ea79SLois Curfman McInnes #endif
4058798bf22SSatish Balay   ierr = MatStashDestroy_Private(&mat->stash); CHKERRQ(ierr);
4060452661fSBarry Smith   PetscFree(mdn->rowners);
4073501a2bdSLois Curfman McInnes   ierr = MatDestroy(mdn->A); CHKERRQ(ierr);
4083501a2bdSLois Curfman McInnes   if (mdn->lvec)   VecDestroy(mdn->lvec);
4093501a2bdSLois Curfman McInnes   if (mdn->Mvctx)  VecScatterDestroy(mdn->Mvctx);
410622d7880SLois Curfman McInnes   if (mdn->factor) {
411622d7880SLois Curfman McInnes     if (mdn->factor->temp)   PetscFree(mdn->factor->temp);
412622d7880SLois Curfman McInnes     if (mdn->factor->tag)    PetscFree(mdn->factor->tag);
413622d7880SLois Curfman McInnes     if (mdn->factor->pivots) PetscFree(mdn->factor->pivots);
414622d7880SLois Curfman McInnes     PetscFree(mdn->factor);
415622d7880SLois Curfman McInnes   }
4160452661fSBarry Smith   PetscFree(mdn);
41761b13de0SBarry Smith   if (mat->rmap) {
41861b13de0SBarry Smith     ierr = MapDestroy(mat->rmap);CHKERRQ(ierr);
41961b13de0SBarry Smith   }
42061b13de0SBarry Smith   if (mat->cmap) {
42161b13de0SBarry Smith     ierr = MapDestroy(mat->cmap);CHKERRQ(ierr);
42290f02eecSBarry Smith   }
4238965ea79SLois Curfman McInnes   PLogObjectDestroy(mat);
4240452661fSBarry Smith   PetscHeaderDestroy(mat);
4253a40ed3dSBarry Smith   PetscFunctionReturn(0);
4268965ea79SLois Curfman McInnes }
42739ddd567SLois Curfman McInnes 
4285615d1e5SSatish Balay #undef __FUNC__
4295615d1e5SSatish Balay #define __FUNC__ "MatView_MPIDense_Binary"
43039ddd567SLois Curfman McInnes static int MatView_MPIDense_Binary(Mat mat,Viewer viewer)
4318965ea79SLois Curfman McInnes {
43239ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
4338965ea79SLois Curfman McInnes   int          ierr;
4347056b6fcSBarry Smith 
4353a40ed3dSBarry Smith   PetscFunctionBegin;
43639ddd567SLois Curfman McInnes   if (mdn->size == 1) {
43739ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
4388965ea79SLois Curfman McInnes   }
439a8c6a408SBarry Smith   else SETERRQ(PETSC_ERR_SUP,0,"Only uniprocessor output supported");
4403a40ed3dSBarry Smith   PetscFunctionReturn(0);
4418965ea79SLois Curfman McInnes }
4428965ea79SLois Curfman McInnes 
4435615d1e5SSatish Balay #undef __FUNC__
4445615d1e5SSatish Balay #define __FUNC__ "MatView_MPIDense_ASCII"
44539ddd567SLois Curfman McInnes static int MatView_MPIDense_ASCII(Mat mat,Viewer viewer)
4468965ea79SLois Curfman McInnes {
44739ddd567SLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) mat->data;
44877ed5343SBarry Smith   int          ierr, format, size = mdn->size, rank = mdn->rank;
4498965ea79SLois Curfman McInnes   FILE         *fd;
45019bcc07fSBarry Smith   ViewerType   vtype;
4518965ea79SLois Curfman McInnes 
4523a40ed3dSBarry Smith   PetscFunctionBegin;
4533a40ed3dSBarry Smith   ierr = ViewerGetType(viewer,&vtype);CHKERRQ(ierr);
45490ace30eSBarry Smith   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
45590ace30eSBarry Smith   ierr = ViewerGetFormat(viewer,&format);
456639f9d9dSBarry Smith   if (format == VIEWER_FORMAT_ASCII_INFO_LONG) {
4574e220ebcSLois Curfman McInnes     MatInfo info;
4584e220ebcSLois Curfman McInnes     ierr = MatGetInfo(mat,MAT_LOCAL,&info);
45977c4ece6SBarry Smith     PetscSequentialPhaseBegin(mat->comm,1);
4604e220ebcSLois Curfman McInnes       fprintf(fd,"  [%d] local rows %d nz %d nz alloced %d mem %d \n",rank,mdn->m,
4614e220ebcSLois Curfman McInnes          (int)info.nz_used,(int)info.nz_allocated,(int)info.memory);
462096963f5SLois Curfman McInnes       fflush(fd);
46377c4ece6SBarry Smith     PetscSequentialPhaseEnd(mat->comm,1);
4643501a2bdSLois Curfman McInnes     ierr = VecScatterView(mdn->Mvctx,viewer); CHKERRQ(ierr);
4653a40ed3dSBarry Smith     PetscFunctionReturn(0);
46696f6c058SBarry Smith   } else if (format == VIEWER_FORMAT_ASCII_INFO) {
4673a40ed3dSBarry Smith     PetscFunctionReturn(0);
4688965ea79SLois Curfman McInnes   }
46977ed5343SBarry Smith 
4708965ea79SLois Curfman McInnes   if (size == 1) {
47139ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer); CHKERRQ(ierr);
4723a40ed3dSBarry Smith   } else {
4738965ea79SLois Curfman McInnes     /* assemble the entire matrix onto first processor. */
4748965ea79SLois Curfman McInnes     Mat          A;
47539ddd567SLois Curfman McInnes     int          M = mdn->M, N = mdn->N,m,row,i, nz, *cols;
47639ddd567SLois Curfman McInnes     Scalar       *vals;
47739ddd567SLois Curfman McInnes     Mat_SeqDense *Amdn = (Mat_SeqDense*) mdn->A->data;
4788965ea79SLois Curfman McInnes 
4798965ea79SLois Curfman McInnes     if (!rank) {
4800513a670SBarry Smith       ierr = MatCreateMPIDense(mat->comm,M,N,M,N,PETSC_NULL,&A); CHKERRQ(ierr);
4813a40ed3dSBarry Smith     } else {
4820513a670SBarry Smith       ierr = MatCreateMPIDense(mat->comm,0,N,M,N,PETSC_NULL,&A); CHKERRQ(ierr);
4838965ea79SLois Curfman McInnes     }
4848965ea79SLois Curfman McInnes     PLogObjectParent(mat,A);
4858965ea79SLois Curfman McInnes 
48639ddd567SLois Curfman McInnes     /* Copy the matrix ... This isn't the most efficient means,
48739ddd567SLois Curfman McInnes        but it's quick for now */
48839ddd567SLois Curfman McInnes     row = mdn->rstart; m = Amdn->m;
4898965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
49039ddd567SLois Curfman McInnes       ierr = MatGetRow(mat,row,&nz,&cols,&vals); CHKERRQ(ierr);
49139ddd567SLois Curfman McInnes       ierr = MatSetValues(A,1,&row,nz,cols,vals,INSERT_VALUES); CHKERRQ(ierr);
49239ddd567SLois Curfman McInnes       ierr = MatRestoreRow(mat,row,&nz,&cols,&vals); CHKERRQ(ierr);
49339ddd567SLois Curfman McInnes       row++;
4948965ea79SLois Curfman McInnes     }
4958965ea79SLois Curfman McInnes 
4966d4a8577SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4976d4a8577SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
4988965ea79SLois Curfman McInnes     if (!rank) {
49939ddd567SLois Curfman McInnes       ierr = MatView(((Mat_MPIDense*)(A->data))->A,viewer); CHKERRQ(ierr);
5008965ea79SLois Curfman McInnes     }
5018965ea79SLois Curfman McInnes     ierr = MatDestroy(A); CHKERRQ(ierr);
5028965ea79SLois Curfman McInnes   }
5033a40ed3dSBarry Smith   PetscFunctionReturn(0);
5048965ea79SLois Curfman McInnes }
5058965ea79SLois Curfman McInnes 
5065615d1e5SSatish Balay #undef __FUNC__
5075615d1e5SSatish Balay #define __FUNC__ "MatView_MPIDense"
508e1311b90SBarry Smith int MatView_MPIDense(Mat mat,Viewer viewer)
5098965ea79SLois Curfman McInnes {
51039ddd567SLois Curfman McInnes   int          ierr;
511bcd2baecSBarry Smith   ViewerType   vtype;
5128965ea79SLois Curfman McInnes 
513bcd2baecSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
5143f1db9ecSBarry Smith   if (PetscTypeCompare(vtype,ASCII_VIEWER)) {
51539ddd567SLois Curfman McInnes     ierr = MatView_MPIDense_ASCII(mat,viewer); CHKERRQ(ierr);
5163f1db9ecSBarry Smith   } else if (PetscTypeCompare(vtype,BINARY_VIEWER)) {
5173a40ed3dSBarry Smith     ierr = MatView_MPIDense_Binary(mat,viewer);CHKERRQ(ierr);
5185cd90555SBarry Smith   } else {
5195cd90555SBarry Smith     SETERRQ(1,1,"Viewer type not supported by PETSc object");
5208965ea79SLois Curfman McInnes   }
5213a40ed3dSBarry Smith   PetscFunctionReturn(0);
5228965ea79SLois Curfman McInnes }
5238965ea79SLois Curfman McInnes 
5245615d1e5SSatish Balay #undef __FUNC__
5255615d1e5SSatish Balay #define __FUNC__ "MatGetInfo_MPIDense"
5268f6be9afSLois Curfman McInnes int MatGetInfo_MPIDense(Mat A,MatInfoType flag,MatInfo *info)
5278965ea79SLois Curfman McInnes {
5283501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
5293501a2bdSLois Curfman McInnes   Mat          mdn = mat->A;
5304e220ebcSLois Curfman McInnes   int          ierr;
5314e220ebcSLois Curfman McInnes   double       isend[5], irecv[5];
5328965ea79SLois Curfman McInnes 
5333a40ed3dSBarry Smith   PetscFunctionBegin;
5344e220ebcSLois Curfman McInnes   info->rows_global    = (double)mat->M;
5354e220ebcSLois Curfman McInnes   info->columns_global = (double)mat->N;
5364e220ebcSLois Curfman McInnes   info->rows_local     = (double)mat->m;
5374e220ebcSLois Curfman McInnes   info->columns_local  = (double)mat->N;
5384e220ebcSLois Curfman McInnes   info->block_size     = 1.0;
5394e220ebcSLois Curfman McInnes   ierr = MatGetInfo(mdn,MAT_LOCAL,info); CHKERRQ(ierr);
5404e220ebcSLois Curfman McInnes   isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded;
5414e220ebcSLois Curfman McInnes   isend[3] = info->memory;  isend[4] = info->mallocs;
5428965ea79SLois Curfman McInnes   if (flag == MAT_LOCAL) {
5434e220ebcSLois Curfman McInnes     info->nz_used      = isend[0];
5444e220ebcSLois Curfman McInnes     info->nz_allocated = isend[1];
5454e220ebcSLois Curfman McInnes     info->nz_unneeded  = isend[2];
5464e220ebcSLois Curfman McInnes     info->memory       = isend[3];
5474e220ebcSLois Curfman McInnes     info->mallocs      = isend[4];
5488965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_MAX) {
549f7cdd7c9SBarry Smith     ierr = MPI_Allreduce(isend,irecv,5,MPI_DOUBLE,MPI_MAX,A->comm);CHKERRQ(ierr);
5504e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
5514e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
5524e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
5534e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
5544e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
5558965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_SUM) {
556f7cdd7c9SBarry Smith     ierr = MPI_Allreduce(isend,irecv,5,MPI_DOUBLE,MPI_SUM,A->comm);CHKERRQ(ierr);
5574e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
5584e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
5594e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
5604e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
5614e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
5628965ea79SLois Curfman McInnes   }
5634e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0; /* no parallel LU/ILU/Cholesky */
5644e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
5654e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
5663a40ed3dSBarry Smith   PetscFunctionReturn(0);
5678965ea79SLois Curfman McInnes }
5688965ea79SLois Curfman McInnes 
5698c469469SLois Curfman McInnes /* extern int MatLUFactorSymbolic_MPIDense(Mat,IS,IS,double,Mat*);
5708aaee692SLois Curfman McInnes    extern int MatLUFactorNumeric_MPIDense(Mat,Mat*);
5718aaee692SLois Curfman McInnes    extern int MatLUFactor_MPIDense(Mat,IS,IS,double);
5728aaee692SLois Curfman McInnes    extern int MatSolve_MPIDense(Mat,Vec,Vec);
5738c469469SLois Curfman McInnes    extern int MatSolveAdd_MPIDense(Mat,Vec,Vec,Vec);
5748aaee692SLois Curfman McInnes    extern int MatSolveTrans_MPIDense(Mat,Vec,Vec);
5758aaee692SLois Curfman McInnes    extern int MatSolveTransAdd_MPIDense(Mat,Vec,Vec,Vec); */
5768aaee692SLois Curfman McInnes 
5775615d1e5SSatish Balay #undef __FUNC__
5785615d1e5SSatish Balay #define __FUNC__ "MatSetOption_MPIDense"
5798f6be9afSLois Curfman McInnes int MatSetOption_MPIDense(Mat A,MatOption op)
5808965ea79SLois Curfman McInnes {
58139ddd567SLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
5828965ea79SLois Curfman McInnes 
5833a40ed3dSBarry Smith   PetscFunctionBegin;
5846d4a8577SBarry Smith   if (op == MAT_NO_NEW_NONZERO_LOCATIONS ||
5856d4a8577SBarry Smith       op == MAT_YES_NEW_NONZERO_LOCATIONS ||
5864787f768SSatish Balay       op == MAT_NEW_NONZERO_LOCATION_ERR ||
5874787f768SSatish Balay       op == MAT_NEW_NONZERO_ALLOCATION_ERR ||
588219d9a1aSLois Curfman McInnes       op == MAT_COLUMNS_SORTED ||
589219d9a1aSLois Curfman McInnes       op == MAT_COLUMNS_UNSORTED) {
590b1fbbac0SLois Curfman McInnes         MatSetOption(a->A,op);
591b1fbbac0SLois Curfman McInnes   } else if (op == MAT_ROW_ORIENTED) {
592aeafbbfcSLois Curfman McInnes         a->roworiented = 1;
5938965ea79SLois Curfman McInnes         MatSetOption(a->A,op);
594b1fbbac0SLois Curfman McInnes   } else if (op == MAT_ROWS_SORTED ||
595219d9a1aSLois Curfman McInnes              op == MAT_ROWS_UNSORTED ||
5966d4a8577SBarry Smith              op == MAT_SYMMETRIC ||
5976d4a8577SBarry Smith              op == MAT_STRUCTURALLY_SYMMETRIC ||
598b51ba29fSSatish Balay              op == MAT_YES_NEW_DIAGONALS ||
599b51ba29fSSatish Balay              op == MAT_USE_HASH_TABLE) {
600981c4779SBarry Smith     PLogInfo(A,"MatSetOption_MPIDense:Option ignored\n");
6013a40ed3dSBarry Smith   } else if (op == MAT_COLUMN_ORIENTED) {
6023a40ed3dSBarry Smith     a->roworiented = 0; MatSetOption(a->A,op);
6033782ba37SSatish Balay   } else if (op == MAT_IGNORE_OFF_PROC_ENTRIES) {
6043782ba37SSatish Balay     a->donotstash = 1;
6053a40ed3dSBarry Smith   } else if (op == MAT_NO_NEW_DIAGONALS) {
6063a40ed3dSBarry Smith     SETERRQ(PETSC_ERR_SUP,0,"MAT_NO_NEW_DIAGONALS");
6073a40ed3dSBarry Smith   } else {
6083a40ed3dSBarry Smith     SETERRQ(PETSC_ERR_SUP,0,"unknown option");
6093a40ed3dSBarry Smith   }
6103a40ed3dSBarry Smith   PetscFunctionReturn(0);
6118965ea79SLois Curfman McInnes }
6128965ea79SLois Curfman McInnes 
6135615d1e5SSatish Balay #undef __FUNC__
6145615d1e5SSatish Balay #define __FUNC__ "MatGetSize_MPIDense"
6158f6be9afSLois Curfman McInnes int MatGetSize_MPIDense(Mat A,int *m,int *n)
6168965ea79SLois Curfman McInnes {
6173501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6183a40ed3dSBarry Smith 
6193a40ed3dSBarry Smith   PetscFunctionBegin;
6208965ea79SLois Curfman McInnes   *m = mat->M; *n = mat->N;
6213a40ed3dSBarry Smith   PetscFunctionReturn(0);
6228965ea79SLois Curfman McInnes }
6238965ea79SLois Curfman McInnes 
6245615d1e5SSatish Balay #undef __FUNC__
6255615d1e5SSatish Balay #define __FUNC__ "MatGetLocalSize_MPIDense"
6268f6be9afSLois Curfman McInnes int MatGetLocalSize_MPIDense(Mat A,int *m,int *n)
6278965ea79SLois Curfman McInnes {
6283501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6293a40ed3dSBarry Smith 
6303a40ed3dSBarry Smith   PetscFunctionBegin;
6318965ea79SLois Curfman McInnes   *m = mat->m; *n = mat->N;
6323a40ed3dSBarry Smith   PetscFunctionReturn(0);
6338965ea79SLois Curfman McInnes }
6348965ea79SLois Curfman McInnes 
6355615d1e5SSatish Balay #undef __FUNC__
6365615d1e5SSatish Balay #define __FUNC__ "MatGetOwnershipRange_MPIDense"
6378f6be9afSLois Curfman McInnes int MatGetOwnershipRange_MPIDense(Mat A,int *m,int *n)
6388965ea79SLois Curfman McInnes {
6393501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6403a40ed3dSBarry Smith 
6413a40ed3dSBarry Smith   PetscFunctionBegin;
6428965ea79SLois Curfman McInnes   *m = mat->rstart; *n = mat->rend;
6433a40ed3dSBarry Smith   PetscFunctionReturn(0);
6448965ea79SLois Curfman McInnes }
6458965ea79SLois Curfman McInnes 
6465615d1e5SSatish Balay #undef __FUNC__
6475615d1e5SSatish Balay #define __FUNC__ "MatGetRow_MPIDense"
6488f6be9afSLois Curfman McInnes int MatGetRow_MPIDense(Mat A,int row,int *nz,int **idx,Scalar **v)
6498965ea79SLois Curfman McInnes {
6503501a2bdSLois Curfman McInnes   Mat_MPIDense *mat = (Mat_MPIDense *) A->data;
6513a40ed3dSBarry Smith   int          lrow, rstart = mat->rstart, rend = mat->rend,ierr;
6528965ea79SLois Curfman McInnes 
6533a40ed3dSBarry Smith   PetscFunctionBegin;
654a8c6a408SBarry Smith   if (row < rstart || row >= rend) SETERRQ(PETSC_ERR_SUP,0,"only local rows")
6558965ea79SLois Curfman McInnes   lrow = row - rstart;
6563a40ed3dSBarry Smith   ierr = MatGetRow(mat->A,lrow,nz,idx,v);CHKERRQ(ierr);
6573a40ed3dSBarry Smith   PetscFunctionReturn(0);
6588965ea79SLois Curfman McInnes }
6598965ea79SLois Curfman McInnes 
6605615d1e5SSatish Balay #undef __FUNC__
6615615d1e5SSatish Balay #define __FUNC__ "MatRestoreRow_MPIDense"
6628f6be9afSLois Curfman McInnes int MatRestoreRow_MPIDense(Mat mat,int row,int *nz,int **idx,Scalar **v)
6638965ea79SLois Curfman McInnes {
6643a40ed3dSBarry Smith   PetscFunctionBegin;
6650452661fSBarry Smith   if (idx) PetscFree(*idx);
6660452661fSBarry Smith   if (v) PetscFree(*v);
6673a40ed3dSBarry Smith   PetscFunctionReturn(0);
6688965ea79SLois Curfman McInnes }
6698965ea79SLois Curfman McInnes 
6705615d1e5SSatish Balay #undef __FUNC__
6715615d1e5SSatish Balay #define __FUNC__ "MatNorm_MPIDense"
6728f6be9afSLois Curfman McInnes int MatNorm_MPIDense(Mat A,NormType type,double *norm)
673096963f5SLois Curfman McInnes {
6743501a2bdSLois Curfman McInnes   Mat_MPIDense *mdn = (Mat_MPIDense *) A->data;
6753501a2bdSLois Curfman McInnes   Mat_SeqDense *mat = (Mat_SeqDense*) mdn->A->data;
6763501a2bdSLois Curfman McInnes   int          ierr, i, j;
6773501a2bdSLois Curfman McInnes   double       sum = 0.0;
6783501a2bdSLois Curfman McInnes   Scalar       *v = mat->v;
6793501a2bdSLois Curfman McInnes 
6803a40ed3dSBarry Smith   PetscFunctionBegin;
6813501a2bdSLois Curfman McInnes   if (mdn->size == 1) {
6823501a2bdSLois Curfman McInnes     ierr =  MatNorm(mdn->A,type,norm); CHKERRQ(ierr);
6833501a2bdSLois Curfman McInnes   } else {
6843501a2bdSLois Curfman McInnes     if (type == NORM_FROBENIUS) {
6853501a2bdSLois Curfman McInnes       for (i=0; i<mat->n*mat->m; i++ ) {
6863a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX)
687e20fef11SSatish Balay         sum += PetscReal(PetscConj(*v)*(*v)); v++;
6883501a2bdSLois Curfman McInnes #else
6893501a2bdSLois Curfman McInnes         sum += (*v)*(*v); v++;
6903501a2bdSLois Curfman McInnes #endif
6913501a2bdSLois Curfman McInnes       }
692ca161407SBarry Smith       ierr = MPI_Allreduce(&sum,norm,1,MPI_DOUBLE,MPI_SUM,A->comm);CHKERRQ(ierr);
6933501a2bdSLois Curfman McInnes       *norm = sqrt(*norm);
6943501a2bdSLois Curfman McInnes       PLogFlops(2*mat->n*mat->m);
6953a40ed3dSBarry Smith     } else if (type == NORM_1) {
6963501a2bdSLois Curfman McInnes       double *tmp, *tmp2;
6970452661fSBarry Smith       tmp  = (double *) PetscMalloc( 2*mdn->N*sizeof(double) ); CHKPTRQ(tmp);
6983501a2bdSLois Curfman McInnes       tmp2 = tmp + mdn->N;
699cddf8d76SBarry Smith       PetscMemzero(tmp,2*mdn->N*sizeof(double));
700096963f5SLois Curfman McInnes       *norm = 0.0;
7013501a2bdSLois Curfman McInnes       v = mat->v;
7023501a2bdSLois Curfman McInnes       for ( j=0; j<mat->n; j++ ) {
7033501a2bdSLois Curfman McInnes         for ( i=0; i<mat->m; i++ ) {
70467e560aaSBarry Smith           tmp[j] += PetscAbsScalar(*v);  v++;
7053501a2bdSLois Curfman McInnes         }
7063501a2bdSLois Curfman McInnes       }
707ca161407SBarry Smith       ierr = MPI_Allreduce(tmp,tmp2,mdn->N,MPI_DOUBLE,MPI_SUM,A->comm);CHKERRQ(ierr);
7083501a2bdSLois Curfman McInnes       for ( j=0; j<mdn->N; j++ ) {
7093501a2bdSLois Curfman McInnes         if (tmp2[j] > *norm) *norm = tmp2[j];
7103501a2bdSLois Curfman McInnes       }
7110452661fSBarry Smith       PetscFree(tmp);
7123501a2bdSLois Curfman McInnes       PLogFlops(mat->n*mat->m);
7133a40ed3dSBarry Smith     } else if (type == NORM_INFINITY) { /* max row norm */
7143501a2bdSLois Curfman McInnes       double ntemp;
7153501a2bdSLois Curfman McInnes       ierr = MatNorm(mdn->A,type,&ntemp); CHKERRQ(ierr);
716ca161407SBarry Smith       ierr = MPI_Allreduce(&ntemp,norm,1,MPI_DOUBLE,MPI_MAX,A->comm);CHKERRQ(ierr);
7173a40ed3dSBarry Smith     } else {
718a8c6a408SBarry Smith       SETERRQ(PETSC_ERR_SUP,0,"No support for two norm");
7193501a2bdSLois Curfman McInnes     }
7203501a2bdSLois Curfman McInnes   }
7213a40ed3dSBarry Smith   PetscFunctionReturn(0);
7223501a2bdSLois Curfman McInnes }
7233501a2bdSLois Curfman McInnes 
7245615d1e5SSatish Balay #undef __FUNC__
7255615d1e5SSatish Balay #define __FUNC__ "MatTranspose_MPIDense"
7268f6be9afSLois Curfman McInnes int MatTranspose_MPIDense(Mat A,Mat *matout)
7273501a2bdSLois Curfman McInnes {
7283501a2bdSLois Curfman McInnes   Mat_MPIDense *a = (Mat_MPIDense *) A->data;
7293501a2bdSLois Curfman McInnes   Mat_SeqDense *Aloc = (Mat_SeqDense *) a->A->data;
7303501a2bdSLois Curfman McInnes   Mat          B;
7313501a2bdSLois Curfman McInnes   int          M = a->M, N = a->N, m, n, *rwork, rstart = a->rstart;
7323501a2bdSLois Curfman McInnes   int          j, i, ierr;
7333501a2bdSLois Curfman McInnes   Scalar       *v;
7343501a2bdSLois Curfman McInnes 
7353a40ed3dSBarry Smith   PetscFunctionBegin;
7367056b6fcSBarry Smith   if (matout == PETSC_NULL && M != N) {
737a8c6a408SBarry Smith     SETERRQ(PETSC_ERR_SUP,0,"Supports square matrix only in-place");
7387056b6fcSBarry Smith   }
7397056b6fcSBarry Smith   ierr = MatCreateMPIDense(A->comm,PETSC_DECIDE,PETSC_DECIDE,N,M,PETSC_NULL,&B);CHKERRQ(ierr);
7403501a2bdSLois Curfman McInnes 
7413501a2bdSLois Curfman McInnes   m = Aloc->m; n = Aloc->n; v = Aloc->v;
7420452661fSBarry Smith   rwork = (int *) PetscMalloc(n*sizeof(int)); CHKPTRQ(rwork);
7433501a2bdSLois Curfman McInnes   for ( j=0; j<n; j++ ) {
7443501a2bdSLois Curfman McInnes     for (i=0; i<m; i++) rwork[i] = rstart + i;
7453501a2bdSLois Curfman McInnes     ierr = MatSetValues(B,1,&j,m,rwork,v,INSERT_VALUES); CHKERRQ(ierr);
7463501a2bdSLois Curfman McInnes     v   += m;
7473501a2bdSLois Curfman McInnes   }
7480452661fSBarry Smith   PetscFree(rwork);
7496d4a8577SBarry Smith   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
7506d4a8577SBarry Smith   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
7513638b69dSLois Curfman McInnes   if (matout != PETSC_NULL) {
7523501a2bdSLois Curfman McInnes     *matout = B;
7533501a2bdSLois Curfman McInnes   } else {
754f830108cSBarry Smith     PetscOps *Abops;
75509dc0095SBarry Smith     MatOps   Aops;
756f830108cSBarry Smith 
7573501a2bdSLois Curfman McInnes     /* This isn't really an in-place transpose, but free data struct from a */
7580452661fSBarry Smith     PetscFree(a->rowners);
7593501a2bdSLois Curfman McInnes     ierr = MatDestroy(a->A); CHKERRQ(ierr);
7603501a2bdSLois Curfman McInnes     if (a->lvec) VecDestroy(a->lvec);
7613501a2bdSLois Curfman McInnes     if (a->Mvctx) VecScatterDestroy(a->Mvctx);
7620452661fSBarry Smith     PetscFree(a);
763f830108cSBarry Smith 
764f830108cSBarry Smith     /*
765f830108cSBarry Smith          This is horrible, horrible code. We need to keep the
766f830108cSBarry Smith       A pointers for the bops and ops but copy everything
767f830108cSBarry Smith       else from C.
768f830108cSBarry Smith     */
769f830108cSBarry Smith     Abops = A->bops;
770f830108cSBarry Smith     Aops  = A->ops;
771f09e8eb9SSatish Balay     PetscMemcpy(A,B,sizeof(struct _p_Mat));
772f830108cSBarry Smith     A->bops = Abops;
773f830108cSBarry Smith     A->ops  = Aops;
774f830108cSBarry Smith 
7750452661fSBarry Smith     PetscHeaderDestroy(B);
7763501a2bdSLois Curfman McInnes   }
7773a40ed3dSBarry Smith   PetscFunctionReturn(0);
778096963f5SLois Curfman McInnes }
779096963f5SLois Curfman McInnes 
780eadb2fb4SBarry Smith #include "pinclude/blaslapack.h"
7815615d1e5SSatish Balay #undef __FUNC__
7825615d1e5SSatish Balay #define __FUNC__ "MatScale_MPIDense"
7838f6be9afSLois Curfman McInnes int MatScale_MPIDense(Scalar *alpha,Mat inA)
78444cd7ae7SLois Curfman McInnes {
78544cd7ae7SLois Curfman McInnes   Mat_MPIDense *A = (Mat_MPIDense *) inA->data;
78644cd7ae7SLois Curfman McInnes   Mat_SeqDense *a = (Mat_SeqDense *) A->A->data;
78744cd7ae7SLois Curfman McInnes   int          one = 1, nz;
78844cd7ae7SLois Curfman McInnes 
7893a40ed3dSBarry Smith   PetscFunctionBegin;
79044cd7ae7SLois Curfman McInnes   nz = a->m*a->n;
79144cd7ae7SLois Curfman McInnes   BLscal_( &nz, alpha, a->v, &one );
79244cd7ae7SLois Curfman McInnes   PLogFlops(nz);
7933a40ed3dSBarry Smith   PetscFunctionReturn(0);
79444cd7ae7SLois Curfman McInnes }
79544cd7ae7SLois Curfman McInnes 
7965609ef8eSBarry Smith static int MatDuplicate_MPIDense(Mat,MatDuplicateOption,Mat *);
7977b2a1423SBarry Smith extern int MatGetSubMatrices_MPIDense(Mat,int,IS *,IS *,MatReuse,Mat **);
7988965ea79SLois Curfman McInnes 
7998965ea79SLois Curfman McInnes /* -------------------------------------------------------------------*/
80009dc0095SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_MPIDense,
80109dc0095SBarry Smith        MatGetRow_MPIDense,
80209dc0095SBarry Smith        MatRestoreRow_MPIDense,
80309dc0095SBarry Smith        MatMult_MPIDense,
80409dc0095SBarry Smith        MatMultAdd_MPIDense,
80509dc0095SBarry Smith        MatMultTrans_MPIDense,
80609dc0095SBarry Smith        MatMultTransAdd_MPIDense,
8078965ea79SLois Curfman McInnes        0,
80809dc0095SBarry Smith        0,
80909dc0095SBarry Smith        0,
81009dc0095SBarry Smith        0,
81109dc0095SBarry Smith        0,
81209dc0095SBarry Smith        0,
81309dc0095SBarry Smith        0,
81409dc0095SBarry Smith        MatTranspose_MPIDense,
81509dc0095SBarry Smith        MatGetInfo_MPIDense,0,
81609dc0095SBarry Smith        MatGetDiagonal_MPIDense,
81709dc0095SBarry Smith        0,
81809dc0095SBarry Smith        MatNorm_MPIDense,
81909dc0095SBarry Smith        MatAssemblyBegin_MPIDense,
82009dc0095SBarry Smith        MatAssemblyEnd_MPIDense,
82109dc0095SBarry Smith        0,
82209dc0095SBarry Smith        MatSetOption_MPIDense,
82309dc0095SBarry Smith        MatZeroEntries_MPIDense,
82409dc0095SBarry Smith        MatZeroRows_MPIDense,
82509dc0095SBarry Smith        0,
82609dc0095SBarry Smith        0,
82709dc0095SBarry Smith        0,
82809dc0095SBarry Smith        0,
82909dc0095SBarry Smith        MatGetSize_MPIDense,
83009dc0095SBarry Smith        MatGetLocalSize_MPIDense,
83139ddd567SLois Curfman McInnes        MatGetOwnershipRange_MPIDense,
83209dc0095SBarry Smith        0,
83309dc0095SBarry Smith        0,
83409dc0095SBarry Smith        MatGetArray_MPIDense,
83509dc0095SBarry Smith        MatRestoreArray_MPIDense,
8365609ef8eSBarry Smith        MatDuplicate_MPIDense,
83709dc0095SBarry Smith        0,
83809dc0095SBarry Smith        0,
83909dc0095SBarry Smith        0,
84009dc0095SBarry Smith        0,
84109dc0095SBarry Smith        0,
8422ce60cd0SSatish Balay        MatGetSubMatrices_MPIDense,
84309dc0095SBarry Smith        0,
84409dc0095SBarry Smith        MatGetValues_MPIDense,
84509dc0095SBarry Smith        0,
84609dc0095SBarry Smith        0,
84709dc0095SBarry Smith        MatScale_MPIDense,
84809dc0095SBarry Smith        0,
84909dc0095SBarry Smith        0,
85009dc0095SBarry Smith        0,
85109dc0095SBarry Smith        MatGetBlockSize_MPIDense,
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        0,
86109dc0095SBarry Smith        0,
86209dc0095SBarry Smith        0,
86309dc0095SBarry Smith        0,
86409dc0095SBarry Smith        MatGetMaps_Petsc};
8658965ea79SLois Curfman McInnes 
8665615d1e5SSatish Balay #undef __FUNC__
8675615d1e5SSatish Balay #define __FUNC__ "MatCreateMPIDense"
8688965ea79SLois Curfman McInnes /*@C
86939ddd567SLois Curfman McInnes    MatCreateMPIDense - Creates a sparse parallel matrix in dense format.
8708965ea79SLois Curfman McInnes 
871db81eaa0SLois Curfman McInnes    Collective on MPI_Comm
872db81eaa0SLois Curfman McInnes 
8738965ea79SLois Curfman McInnes    Input Parameters:
874db81eaa0SLois Curfman McInnes +  comm - MPI communicator
8758965ea79SLois Curfman McInnes .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
876db81eaa0SLois Curfman McInnes .  n - number of local columns (or PETSC_DECIDE to have calculated if N is given)
8778965ea79SLois Curfman McInnes .  M - number of global rows (or PETSC_DECIDE to have calculated if m is given)
878db81eaa0SLois Curfman McInnes .  N - number of global columns (or PETSC_DECIDE to have calculated if n is given)
879db81eaa0SLois Curfman McInnes -  data - optional location of matrix data.  Set data=PETSC_NULL for PETSc
880dfc5480cSLois Curfman McInnes    to control all matrix memory allocation.
8818965ea79SLois Curfman McInnes 
8828965ea79SLois Curfman McInnes    Output Parameter:
883477f1c0bSLois Curfman McInnes .  A - the matrix
8848965ea79SLois Curfman McInnes 
885b259b22eSLois Curfman McInnes    Notes:
88639ddd567SLois Curfman McInnes    The dense format is fully compatible with standard Fortran 77
88739ddd567SLois Curfman McInnes    storage by columns.
8888965ea79SLois Curfman McInnes 
88918f449edSLois Curfman McInnes    The data input variable is intended primarily for Fortran programmers
89018f449edSLois Curfman McInnes    who wish to allocate their own matrix memory space.  Most users should
891b4fd4287SBarry Smith    set data=PETSC_NULL.
89218f449edSLois Curfman McInnes 
8938965ea79SLois Curfman McInnes    The user MUST specify either the local or global matrix dimensions
8948965ea79SLois Curfman McInnes    (possibly both).
8958965ea79SLois Curfman McInnes 
8963501a2bdSLois Curfman McInnes    Currently, the only parallel dense matrix decomposition is by rows,
8973501a2bdSLois Curfman McInnes    so that n=N and each submatrix owns all of the global columns.
8983501a2bdSLois Curfman McInnes 
899027ccd11SLois Curfman McInnes    Level: intermediate
900027ccd11SLois Curfman McInnes 
90139ddd567SLois Curfman McInnes .keywords: matrix, dense, parallel
9028965ea79SLois Curfman McInnes 
90339ddd567SLois Curfman McInnes .seealso: MatCreate(), MatCreateSeqDense(), MatSetValues()
9048965ea79SLois Curfman McInnes @*/
905477f1c0bSLois Curfman McInnes int MatCreateMPIDense(MPI_Comm comm,int m,int n,int M,int N,Scalar *data,Mat *A)
9068965ea79SLois Curfman McInnes {
9078965ea79SLois Curfman McInnes   Mat          mat;
90839ddd567SLois Curfman McInnes   Mat_MPIDense *a;
90925cdf11fSBarry Smith   int          ierr, i,flg;
9108965ea79SLois Curfman McInnes 
9113a40ed3dSBarry Smith   PetscFunctionBegin;
912ed2daf61SLois Curfman McInnes   /* Note:  For now, when data is specified above, this assumes the user correctly
913ed2daf61SLois Curfman McInnes    allocates the local dense storage space.  We should add error checking. */
91418f449edSLois Curfman McInnes 
915477f1c0bSLois Curfman McInnes   *A = 0;
9163f1db9ecSBarry Smith   PetscHeaderCreate(mat,_p_Mat,struct _MatOps,MAT_COOKIE,MATMPIDENSE,"Mat",comm,MatDestroy,MatView);
9178965ea79SLois Curfman McInnes   PLogObjectCreate(mat);
9180452661fSBarry Smith   mat->data       = (void *) (a = PetscNew(Mat_MPIDense)); CHKPTRQ(a);
91909dc0095SBarry Smith   PetscMemcpy(mat->ops,&MatOps_Values,sizeof(struct _MatOps));
920e1311b90SBarry Smith   mat->ops->destroy    = MatDestroy_MPIDense;
921e1311b90SBarry Smith   mat->ops->view       = MatView_MPIDense;
9228965ea79SLois Curfman McInnes   mat->factor          = 0;
92390f02eecSBarry Smith   mat->mapping         = 0;
9248965ea79SLois Curfman McInnes 
925622d7880SLois Curfman McInnes   a->factor       = 0;
926e0fa3b82SLois Curfman McInnes   mat->insertmode = NOT_SET_VALUES;
927*d132466eSBarry Smith   ierr = MPI_Comm_rank(comm,&a->rank);CHKERRQ(ierr);
928*d132466eSBarry Smith   ierr = MPI_Comm_size(comm,&a->size);CHKERRQ(ierr);
9298965ea79SLois Curfman McInnes 
93096f6c058SBarry Smith   ierr = PetscSplitOwnership(comm,&m,&M);CHKERRQ(ierr);
93139ddd567SLois Curfman McInnes 
932c7fcc2eaSBarry Smith   /*
933c7fcc2eaSBarry Smith      The computation of n is wrong below, n should represent the number of local
934c7fcc2eaSBarry Smith      rows in the right (column vector)
935c7fcc2eaSBarry Smith   */
936c7fcc2eaSBarry Smith 
93739ddd567SLois Curfman McInnes   /* each row stores all columns */
93839ddd567SLois Curfman McInnes   if (N == PETSC_DECIDE) N = n;
939d7e8b826SBarry Smith   if (n == PETSC_DECIDE) {n = N/a->size + ((N % a->size) > a->rank);}
940a8c6a408SBarry Smith   /*  if (n != N) SETERRQ(PETSC_ERR_SUP,0,"For now, only n=N is supported"); */
941aca0ad90SLois Curfman McInnes   a->N = mat->N = N;
942aca0ad90SLois Curfman McInnes   a->M = mat->M = M;
943aca0ad90SLois Curfman McInnes   a->m = mat->m = m;
944aca0ad90SLois Curfman McInnes   a->n = mat->n = n;
9458965ea79SLois Curfman McInnes 
946c7fcc2eaSBarry Smith   /* the information in the maps duplicates the information computed below, eventually
947c7fcc2eaSBarry Smith      we should remove the duplicate information that is not contained in the maps */
948488ecbafSBarry Smith   ierr = MapCreateMPI(comm,m,M,&mat->rmap);CHKERRQ(ierr);
94996f6c058SBarry Smith   ierr = MapCreateMPI(comm,PETSC_DECIDE,N,&mat->cmap);CHKERRQ(ierr);
950c7fcc2eaSBarry Smith 
9518965ea79SLois Curfman McInnes   /* build local table of row and column ownerships */
952d7e8b826SBarry Smith   a->rowners = (int *) PetscMalloc(2*(a->size+2)*sizeof(int)); CHKPTRQ(a->rowners);
953d7e8b826SBarry Smith   a->cowners = a->rowners + a->size + 1;
954f09e8eb9SSatish Balay   PLogObjectMemory(mat,2*(a->size+2)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_MPIDense));
955ca161407SBarry Smith   ierr = MPI_Allgather(&m,1,MPI_INT,a->rowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
9568965ea79SLois Curfman McInnes   a->rowners[0] = 0;
9578965ea79SLois Curfman McInnes   for ( i=2; i<=a->size; i++ ) {
9588965ea79SLois Curfman McInnes     a->rowners[i] += a->rowners[i-1];
9598965ea79SLois Curfman McInnes   }
9608965ea79SLois Curfman McInnes   a->rstart = a->rowners[a->rank];
9618965ea79SLois Curfman McInnes   a->rend   = a->rowners[a->rank+1];
962ca161407SBarry Smith   ierr      = MPI_Allgather(&n,1,MPI_INT,a->cowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
963d7e8b826SBarry Smith   a->cowners[0] = 0;
964d7e8b826SBarry Smith   for ( i=2; i<=a->size; i++ ) {
965d7e8b826SBarry Smith     a->cowners[i] += a->cowners[i-1];
966d7e8b826SBarry Smith   }
9678965ea79SLois Curfman McInnes 
968029af93fSBarry Smith   ierr = MatCreateSeqDense(PETSC_COMM_SELF,m,N,data,&a->A); CHKERRQ(ierr);
9698965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->A);
9708965ea79SLois Curfman McInnes 
9718965ea79SLois Curfman McInnes   /* build cache for off array entries formed */
9723782ba37SSatish Balay   a->donotstash = 0;
9738798bf22SSatish Balay   ierr = MatStashCreate_Private(comm,1,&mat->stash); CHKERRQ(ierr);
9748965ea79SLois Curfman McInnes 
9758965ea79SLois Curfman McInnes   /* stuff used for matrix vector multiply */
9768965ea79SLois Curfman McInnes   a->lvec        = 0;
9778965ea79SLois Curfman McInnes   a->Mvctx       = 0;
97839b7565bSBarry Smith   a->roworiented = 1;
9798965ea79SLois Curfman McInnes 
980477f1c0bSLois Curfman McInnes   *A = mat;
98125cdf11fSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-help",&flg); CHKERRQ(ierr);
98225cdf11fSBarry Smith   if (flg) {
9838c469469SLois Curfman McInnes     ierr = MatPrintHelp(mat); CHKERRQ(ierr);
9848c469469SLois Curfman McInnes   }
9853a40ed3dSBarry Smith   PetscFunctionReturn(0);
9868965ea79SLois Curfman McInnes }
9878965ea79SLois Curfman McInnes 
9885615d1e5SSatish Balay #undef __FUNC__
9895609ef8eSBarry Smith #define __FUNC__ "MatDuplicate_MPIDense"
9905609ef8eSBarry Smith static int MatDuplicate_MPIDense(Mat A,MatDuplicateOption cpvalues,Mat *newmat)
9918965ea79SLois Curfman McInnes {
9928965ea79SLois Curfman McInnes   Mat          mat;
9933501a2bdSLois Curfman McInnes   Mat_MPIDense *a,*oldmat = (Mat_MPIDense *) A->data;
99439ddd567SLois Curfman McInnes   int          ierr;
9952ba99913SLois Curfman McInnes   FactorCtx    *factor;
9968965ea79SLois Curfman McInnes 
9973a40ed3dSBarry Smith   PetscFunctionBegin;
9988965ea79SLois Curfman McInnes   *newmat       = 0;
9993f1db9ecSBarry Smith   PetscHeaderCreate(mat,_p_Mat,struct _MatOps,MAT_COOKIE,MATMPIDENSE,"Mat",A->comm,MatDestroy,MatView);
10008965ea79SLois Curfman McInnes   PLogObjectCreate(mat);
10010452661fSBarry Smith   mat->data      = (void *) (a = PetscNew(Mat_MPIDense)); CHKPTRQ(a);
100209dc0095SBarry Smith   PetscMemcpy(mat->ops,&MatOps_Values,sizeof(struct _MatOps));
1003e1311b90SBarry Smith   mat->ops->destroy   = MatDestroy_MPIDense;
1004e1311b90SBarry Smith   mat->ops->view      = MatView_MPIDense;
10053501a2bdSLois Curfman McInnes   mat->factor         = A->factor;
1006c456f294SBarry Smith   mat->assembled      = PETSC_TRUE;
10078965ea79SLois Curfman McInnes 
100844cd7ae7SLois Curfman McInnes   a->m = mat->m = oldmat->m;
100944cd7ae7SLois Curfman McInnes   a->n = mat->n = oldmat->n;
101044cd7ae7SLois Curfman McInnes   a->M = mat->M = oldmat->M;
101144cd7ae7SLois Curfman McInnes   a->N = mat->N = oldmat->N;
10122ba99913SLois Curfman McInnes   if (oldmat->factor) {
10132ba99913SLois Curfman McInnes     a->factor = (FactorCtx *) (factor = PetscNew(FactorCtx)); CHKPTRQ(factor);
10142ba99913SLois Curfman McInnes     /* copy factor contents ... add this code! */
10152ba99913SLois Curfman McInnes   } else a->factor = 0;
10168965ea79SLois Curfman McInnes 
10178965ea79SLois Curfman McInnes   a->rstart       = oldmat->rstart;
10188965ea79SLois Curfman McInnes   a->rend         = oldmat->rend;
10198965ea79SLois Curfman McInnes   a->size         = oldmat->size;
10208965ea79SLois Curfman McInnes   a->rank         = oldmat->rank;
1021e0fa3b82SLois Curfman McInnes   mat->insertmode = NOT_SET_VALUES;
10223782ba37SSatish Balay   a->donotstash   = oldmat->donotstash;
10230452661fSBarry Smith   a->rowners = (int *) PetscMalloc((a->size+1)*sizeof(int)); CHKPTRQ(a->rowners);
1024f09e8eb9SSatish Balay   PLogObjectMemory(mat,(a->size+1)*sizeof(int)+sizeof(struct _p_Mat)+sizeof(Mat_MPIDense));
10258965ea79SLois Curfman McInnes   PetscMemcpy(a->rowners,oldmat->rowners,(a->size+1)*sizeof(int));
10268798bf22SSatish Balay   ierr = MatStashCreate_Private(A->comm,1,&mat->stash); CHKERRQ(ierr);
10278965ea79SLois Curfman McInnes 
10288965ea79SLois Curfman McInnes   ierr =  VecDuplicate(oldmat->lvec,&a->lvec); CHKERRQ(ierr);
10298965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->lvec);
103055659b69SBarry Smith   ierr =  VecScatterCopy(oldmat->Mvctx,&a->Mvctx); CHKERRQ(ierr);
10318965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->Mvctx);
10325609ef8eSBarry Smith   ierr =  MatDuplicate(oldmat->A,cpvalues,&a->A); CHKERRQ(ierr);
10338965ea79SLois Curfman McInnes   PLogObjectParent(mat,a->A);
10348965ea79SLois Curfman McInnes   *newmat = mat;
10353a40ed3dSBarry Smith   PetscFunctionReturn(0);
10368965ea79SLois Curfman McInnes }
10378965ea79SLois Curfman McInnes 
103877c4ece6SBarry Smith #include "sys.h"
10398965ea79SLois Curfman McInnes 
10405615d1e5SSatish Balay #undef __FUNC__
10415615d1e5SSatish Balay #define __FUNC__ "MatLoad_MPIDense_DenseInFile"
104290ace30eSBarry Smith int MatLoad_MPIDense_DenseInFile(MPI_Comm comm,int fd,int M, int N, Mat *newmat)
104390ace30eSBarry Smith {
104440011551SBarry Smith   int        *rowners, i,size,rank,m,ierr,nz,j;
104590ace30eSBarry Smith   Scalar     *array,*vals,*vals_ptr;
104690ace30eSBarry Smith   MPI_Status status;
104790ace30eSBarry Smith 
10483a40ed3dSBarry Smith   PetscFunctionBegin;
1049*d132466eSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1050*d132466eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
105190ace30eSBarry Smith 
105290ace30eSBarry Smith   /* determine ownership of all rows */
105390ace30eSBarry Smith   m          = M/size + ((M % size) > rank);
105490ace30eSBarry Smith   rowners    = (int *) PetscMalloc((size+2)*sizeof(int)); CHKPTRQ(rowners);
1055ca161407SBarry Smith   ierr       = MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
105690ace30eSBarry Smith   rowners[0] = 0;
105790ace30eSBarry Smith   for ( i=2; i<=size; i++ ) {
105890ace30eSBarry Smith     rowners[i] += rowners[i-1];
105990ace30eSBarry Smith   }
106090ace30eSBarry Smith 
106190ace30eSBarry Smith   ierr = MatCreateMPIDense(comm,m,PETSC_DECIDE,M,N,PETSC_NULL,newmat);CHKERRQ(ierr);
106290ace30eSBarry Smith   ierr = MatGetArray(*newmat,&array); CHKERRQ(ierr);
106390ace30eSBarry Smith 
106490ace30eSBarry Smith   if (!rank) {
106590ace30eSBarry Smith     vals = (Scalar *) PetscMalloc( m*N*sizeof(Scalar) ); CHKPTRQ(vals);
106690ace30eSBarry Smith 
106790ace30eSBarry Smith     /* read in my part of the matrix numerical values  */
10680752156aSBarry Smith     ierr = PetscBinaryRead(fd,vals,m*N,PETSC_SCALAR); CHKERRQ(ierr);
106990ace30eSBarry Smith 
107090ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
107190ace30eSBarry Smith     vals_ptr = vals;
107290ace30eSBarry Smith     for ( i=0; i<m; i++ ) {
107390ace30eSBarry Smith       for ( j=0; j<N; j++ ) {
107490ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
107590ace30eSBarry Smith       }
107690ace30eSBarry Smith     }
107790ace30eSBarry Smith 
107890ace30eSBarry Smith     /* read in other processors and ship out */
107990ace30eSBarry Smith     for ( i=1; i<size; i++ ) {
108090ace30eSBarry Smith       nz   = (rowners[i+1] - rowners[i])*N;
10810752156aSBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR); CHKERRQ(ierr);
1082ca161407SBarry Smith       ierr = MPI_Send(vals,nz,MPIU_SCALAR,i,(*newmat)->tag,comm);CHKERRQ(ierr);
108390ace30eSBarry Smith     }
10843a40ed3dSBarry Smith   } else {
108590ace30eSBarry Smith     /* receive numeric values */
108690ace30eSBarry Smith     vals = (Scalar*) PetscMalloc( m*N*sizeof(Scalar) ); CHKPTRQ(vals);
108790ace30eSBarry Smith 
108890ace30eSBarry Smith     /* receive message of values*/
1089ca161407SBarry Smith     ierr = MPI_Recv(vals,m*N,MPIU_SCALAR,0,(*newmat)->tag,comm,&status);CHKERRQ(ierr);
109090ace30eSBarry Smith 
109190ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
109290ace30eSBarry Smith     vals_ptr = vals;
109390ace30eSBarry Smith     for ( i=0; i<m; i++ ) {
109490ace30eSBarry Smith       for ( j=0; j<N; j++ ) {
109590ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
109690ace30eSBarry Smith       }
109790ace30eSBarry Smith     }
109890ace30eSBarry Smith   }
109990ace30eSBarry Smith   PetscFree(rowners);
110090ace30eSBarry Smith   PetscFree(vals);
11016d4a8577SBarry Smith   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
11026d4a8577SBarry Smith   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
11033a40ed3dSBarry Smith   PetscFunctionReturn(0);
110490ace30eSBarry Smith }
110590ace30eSBarry Smith 
110690ace30eSBarry Smith 
11075615d1e5SSatish Balay #undef __FUNC__
11085615d1e5SSatish Balay #define __FUNC__ "MatLoad_MPIDense"
110919bcc07fSBarry Smith int MatLoad_MPIDense(Viewer viewer,MatType type,Mat *newmat)
11108965ea79SLois Curfman McInnes {
11118965ea79SLois Curfman McInnes   Mat          A;
11128965ea79SLois Curfman McInnes   Scalar       *vals,*svals;
111319bcc07fSBarry Smith   MPI_Comm     comm = ((PetscObject)viewer)->comm;
11148965ea79SLois Curfman McInnes   MPI_Status   status;
11158965ea79SLois Curfman McInnes   int          header[4],rank,size,*rowlengths = 0,M,N,m,*rowners,maxnz,*cols;
11168965ea79SLois Curfman McInnes   int          *ourlens,*sndcounts = 0,*procsnz = 0, *offlens,jj,*mycols,*smycols;
111719bcc07fSBarry Smith   int          tag = ((PetscObject)viewer)->tag;
11183a40ed3dSBarry Smith   int          i, nz, ierr, j,rstart, rend, fd;
11198965ea79SLois Curfman McInnes 
11203a40ed3dSBarry Smith   PetscFunctionBegin;
1121*d132466eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1122*d132466eSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
11238965ea79SLois Curfman McInnes   if (!rank) {
112490ace30eSBarry Smith     ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
11250752156aSBarry Smith     ierr = PetscBinaryRead(fd,(char *)header,4,PETSC_INT); CHKERRQ(ierr);
1126a8c6a408SBarry Smith     if (header[0] != MAT_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"not matrix object");
11278965ea79SLois Curfman McInnes   }
11288965ea79SLois Curfman McInnes 
1129ca161407SBarry Smith   ierr = MPI_Bcast(header+1,3,MPI_INT,0,comm);CHKERRQ(ierr);
113090ace30eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
113190ace30eSBarry Smith 
113290ace30eSBarry Smith   /*
113390ace30eSBarry Smith        Handle case where matrix is stored on disk as a dense matrix
113490ace30eSBarry Smith   */
113590ace30eSBarry Smith   if (nz == MATRIX_BINARY_FORMAT_DENSE) {
11363a40ed3dSBarry Smith     ierr = MatLoad_MPIDense_DenseInFile(comm,fd,M,N,newmat);CHKERRQ(ierr);
11373a40ed3dSBarry Smith     PetscFunctionReturn(0);
113890ace30eSBarry Smith   }
113990ace30eSBarry Smith 
11408965ea79SLois Curfman McInnes   /* determine ownership of all rows */
11418965ea79SLois Curfman McInnes   m          = M/size + ((M % size) > rank);
11420452661fSBarry Smith   rowners    = (int *) PetscMalloc((size+2)*sizeof(int)); CHKPTRQ(rowners);
1143ca161407SBarry Smith   ierr       = MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
11448965ea79SLois Curfman McInnes   rowners[0] = 0;
11458965ea79SLois Curfman McInnes   for ( i=2; i<=size; i++ ) {
11468965ea79SLois Curfman McInnes     rowners[i] += rowners[i-1];
11478965ea79SLois Curfman McInnes   }
11488965ea79SLois Curfman McInnes   rstart = rowners[rank];
11498965ea79SLois Curfman McInnes   rend   = rowners[rank+1];
11508965ea79SLois Curfman McInnes 
11518965ea79SLois Curfman McInnes   /* distribute row lengths to all processors */
11520452661fSBarry Smith   ourlens = (int*) PetscMalloc( 2*(rend-rstart)*sizeof(int) ); CHKPTRQ(ourlens);
11538965ea79SLois Curfman McInnes   offlens = ourlens + (rend-rstart);
11548965ea79SLois Curfman McInnes   if (!rank) {
11550452661fSBarry Smith     rowlengths = (int*) PetscMalloc( M*sizeof(int) ); CHKPTRQ(rowlengths);
11560752156aSBarry Smith     ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT); CHKERRQ(ierr);
11570452661fSBarry Smith     sndcounts = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(sndcounts);
11588965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) sndcounts[i] = rowners[i+1] - rowners[i];
1159ca161407SBarry Smith     ierr = MPI_Scatterv(rowlengths,sndcounts,rowners,MPI_INT,ourlens,rend-rstart,MPI_INT,0,comm);CHKERRQ(ierr);
11600452661fSBarry Smith     PetscFree(sndcounts);
1161ca161407SBarry Smith   } else {
1162ca161407SBarry Smith     ierr = MPI_Scatterv(0,0,0,MPI_INT,ourlens,rend-rstart,MPI_INT, 0,comm);CHKERRQ(ierr);
11638965ea79SLois Curfman McInnes   }
11648965ea79SLois Curfman McInnes 
11658965ea79SLois Curfman McInnes   if (!rank) {
11668965ea79SLois Curfman McInnes     /* calculate the number of nonzeros on each processor */
11670452661fSBarry Smith     procsnz = (int*) PetscMalloc( size*sizeof(int) ); CHKPTRQ(procsnz);
1168cddf8d76SBarry Smith     PetscMemzero(procsnz,size*sizeof(int));
11698965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) {
11708965ea79SLois Curfman McInnes       for ( j=rowners[i]; j< rowners[i+1]; j++ ) {
11718965ea79SLois Curfman McInnes         procsnz[i] += rowlengths[j];
11728965ea79SLois Curfman McInnes       }
11738965ea79SLois Curfman McInnes     }
11740452661fSBarry Smith     PetscFree(rowlengths);
11758965ea79SLois Curfman McInnes 
11768965ea79SLois Curfman McInnes     /* determine max buffer needed and allocate it */
11778965ea79SLois Curfman McInnes     maxnz = 0;
11788965ea79SLois Curfman McInnes     for ( i=0; i<size; i++ ) {
11790452661fSBarry Smith       maxnz = PetscMax(maxnz,procsnz[i]);
11808965ea79SLois Curfman McInnes     }
11810452661fSBarry Smith     cols = (int *) PetscMalloc( maxnz*sizeof(int) ); CHKPTRQ(cols);
11828965ea79SLois Curfman McInnes 
11838965ea79SLois Curfman McInnes     /* read in my part of the matrix column indices  */
11848965ea79SLois Curfman McInnes     nz = procsnz[0];
11850452661fSBarry Smith     mycols = (int *) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(mycols);
11860752156aSBarry Smith     ierr = PetscBinaryRead(fd,mycols,nz,PETSC_INT); CHKERRQ(ierr);
11878965ea79SLois Curfman McInnes 
11888965ea79SLois Curfman McInnes     /* read in every one elses and ship off */
11898965ea79SLois Curfman McInnes     for ( i=1; i<size; i++ ) {
11908965ea79SLois Curfman McInnes       nz   = procsnz[i];
11910752156aSBarry Smith       ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT); CHKERRQ(ierr);
1192ca161407SBarry Smith       ierr = MPI_Send(cols,nz,MPI_INT,i,tag,comm);CHKERRQ(ierr);
11938965ea79SLois Curfman McInnes     }
11940452661fSBarry Smith     PetscFree(cols);
11953a40ed3dSBarry Smith   } else {
11968965ea79SLois Curfman McInnes     /* determine buffer space needed for message */
11978965ea79SLois Curfman McInnes     nz = 0;
11988965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
11998965ea79SLois Curfman McInnes       nz += ourlens[i];
12008965ea79SLois Curfman McInnes     }
12010452661fSBarry Smith     mycols = (int*) PetscMalloc( nz*sizeof(int) ); CHKPTRQ(mycols);
12028965ea79SLois Curfman McInnes 
12038965ea79SLois Curfman McInnes     /* receive message of column indices*/
1204ca161407SBarry Smith     ierr = MPI_Recv(mycols,nz,MPI_INT,0,tag,comm,&status);CHKERRQ(ierr);
1205ca161407SBarry Smith     ierr = MPI_Get_count(&status,MPI_INT,&maxnz);CHKERRQ(ierr);
1206a8c6a408SBarry Smith     if (maxnz != nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"something is wrong with file");
12078965ea79SLois Curfman McInnes   }
12088965ea79SLois Curfman McInnes 
12098965ea79SLois Curfman McInnes   /* loop over local rows, determining number of off diagonal entries */
1210cddf8d76SBarry Smith   PetscMemzero(offlens,m*sizeof(int));
12118965ea79SLois Curfman McInnes   jj = 0;
12128965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
12138965ea79SLois Curfman McInnes     for ( j=0; j<ourlens[i]; j++ ) {
12148965ea79SLois Curfman McInnes       if (mycols[jj] < rstart || mycols[jj] >= rend) offlens[i]++;
12158965ea79SLois Curfman McInnes       jj++;
12168965ea79SLois Curfman McInnes     }
12178965ea79SLois Curfman McInnes   }
12188965ea79SLois Curfman McInnes 
12198965ea79SLois Curfman McInnes   /* create our matrix */
12208965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
12218965ea79SLois Curfman McInnes     ourlens[i] -= offlens[i];
12228965ea79SLois Curfman McInnes   }
1223b4fd4287SBarry Smith   ierr = MatCreateMPIDense(comm,m,PETSC_DECIDE,M,N,PETSC_NULL,newmat);CHKERRQ(ierr);
12248965ea79SLois Curfman McInnes   A = *newmat;
12258965ea79SLois Curfman McInnes   for ( i=0; i<m; i++ ) {
12268965ea79SLois Curfman McInnes     ourlens[i] += offlens[i];
12278965ea79SLois Curfman McInnes   }
12288965ea79SLois Curfman McInnes 
12298965ea79SLois Curfman McInnes   if (!rank) {
12300452661fSBarry Smith     vals = (Scalar *) PetscMalloc( maxnz*sizeof(Scalar) ); CHKPTRQ(vals);
12318965ea79SLois Curfman McInnes 
12328965ea79SLois Curfman McInnes     /* read in my part of the matrix numerical values  */
12338965ea79SLois Curfman McInnes     nz = procsnz[0];
12340752156aSBarry Smith     ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR); CHKERRQ(ierr);
12358965ea79SLois Curfman McInnes 
12368965ea79SLois Curfman McInnes     /* insert into matrix */
12378965ea79SLois Curfman McInnes     jj      = rstart;
12388965ea79SLois Curfman McInnes     smycols = mycols;
12398965ea79SLois Curfman McInnes     svals   = vals;
12408965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
12418965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
12428965ea79SLois Curfman McInnes       smycols += ourlens[i];
12438965ea79SLois Curfman McInnes       svals   += ourlens[i];
12448965ea79SLois Curfman McInnes       jj++;
12458965ea79SLois Curfman McInnes     }
12468965ea79SLois Curfman McInnes 
12478965ea79SLois Curfman McInnes     /* read in other processors and ship out */
12488965ea79SLois Curfman McInnes     for ( i=1; i<size; i++ ) {
12498965ea79SLois Curfman McInnes       nz   = procsnz[i];
12500752156aSBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR); CHKERRQ(ierr);
1251ca161407SBarry Smith       ierr = MPI_Send(vals,nz,MPIU_SCALAR,i,A->tag,comm);CHKERRQ(ierr);
12528965ea79SLois Curfman McInnes     }
12530452661fSBarry Smith     PetscFree(procsnz);
12543a40ed3dSBarry Smith   } else {
12558965ea79SLois Curfman McInnes     /* receive numeric values */
12560452661fSBarry Smith     vals = (Scalar*) PetscMalloc( nz*sizeof(Scalar) ); CHKPTRQ(vals);
12578965ea79SLois Curfman McInnes 
12588965ea79SLois Curfman McInnes     /* receive message of values*/
1259ca161407SBarry Smith     ierr = MPI_Recv(vals,nz,MPIU_SCALAR,0,A->tag,comm,&status);CHKERRQ(ierr);
1260ca161407SBarry Smith     ierr = MPI_Get_count(&status,MPIU_SCALAR,&maxnz);CHKERRQ(ierr);
1261a8c6a408SBarry Smith     if (maxnz != nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,0,"something is wrong with file");
12628965ea79SLois Curfman McInnes 
12638965ea79SLois Curfman McInnes     /* insert into matrix */
12648965ea79SLois Curfman McInnes     jj      = rstart;
12658965ea79SLois Curfman McInnes     smycols = mycols;
12668965ea79SLois Curfman McInnes     svals   = vals;
12678965ea79SLois Curfman McInnes     for ( i=0; i<m; i++ ) {
12688965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
12698965ea79SLois Curfman McInnes       smycols += ourlens[i];
12708965ea79SLois Curfman McInnes       svals   += ourlens[i];
12718965ea79SLois Curfman McInnes       jj++;
12728965ea79SLois Curfman McInnes     }
12738965ea79SLois Curfman McInnes   }
12740452661fSBarry Smith   PetscFree(ourlens); PetscFree(vals); PetscFree(mycols); PetscFree(rowners);
12758965ea79SLois Curfman McInnes 
12766d4a8577SBarry Smith   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
12776d4a8577SBarry Smith   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
12783a40ed3dSBarry Smith   PetscFunctionReturn(0);
12798965ea79SLois Curfman McInnes }
128090ace30eSBarry Smith 
128190ace30eSBarry Smith 
128290ace30eSBarry Smith 
128390ace30eSBarry Smith 
128490ace30eSBarry Smith 
1285