xref: /petsc/src/mat/impls/dense/mpi/mpidense.c (revision 1ae5eee899a06adc59d7f5b9fdd066c5b774aedc)
1be1d678aSKris Buschelman 
2ed3cc1f0SBarry Smith /*
3ed3cc1f0SBarry Smith    Basic functions for basic parallel dense matrices.
4ed3cc1f0SBarry Smith */
5ed3cc1f0SBarry Smith 
604fea9ffSBarry Smith 
7c6db04a5SJed Brown #include <../src/mat/impls/dense/mpi/mpidense.h>    /*I   "petscmat.h"  I*/
88949adfdSHong Zhang #include <../src/mat/impls/aij/mpi/mpiaij.h>
9baa3c1c6SHong Zhang #include <petscblaslapack.h>
108965ea79SLois Curfman McInnes 
11ab92ecdeSBarry Smith /*@
12ab92ecdeSBarry Smith 
13ab92ecdeSBarry Smith       MatDenseGetLocalMatrix - For a MATMPIDENSE or MATSEQDENSE matrix returns the sequential
14ab92ecdeSBarry Smith               matrix that represents the operator. For sequential matrices it returns itself.
15ab92ecdeSBarry Smith 
16ab92ecdeSBarry Smith     Input Parameter:
17ab92ecdeSBarry Smith .      A - the Seq or MPI dense matrix
18ab92ecdeSBarry Smith 
19ab92ecdeSBarry Smith     Output Parameter:
20ab92ecdeSBarry Smith .      B - the inner matrix
21ab92ecdeSBarry Smith 
228e6c10adSSatish Balay     Level: intermediate
238e6c10adSSatish Balay 
24ab92ecdeSBarry Smith @*/
25ab92ecdeSBarry Smith PetscErrorCode MatDenseGetLocalMatrix(Mat A,Mat *B)
26ab92ecdeSBarry Smith {
27ab92ecdeSBarry Smith   Mat_MPIDense   *mat = (Mat_MPIDense*)A->data;
28ab92ecdeSBarry Smith   PetscErrorCode ierr;
29ace3abfcSBarry Smith   PetscBool      flg;
30ab92ecdeSBarry Smith 
31ab92ecdeSBarry Smith   PetscFunctionBegin;
32251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIDENSE,&flg);CHKERRQ(ierr);
332205254eSKarl Rupp   if (flg) *B = mat->A;
342205254eSKarl Rupp   else *B = A;
35ab92ecdeSBarry Smith   PetscFunctionReturn(0);
36ab92ecdeSBarry Smith }
37ab92ecdeSBarry Smith 
38ba8c8a56SBarry Smith PetscErrorCode MatGetRow_MPIDense(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
39ba8c8a56SBarry Smith {
40ba8c8a56SBarry Smith   Mat_MPIDense   *mat = (Mat_MPIDense*)A->data;
41ba8c8a56SBarry Smith   PetscErrorCode ierr;
42d0f46423SBarry Smith   PetscInt       lrow,rstart = A->rmap->rstart,rend = A->rmap->rend;
43ba8c8a56SBarry Smith 
44ba8c8a56SBarry Smith   PetscFunctionBegin;
45e7e72b3dSBarry Smith   if (row < rstart || row >= rend) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"only local rows");
46ba8c8a56SBarry Smith   lrow = row - rstart;
47ba8c8a56SBarry Smith   ierr = MatGetRow(mat->A,lrow,nz,(const PetscInt**)idx,(const PetscScalar**)v);CHKERRQ(ierr);
48ba8c8a56SBarry Smith   PetscFunctionReturn(0);
49ba8c8a56SBarry Smith }
50ba8c8a56SBarry Smith 
51ba8c8a56SBarry Smith PetscErrorCode MatRestoreRow_MPIDense(Mat mat,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
52ba8c8a56SBarry Smith {
53ba8c8a56SBarry Smith   PetscErrorCode ierr;
54ba8c8a56SBarry Smith 
55ba8c8a56SBarry Smith   PetscFunctionBegin;
56ba8c8a56SBarry Smith   if (idx) {ierr = PetscFree(*idx);CHKERRQ(ierr);}
57ba8c8a56SBarry Smith   if (v) {ierr = PetscFree(*v);CHKERRQ(ierr);}
58ba8c8a56SBarry Smith   PetscFunctionReturn(0);
59ba8c8a56SBarry Smith }
60ba8c8a56SBarry Smith 
6111bd1e4dSLisandro Dalcin PetscErrorCode  MatGetDiagonalBlock_MPIDense(Mat A,Mat *a)
620de54da6SSatish Balay {
630de54da6SSatish Balay   Mat_MPIDense   *mdn = (Mat_MPIDense*)A->data;
646849ba73SBarry Smith   PetscErrorCode ierr;
65d0f46423SBarry Smith   PetscInt       m = A->rmap->n,rstart = A->rmap->rstart;
6687828ca2SBarry Smith   PetscScalar    *array;
670de54da6SSatish Balay   MPI_Comm       comm;
6811bd1e4dSLisandro Dalcin   Mat            B;
690de54da6SSatish Balay 
700de54da6SSatish Balay   PetscFunctionBegin;
71e32f2f54SBarry Smith   if (A->rmap->N != A->cmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only square matrices supported.");
720de54da6SSatish Balay 
7311bd1e4dSLisandro Dalcin   ierr = PetscObjectQuery((PetscObject)A,"DiagonalBlock",(PetscObject*)&B);CHKERRQ(ierr);
7411bd1e4dSLisandro Dalcin   if (!B) {
750de54da6SSatish Balay     ierr = PetscObjectGetComm((PetscObject)(mdn->A),&comm);CHKERRQ(ierr);
7611bd1e4dSLisandro Dalcin     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
7711bd1e4dSLisandro Dalcin     ierr = MatSetSizes(B,m,m,m,m);CHKERRQ(ierr);
7811bd1e4dSLisandro Dalcin     ierr = MatSetType(B,((PetscObject)mdn->A)->type_name);CHKERRQ(ierr);
798c778c55SBarry Smith     ierr = MatDenseGetArray(mdn->A,&array);CHKERRQ(ierr);
8011bd1e4dSLisandro Dalcin     ierr = MatSeqDenseSetPreallocation(B,array+m*rstart);CHKERRQ(ierr);
818c778c55SBarry Smith     ierr = MatDenseRestoreArray(mdn->A,&array);CHKERRQ(ierr);
8211bd1e4dSLisandro Dalcin     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8311bd1e4dSLisandro Dalcin     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8411bd1e4dSLisandro Dalcin     ierr = PetscObjectCompose((PetscObject)A,"DiagonalBlock",(PetscObject)B);CHKERRQ(ierr);
8511bd1e4dSLisandro Dalcin     *a   = B;
8611bd1e4dSLisandro Dalcin     ierr = MatDestroy(&B);CHKERRQ(ierr);
872205254eSKarl Rupp   } else *a = B;
880de54da6SSatish Balay   PetscFunctionReturn(0);
890de54da6SSatish Balay }
900de54da6SSatish Balay 
9113f74950SBarry Smith PetscErrorCode MatSetValues_MPIDense(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
928965ea79SLois Curfman McInnes {
9339b7565bSBarry Smith   Mat_MPIDense   *A = (Mat_MPIDense*)mat->data;
94dfbe8321SBarry Smith   PetscErrorCode ierr;
95d0f46423SBarry Smith   PetscInt       i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend,row;
96ace3abfcSBarry Smith   PetscBool      roworiented = A->roworiented;
978965ea79SLois Curfman McInnes 
983a40ed3dSBarry Smith   PetscFunctionBegin;
998965ea79SLois Curfman McInnes   for (i=0; i<m; i++) {
1005ef9f2a5SBarry Smith     if (idxm[i] < 0) continue;
101e32f2f54SBarry Smith     if (idxm[i] >= mat->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
1028965ea79SLois Curfman McInnes     if (idxm[i] >= rstart && idxm[i] < rend) {
1038965ea79SLois Curfman McInnes       row = idxm[i] - rstart;
10439b7565bSBarry Smith       if (roworiented) {
10539b7565bSBarry Smith         ierr = MatSetValues(A->A,1,&row,n,idxn,v+i*n,addv);CHKERRQ(ierr);
1063a40ed3dSBarry Smith       } else {
1078965ea79SLois Curfman McInnes         for (j=0; j<n; j++) {
1085ef9f2a5SBarry Smith           if (idxn[j] < 0) continue;
109e32f2f54SBarry Smith           if (idxn[j] >= mat->cmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
11039b7565bSBarry Smith           ierr = MatSetValues(A->A,1,&row,1,&idxn[j],v+i+j*m,addv);CHKERRQ(ierr);
11139b7565bSBarry Smith         }
1128965ea79SLois Curfman McInnes       }
1132205254eSKarl Rupp     } else if (!A->donotstash) {
1145080c13bSMatthew G Knepley       mat->assembled = PETSC_FALSE;
11539b7565bSBarry Smith       if (roworiented) {
116b400d20cSBarry Smith         ierr = MatStashValuesRow_Private(&mat->stash,idxm[i],n,idxn,v+i*n,PETSC_FALSE);CHKERRQ(ierr);
117d36fbae8SSatish Balay       } else {
118b400d20cSBarry Smith         ierr = MatStashValuesCol_Private(&mat->stash,idxm[i],n,idxn,v+i,m,PETSC_FALSE);CHKERRQ(ierr);
11939b7565bSBarry Smith       }
120b49de8d1SLois Curfman McInnes     }
121b49de8d1SLois Curfman McInnes   }
1223a40ed3dSBarry Smith   PetscFunctionReturn(0);
123b49de8d1SLois Curfman McInnes }
124b49de8d1SLois Curfman McInnes 
12513f74950SBarry Smith PetscErrorCode MatGetValues_MPIDense(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
126b49de8d1SLois Curfman McInnes {
127b49de8d1SLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)mat->data;
128dfbe8321SBarry Smith   PetscErrorCode ierr;
129d0f46423SBarry Smith   PetscInt       i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend,row;
130b49de8d1SLois Curfman McInnes 
1313a40ed3dSBarry Smith   PetscFunctionBegin;
132b49de8d1SLois Curfman McInnes   for (i=0; i<m; i++) {
133e32f2f54SBarry Smith     if (idxm[i] < 0) continue; /* SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row"); */
134e32f2f54SBarry Smith     if (idxm[i] >= mat->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
135b49de8d1SLois Curfman McInnes     if (idxm[i] >= rstart && idxm[i] < rend) {
136b49de8d1SLois Curfman McInnes       row = idxm[i] - rstart;
137b49de8d1SLois Curfman McInnes       for (j=0; j<n; j++) {
138e32f2f54SBarry Smith         if (idxn[j] < 0) continue; /* SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column"); */
139e7e72b3dSBarry Smith         if (idxn[j] >= mat->cmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
140b49de8d1SLois Curfman McInnes         ierr = MatGetValues(mdn->A,1,&row,1,&idxn[j],v+i*n+j);CHKERRQ(ierr);
141b49de8d1SLois Curfman McInnes       }
142e7e72b3dSBarry Smith     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only local values currently supported");
1438965ea79SLois Curfman McInnes   }
1443a40ed3dSBarry Smith   PetscFunctionReturn(0);
1458965ea79SLois Curfman McInnes }
1468965ea79SLois Curfman McInnes 
147d3042a70SBarry Smith static PetscErrorCode MatDenseGetArray_MPIDense(Mat A,PetscScalar *array[])
148ff14e315SSatish Balay {
149ff14e315SSatish Balay   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
150dfbe8321SBarry Smith   PetscErrorCode ierr;
151ff14e315SSatish Balay 
1523a40ed3dSBarry Smith   PetscFunctionBegin;
1538c778c55SBarry Smith   ierr = MatDenseGetArray(a->A,array);CHKERRQ(ierr);
1543a40ed3dSBarry Smith   PetscFunctionReturn(0);
155ff14e315SSatish Balay }
156ff14e315SSatish Balay 
1578572280aSBarry Smith static PetscErrorCode MatDenseGetArrayRead_MPIDense(Mat A,const PetscScalar *array[])
1588572280aSBarry Smith {
1598572280aSBarry Smith   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
1608572280aSBarry Smith   PetscErrorCode ierr;
1618572280aSBarry Smith 
1628572280aSBarry Smith   PetscFunctionBegin;
1638572280aSBarry Smith   ierr = MatDenseGetArrayRead(a->A,array);CHKERRQ(ierr);
1648572280aSBarry Smith   PetscFunctionReturn(0);
1658572280aSBarry Smith }
1668572280aSBarry Smith 
167d3042a70SBarry Smith static PetscErrorCode MatDensePlaceArray_MPIDense(Mat A,const PetscScalar array[])
168d3042a70SBarry Smith {
169d3042a70SBarry Smith   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
170d3042a70SBarry Smith   PetscErrorCode ierr;
171d3042a70SBarry Smith 
172d3042a70SBarry Smith   PetscFunctionBegin;
173d3042a70SBarry Smith   ierr = MatDensePlaceArray(a->A,array);CHKERRQ(ierr);
174d3042a70SBarry Smith   PetscFunctionReturn(0);
175d3042a70SBarry Smith }
176d3042a70SBarry Smith 
177d3042a70SBarry Smith static PetscErrorCode MatDenseResetArray_MPIDense(Mat A)
178d3042a70SBarry Smith {
179d3042a70SBarry Smith   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
180d3042a70SBarry Smith   PetscErrorCode ierr;
181d3042a70SBarry Smith 
182d3042a70SBarry Smith   PetscFunctionBegin;
183d3042a70SBarry Smith   ierr = MatDenseResetArray(a->A);CHKERRQ(ierr);
184d3042a70SBarry Smith   PetscFunctionReturn(0);
185d3042a70SBarry Smith }
186d3042a70SBarry Smith 
1877dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_MPIDense(Mat A,IS isrow,IS iscol,MatReuse scall,Mat *B)
188ca3fa75bSLois Curfman McInnes {
189ca3fa75bSLois Curfman McInnes   Mat_MPIDense   *mat  = (Mat_MPIDense*)A->data,*newmatd;
190ca3fa75bSLois Curfman McInnes   Mat_SeqDense   *lmat = (Mat_SeqDense*)mat->A->data;
1916849ba73SBarry Smith   PetscErrorCode ierr;
1924aa3045dSJed Brown   PetscInt       i,j,rstart,rend,nrows,ncols,Ncols,nlrows,nlcols;
1935d0c19d7SBarry Smith   const PetscInt *irow,*icol;
19487828ca2SBarry Smith   PetscScalar    *av,*bv,*v = lmat->v;
195ca3fa75bSLois Curfman McInnes   Mat            newmat;
1964aa3045dSJed Brown   IS             iscol_local;
197ca3fa75bSLois Curfman McInnes 
198ca3fa75bSLois Curfman McInnes   PetscFunctionBegin;
1994aa3045dSJed Brown   ierr = ISAllGather(iscol,&iscol_local);CHKERRQ(ierr);
200ca3fa75bSLois Curfman McInnes   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2014aa3045dSJed Brown   ierr = ISGetIndices(iscol_local,&icol);CHKERRQ(ierr);
202b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
203b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
2044aa3045dSJed Brown   ierr = ISGetSize(iscol,&Ncols);CHKERRQ(ierr); /* global number of columns, size of iscol_local */
205ca3fa75bSLois Curfman McInnes 
206ca3fa75bSLois Curfman McInnes   /* No parallel redistribution currently supported! Should really check each index set
2077eba5e9cSLois Curfman McInnes      to comfirm that it is OK.  ... Currently supports only submatrix same partitioning as
2087eba5e9cSLois Curfman McInnes      original matrix! */
209ca3fa75bSLois Curfman McInnes 
210ca3fa75bSLois Curfman McInnes   ierr = MatGetLocalSize(A,&nlrows,&nlcols);CHKERRQ(ierr);
2117eba5e9cSLois Curfman McInnes   ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr);
212ca3fa75bSLois Curfman McInnes 
213ca3fa75bSLois Curfman McInnes   /* Check submatrix call */
214ca3fa75bSLois Curfman McInnes   if (scall == MAT_REUSE_MATRIX) {
215e32f2f54SBarry Smith     /* SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); */
2167eba5e9cSLois Curfman McInnes     /* Really need to test rows and column sizes! */
217ca3fa75bSLois Curfman McInnes     newmat = *B;
218ca3fa75bSLois Curfman McInnes   } else {
219ca3fa75bSLois Curfman McInnes     /* Create and fill new matrix */
220ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)A),&newmat);CHKERRQ(ierr);
2214aa3045dSJed Brown     ierr = MatSetSizes(newmat,nrows,ncols,PETSC_DECIDE,Ncols);CHKERRQ(ierr);
2227adad957SLisandro Dalcin     ierr = MatSetType(newmat,((PetscObject)A)->type_name);CHKERRQ(ierr);
2230298fd71SBarry Smith     ierr = MatMPIDenseSetPreallocation(newmat,NULL);CHKERRQ(ierr);
224ca3fa75bSLois Curfman McInnes   }
225ca3fa75bSLois Curfman McInnes 
226ca3fa75bSLois Curfman McInnes   /* Now extract the data pointers and do the copy, column at a time */
227ca3fa75bSLois Curfman McInnes   newmatd = (Mat_MPIDense*)newmat->data;
228ca3fa75bSLois Curfman McInnes   bv      = ((Mat_SeqDense*)newmatd->A->data)->v;
229ca3fa75bSLois Curfman McInnes 
2304aa3045dSJed Brown   for (i=0; i<Ncols; i++) {
23125a33276SHong Zhang     av = v + ((Mat_SeqDense*)mat->A->data)->lda*icol[i];
232ca3fa75bSLois Curfman McInnes     for (j=0; j<nrows; j++) {
2337eba5e9cSLois Curfman McInnes       *bv++ = av[irow[j] - rstart];
234ca3fa75bSLois Curfman McInnes     }
235ca3fa75bSLois Curfman McInnes   }
236ca3fa75bSLois Curfman McInnes 
237ca3fa75bSLois Curfman McInnes   /* Assemble the matrices so that the correct flags are set */
238ca3fa75bSLois Curfman McInnes   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
239ca3fa75bSLois Curfman McInnes   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
240ca3fa75bSLois Curfman McInnes 
241ca3fa75bSLois Curfman McInnes   /* Free work space */
242ca3fa75bSLois Curfman McInnes   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2435bdf786aSShri Abhyankar   ierr = ISRestoreIndices(iscol_local,&icol);CHKERRQ(ierr);
24432bb1f2dSLisandro Dalcin   ierr = ISDestroy(&iscol_local);CHKERRQ(ierr);
245ca3fa75bSLois Curfman McInnes   *B   = newmat;
246ca3fa75bSLois Curfman McInnes   PetscFunctionReturn(0);
247ca3fa75bSLois Curfman McInnes }
248ca3fa75bSLois Curfman McInnes 
2498c778c55SBarry Smith PetscErrorCode MatDenseRestoreArray_MPIDense(Mat A,PetscScalar *array[])
250ff14e315SSatish Balay {
25173a71a0fSBarry Smith   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
25273a71a0fSBarry Smith   PetscErrorCode ierr;
25373a71a0fSBarry Smith 
2543a40ed3dSBarry Smith   PetscFunctionBegin;
2558c778c55SBarry Smith   ierr = MatDenseRestoreArray(a->A,array);CHKERRQ(ierr);
2563a40ed3dSBarry Smith   PetscFunctionReturn(0);
257ff14e315SSatish Balay }
258ff14e315SSatish Balay 
2598572280aSBarry Smith PetscErrorCode MatDenseRestoreArrayRead_MPIDense(Mat A,const PetscScalar *array[])
2608572280aSBarry Smith {
2618572280aSBarry Smith   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
2628572280aSBarry Smith   PetscErrorCode ierr;
2638572280aSBarry Smith 
2648572280aSBarry Smith   PetscFunctionBegin;
2658572280aSBarry Smith   ierr = MatDenseRestoreArrayRead(a->A,array);CHKERRQ(ierr);
2668572280aSBarry Smith   PetscFunctionReturn(0);
2678572280aSBarry Smith }
2688572280aSBarry Smith 
269dfbe8321SBarry Smith PetscErrorCode MatAssemblyBegin_MPIDense(Mat mat,MatAssemblyType mode)
2708965ea79SLois Curfman McInnes {
27139ddd567SLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)mat->data;
272ce94432eSBarry Smith   MPI_Comm       comm;
273dfbe8321SBarry Smith   PetscErrorCode ierr;
27413f74950SBarry Smith   PetscInt       nstash,reallocs;
2758965ea79SLois Curfman McInnes   InsertMode     addv;
2768965ea79SLois Curfman McInnes 
2773a40ed3dSBarry Smith   PetscFunctionBegin;
278ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
2798965ea79SLois Curfman McInnes   /* make sure all processors are either in INSERTMODE or ADDMODE */
280b2566f29SBarry Smith   ierr = MPIU_Allreduce((PetscEnum*)&mat->insertmode,(PetscEnum*)&addv,1,MPIU_ENUM,MPI_BOR,comm);CHKERRQ(ierr);
281ce94432eSBarry Smith   if (addv == (ADD_VALUES|INSERT_VALUES)) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Cannot mix adds/inserts on different procs");
282e0fa3b82SLois Curfman McInnes   mat->insertmode = addv; /* in case this processor had no cache */
2838965ea79SLois Curfman McInnes 
284d0f46423SBarry Smith   ierr = MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range);CHKERRQ(ierr);
2858798bf22SSatish Balay   ierr = MatStashGetInfo_Private(&mat->stash,&nstash,&reallocs);CHKERRQ(ierr);
286ae15b995SBarry Smith   ierr = PetscInfo2(mdn->A,"Stash has %D entries, uses %D mallocs.\n",nstash,reallocs);CHKERRQ(ierr);
2873a40ed3dSBarry Smith   PetscFunctionReturn(0);
2888965ea79SLois Curfman McInnes }
2898965ea79SLois Curfman McInnes 
290dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_MPIDense(Mat mat,MatAssemblyType mode)
2918965ea79SLois Curfman McInnes {
29239ddd567SLois Curfman McInnes   Mat_MPIDense   *mdn=(Mat_MPIDense*)mat->data;
2936849ba73SBarry Smith   PetscErrorCode ierr;
29413f74950SBarry Smith   PetscInt       i,*row,*col,flg,j,rstart,ncols;
29513f74950SBarry Smith   PetscMPIInt    n;
29687828ca2SBarry Smith   PetscScalar    *val;
2978965ea79SLois Curfman McInnes 
2983a40ed3dSBarry Smith   PetscFunctionBegin;
2998965ea79SLois Curfman McInnes   /*  wait on receives */
3007ef1d9bdSSatish Balay   while (1) {
3018798bf22SSatish Balay     ierr = MatStashScatterGetMesg_Private(&mat->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr);
3027ef1d9bdSSatish Balay     if (!flg) break;
3038965ea79SLois Curfman McInnes 
3047ef1d9bdSSatish Balay     for (i=0; i<n;) {
3057ef1d9bdSSatish Balay       /* Now identify the consecutive vals belonging to the same row */
3062205254eSKarl Rupp       for (j=i,rstart=row[j]; j<n; j++) {
3072205254eSKarl Rupp         if (row[j] != rstart) break;
3082205254eSKarl Rupp       }
3097ef1d9bdSSatish Balay       if (j < n) ncols = j-i;
3107ef1d9bdSSatish Balay       else       ncols = n-i;
3117ef1d9bdSSatish Balay       /* Now assemble all these values with a single function call */
3124b4eb8d3SJed Brown       ierr = MatSetValues_MPIDense(mat,1,row+i,ncols,col+i,val+i,mat->insertmode);CHKERRQ(ierr);
3137ef1d9bdSSatish Balay       i    = j;
3148965ea79SLois Curfman McInnes     }
3157ef1d9bdSSatish Balay   }
3168798bf22SSatish Balay   ierr = MatStashScatterEnd_Private(&mat->stash);CHKERRQ(ierr);
3178965ea79SLois Curfman McInnes 
31839ddd567SLois Curfman McInnes   ierr = MatAssemblyBegin(mdn->A,mode);CHKERRQ(ierr);
31939ddd567SLois Curfman McInnes   ierr = MatAssemblyEnd(mdn->A,mode);CHKERRQ(ierr);
3208965ea79SLois Curfman McInnes 
3216d4a8577SBarry Smith   if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) {
32239ddd567SLois Curfman McInnes     ierr = MatSetUpMultiply_MPIDense(mat);CHKERRQ(ierr);
3238965ea79SLois Curfman McInnes   }
3243a40ed3dSBarry Smith   PetscFunctionReturn(0);
3258965ea79SLois Curfman McInnes }
3268965ea79SLois Curfman McInnes 
327dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_MPIDense(Mat A)
3288965ea79SLois Curfman McInnes {
329dfbe8321SBarry Smith   PetscErrorCode ierr;
33039ddd567SLois Curfman McInnes   Mat_MPIDense   *l = (Mat_MPIDense*)A->data;
3313a40ed3dSBarry Smith 
3323a40ed3dSBarry Smith   PetscFunctionBegin;
3333a40ed3dSBarry Smith   ierr = MatZeroEntries(l->A);CHKERRQ(ierr);
3343a40ed3dSBarry Smith   PetscFunctionReturn(0);
3358965ea79SLois Curfman McInnes }
3368965ea79SLois Curfman McInnes 
3378965ea79SLois Curfman McInnes /* the code does not do the diagonal entries correctly unless the
3388965ea79SLois Curfman McInnes    matrix is square and the column and row owerships are identical.
3398965ea79SLois Curfman McInnes    This is a BUG. The only way to fix it seems to be to access
3403501a2bdSLois Curfman McInnes    mdn->A and mdn->B directly and not through the MatZeroRows()
3418965ea79SLois Curfman McInnes    routine.
3428965ea79SLois Curfman McInnes */
3432b40b63fSBarry Smith PetscErrorCode MatZeroRows_MPIDense(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
3448965ea79SLois Curfman McInnes {
34539ddd567SLois Curfman McInnes   Mat_MPIDense      *l = (Mat_MPIDense*)A->data;
3466849ba73SBarry Smith   PetscErrorCode    ierr;
347d0f46423SBarry Smith   PetscInt          i,*owners = A->rmap->range;
34876ec1555SBarry Smith   PetscInt          *sizes,j,idx,nsends;
34913f74950SBarry Smith   PetscInt          nmax,*svalues,*starts,*owner,nrecvs;
3507adad957SLisandro Dalcin   PetscInt          *rvalues,tag = ((PetscObject)A)->tag,count,base,slen,*source;
35113f74950SBarry Smith   PetscInt          *lens,*lrows,*values;
35213f74950SBarry Smith   PetscMPIInt       n,imdex,rank = l->rank,size = l->size;
353ce94432eSBarry Smith   MPI_Comm          comm;
3548965ea79SLois Curfman McInnes   MPI_Request       *send_waits,*recv_waits;
3558965ea79SLois Curfman McInnes   MPI_Status        recv_status,*send_status;
356ace3abfcSBarry Smith   PetscBool         found;
35797b48c8fSBarry Smith   const PetscScalar *xx;
35897b48c8fSBarry Smith   PetscScalar       *bb;
3598965ea79SLois Curfman McInnes 
3603a40ed3dSBarry Smith   PetscFunctionBegin;
361ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
362ce94432eSBarry Smith   if (A->rmap->N != A->cmap->N) SETERRQ(comm,PETSC_ERR_SUP,"Only handles square matrices");
363b9679d65SBarry Smith   if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only handles matrices with identical column and row ownership");
3648965ea79SLois Curfman McInnes   /*  first count number of contributors to each processor */
365f628708eSJed Brown   ierr = PetscCalloc1(2*size,&sizes);CHKERRQ(ierr);
366037dbc42SBarry Smith   ierr = PetscMalloc1(N+1,&owner);CHKERRQ(ierr);  /* see note*/
3678965ea79SLois Curfman McInnes   for (i=0; i<N; i++) {
3688965ea79SLois Curfman McInnes     idx   = rows[i];
36935d8aa7fSBarry Smith     found = PETSC_FALSE;
3708965ea79SLois Curfman McInnes     for (j=0; j<size; j++) {
3718965ea79SLois Curfman McInnes       if (idx >= owners[j] && idx < owners[j+1]) {
37276ec1555SBarry Smith         sizes[2*j]++; sizes[2*j+1] = 1; owner[i] = j; found = PETSC_TRUE; break;
3738965ea79SLois Curfman McInnes       }
3748965ea79SLois Curfman McInnes     }
375e32f2f54SBarry Smith     if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index out of range");
3768965ea79SLois Curfman McInnes   }
3772205254eSKarl Rupp   nsends = 0;
37876ec1555SBarry Smith   for (i=0; i<size; i++) nsends += sizes[2*i+1];
3798965ea79SLois Curfman McInnes 
3808965ea79SLois Curfman McInnes   /* inform other processors of number of messages and max length*/
38176ec1555SBarry Smith   ierr = PetscMaxSum(comm,sizes,&nmax,&nrecvs);CHKERRQ(ierr);
3828965ea79SLois Curfman McInnes 
3838965ea79SLois Curfman McInnes   /* post receives:   */
384785e854fSJed Brown   ierr = PetscMalloc1((nrecvs+1)*(nmax+1),&rvalues);CHKERRQ(ierr);
385854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&recv_waits);CHKERRQ(ierr);
3868965ea79SLois Curfman McInnes   for (i=0; i<nrecvs; i++) {
38713f74950SBarry Smith     ierr = MPI_Irecv(rvalues+nmax*i,nmax,MPIU_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr);
3888965ea79SLois Curfman McInnes   }
3898965ea79SLois Curfman McInnes 
3908965ea79SLois Curfman McInnes   /* do sends:
3918965ea79SLois Curfman McInnes       1) starts[i] gives the starting index in svalues for stuff going to
3928965ea79SLois Curfman McInnes          the ith processor
3938965ea79SLois Curfman McInnes   */
394854ce69bSBarry Smith   ierr = PetscMalloc1(N+1,&svalues);CHKERRQ(ierr);
395854ce69bSBarry Smith   ierr = PetscMalloc1(nsends+1,&send_waits);CHKERRQ(ierr);
396854ce69bSBarry Smith   ierr = PetscMalloc1(size+1,&starts);CHKERRQ(ierr);
3978965ea79SLois Curfman McInnes 
3988965ea79SLois Curfman McInnes   starts[0] = 0;
39976ec1555SBarry Smith   for (i=1; i<size; i++) starts[i] = starts[i-1] + sizes[2*i-2];
4002205254eSKarl Rupp   for (i=0; i<N; i++) svalues[starts[owner[i]]++] = rows[i];
4012205254eSKarl Rupp 
4022205254eSKarl Rupp   starts[0] = 0;
40376ec1555SBarry Smith   for (i=1; i<size+1; i++) starts[i] = starts[i-1] + sizes[2*i-2];
4048965ea79SLois Curfman McInnes   count = 0;
4058965ea79SLois Curfman McInnes   for (i=0; i<size; i++) {
40676ec1555SBarry Smith     if (sizes[2*i+1]) {
40776ec1555SBarry Smith       ierr = MPI_Isend(svalues+starts[i],sizes[2*i],MPIU_INT,i,tag,comm,send_waits+count++);CHKERRQ(ierr);
4088965ea79SLois Curfman McInnes     }
4098965ea79SLois Curfman McInnes   }
410606d414cSSatish Balay   ierr = PetscFree(starts);CHKERRQ(ierr);
4118965ea79SLois Curfman McInnes 
4128965ea79SLois Curfman McInnes   base = owners[rank];
4138965ea79SLois Curfman McInnes 
4148965ea79SLois Curfman McInnes   /*  wait on receives */
415dcca6d9dSJed Brown   ierr  = PetscMalloc2(nrecvs,&lens,nrecvs,&source);CHKERRQ(ierr);
41674ed9c26SBarry Smith   count = nrecvs;
41774ed9c26SBarry Smith   slen  = 0;
4188965ea79SLois Curfman McInnes   while (count) {
419ca161407SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
4208965ea79SLois Curfman McInnes     /* unpack receives into our local space */
42113f74950SBarry Smith     ierr = MPI_Get_count(&recv_status,MPIU_INT,&n);CHKERRQ(ierr);
4222205254eSKarl Rupp 
4238965ea79SLois Curfman McInnes     source[imdex] = recv_status.MPI_SOURCE;
4248965ea79SLois Curfman McInnes     lens[imdex]   = n;
4258965ea79SLois Curfman McInnes     slen += n;
4268965ea79SLois Curfman McInnes     count--;
4278965ea79SLois Curfman McInnes   }
428606d414cSSatish Balay   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
4298965ea79SLois Curfman McInnes 
4308965ea79SLois Curfman McInnes   /* move the data into the send scatter */
431854ce69bSBarry Smith   ierr  = PetscMalloc1(slen+1,&lrows);CHKERRQ(ierr);
4328965ea79SLois Curfman McInnes   count = 0;
4338965ea79SLois Curfman McInnes   for (i=0; i<nrecvs; i++) {
4348965ea79SLois Curfman McInnes     values = rvalues + i*nmax;
4358965ea79SLois Curfman McInnes     for (j=0; j<lens[i]; j++) {
4368965ea79SLois Curfman McInnes       lrows[count++] = values[j] - base;
4378965ea79SLois Curfman McInnes     }
4388965ea79SLois Curfman McInnes   }
439606d414cSSatish Balay   ierr = PetscFree(rvalues);CHKERRQ(ierr);
44074ed9c26SBarry Smith   ierr = PetscFree2(lens,source);CHKERRQ(ierr);
441606d414cSSatish Balay   ierr = PetscFree(owner);CHKERRQ(ierr);
44276ec1555SBarry Smith   ierr = PetscFree(sizes);CHKERRQ(ierr);
4438965ea79SLois Curfman McInnes 
44497b48c8fSBarry Smith   /* fix right hand side if needed */
44597b48c8fSBarry Smith   if (x && b) {
44697b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
44797b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
44897b48c8fSBarry Smith     for (i=0; i<slen; i++) {
44997b48c8fSBarry Smith       bb[lrows[i]] = diag*xx[lrows[i]];
45097b48c8fSBarry Smith     }
45197b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
45297b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
45397b48c8fSBarry Smith   }
45497b48c8fSBarry Smith 
4558965ea79SLois Curfman McInnes   /* actually zap the local rows */
456b9679d65SBarry Smith   ierr = MatZeroRows(l->A,slen,lrows,0.0,0,0);CHKERRQ(ierr);
457e2eb51b1SBarry Smith   if (diag != 0.0) {
458b9679d65SBarry Smith     Mat_SeqDense *ll = (Mat_SeqDense*)l->A->data;
459b9679d65SBarry Smith     PetscInt     m   = ll->lda, i;
460b9679d65SBarry Smith 
461b9679d65SBarry Smith     for (i=0; i<slen; i++) {
462b9679d65SBarry Smith       ll->v[lrows[i] + m*(A->cmap->rstart + lrows[i])] = diag;
463b9679d65SBarry Smith     }
464b9679d65SBarry Smith   }
465606d414cSSatish Balay   ierr = PetscFree(lrows);CHKERRQ(ierr);
4668965ea79SLois Curfman McInnes 
4678965ea79SLois Curfman McInnes   /* wait on sends */
4688965ea79SLois Curfman McInnes   if (nsends) {
469785e854fSJed Brown     ierr = PetscMalloc1(nsends,&send_status);CHKERRQ(ierr);
470ca161407SBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
471606d414cSSatish Balay     ierr = PetscFree(send_status);CHKERRQ(ierr);
4728965ea79SLois Curfman McInnes   }
473606d414cSSatish Balay   ierr = PetscFree(send_waits);CHKERRQ(ierr);
474606d414cSSatish Balay   ierr = PetscFree(svalues);CHKERRQ(ierr);
4753a40ed3dSBarry Smith   PetscFunctionReturn(0);
4768965ea79SLois Curfman McInnes }
4778965ea79SLois Curfman McInnes 
478cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatMult_SeqDense(Mat,Vec,Vec);
479cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatMultAdd_SeqDense(Mat,Vec,Vec,Vec);
480cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatMultTranspose_SeqDense(Mat,Vec,Vec);
481cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatMultTransposeAdd_SeqDense(Mat,Vec,Vec,Vec);
482cc2e6a90SBarry Smith 
483dfbe8321SBarry Smith PetscErrorCode MatMult_MPIDense(Mat mat,Vec xx,Vec yy)
4848965ea79SLois Curfman McInnes {
48539ddd567SLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)mat->data;
486dfbe8321SBarry Smith   PetscErrorCode ierr;
487c456f294SBarry Smith 
4883a40ed3dSBarry Smith   PetscFunctionBegin;
489ca9f406cSSatish Balay   ierr = VecScatterBegin(mdn->Mvctx,xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
490ca9f406cSSatish Balay   ierr = VecScatterEnd(mdn->Mvctx,xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
491cc2e6a90SBarry Smith   ierr = MatMult_SeqDense(mdn->A,mdn->lvec,yy);CHKERRQ(ierr);
4923a40ed3dSBarry Smith   PetscFunctionReturn(0);
4938965ea79SLois Curfman McInnes }
4948965ea79SLois Curfman McInnes 
495dfbe8321SBarry Smith PetscErrorCode MatMultAdd_MPIDense(Mat mat,Vec xx,Vec yy,Vec zz)
4968965ea79SLois Curfman McInnes {
49739ddd567SLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)mat->data;
498dfbe8321SBarry Smith   PetscErrorCode ierr;
499c456f294SBarry Smith 
5003a40ed3dSBarry Smith   PetscFunctionBegin;
501ca9f406cSSatish Balay   ierr = VecScatterBegin(mdn->Mvctx,xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
502ca9f406cSSatish Balay   ierr = VecScatterEnd(mdn->Mvctx,xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
503cc2e6a90SBarry Smith   ierr = MatMultAdd_SeqDense(mdn->A,mdn->lvec,yy,zz);CHKERRQ(ierr);
5043a40ed3dSBarry Smith   PetscFunctionReturn(0);
5058965ea79SLois Curfman McInnes }
5068965ea79SLois Curfman McInnes 
507dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_MPIDense(Mat A,Vec xx,Vec yy)
508096963f5SLois Curfman McInnes {
509096963f5SLois Curfman McInnes   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
510dfbe8321SBarry Smith   PetscErrorCode ierr;
51187828ca2SBarry Smith   PetscScalar    zero = 0.0;
512096963f5SLois Curfman McInnes 
5133a40ed3dSBarry Smith   PetscFunctionBegin;
5142dcb1b2aSMatthew Knepley   ierr = VecSet(yy,zero);CHKERRQ(ierr);
515cc2e6a90SBarry Smith   ierr = MatMultTranspose_SeqDense(a->A,xx,a->lvec);CHKERRQ(ierr);
516ca9f406cSSatish Balay   ierr = VecScatterBegin(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
517ca9f406cSSatish Balay   ierr = VecScatterEnd(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5183a40ed3dSBarry Smith   PetscFunctionReturn(0);
519096963f5SLois Curfman McInnes }
520096963f5SLois Curfman McInnes 
521dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_MPIDense(Mat A,Vec xx,Vec yy,Vec zz)
522096963f5SLois Curfman McInnes {
523096963f5SLois Curfman McInnes   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
524dfbe8321SBarry Smith   PetscErrorCode ierr;
525096963f5SLois Curfman McInnes 
5263a40ed3dSBarry Smith   PetscFunctionBegin;
5273501a2bdSLois Curfman McInnes   ierr = VecCopy(yy,zz);CHKERRQ(ierr);
528cc2e6a90SBarry Smith   ierr = MatMultTranspose_SeqDense(a->A,xx,a->lvec);CHKERRQ(ierr);
529ca9f406cSSatish Balay   ierr = VecScatterBegin(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
530ca9f406cSSatish Balay   ierr = VecScatterEnd(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5313a40ed3dSBarry Smith   PetscFunctionReturn(0);
532096963f5SLois Curfman McInnes }
533096963f5SLois Curfman McInnes 
534dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_MPIDense(Mat A,Vec v)
5358965ea79SLois Curfman McInnes {
53639ddd567SLois Curfman McInnes   Mat_MPIDense   *a    = (Mat_MPIDense*)A->data;
537096963f5SLois Curfman McInnes   Mat_SeqDense   *aloc = (Mat_SeqDense*)a->A->data;
538dfbe8321SBarry Smith   PetscErrorCode ierr;
539d0f46423SBarry Smith   PetscInt       len,i,n,m = A->rmap->n,radd;
54087828ca2SBarry Smith   PetscScalar    *x,zero = 0.0;
541ed3cc1f0SBarry Smith 
5423a40ed3dSBarry Smith   PetscFunctionBegin;
5432dcb1b2aSMatthew Knepley   ierr = VecSet(v,zero);CHKERRQ(ierr);
5441ebc52fbSHong Zhang   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
545096963f5SLois Curfman McInnes   ierr = VecGetSize(v,&n);CHKERRQ(ierr);
546e32f2f54SBarry Smith   if (n != A->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming mat and vec");
547d0f46423SBarry Smith   len  = PetscMin(a->A->rmap->n,a->A->cmap->n);
548d0f46423SBarry Smith   radd = A->rmap->rstart*m;
54944cd7ae7SLois Curfman McInnes   for (i=0; i<len; i++) {
550096963f5SLois Curfman McInnes     x[i] = aloc->v[radd + i*m + i];
551096963f5SLois Curfman McInnes   }
5521ebc52fbSHong Zhang   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
5533a40ed3dSBarry Smith   PetscFunctionReturn(0);
5548965ea79SLois Curfman McInnes }
5558965ea79SLois Curfman McInnes 
556dfbe8321SBarry Smith PetscErrorCode MatDestroy_MPIDense(Mat mat)
5578965ea79SLois Curfman McInnes {
5583501a2bdSLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)mat->data;
559dfbe8321SBarry Smith   PetscErrorCode ierr;
560ed3cc1f0SBarry Smith 
5613a40ed3dSBarry Smith   PetscFunctionBegin;
562aa482453SBarry Smith #if defined(PETSC_USE_LOG)
563d0f46423SBarry Smith   PetscLogObjectState((PetscObject)mat,"Rows=%D, Cols=%D",mat->rmap->N,mat->cmap->N);
5648965ea79SLois Curfman McInnes #endif
5658798bf22SSatish Balay   ierr = MatStashDestroy_Private(&mat->stash);CHKERRQ(ierr);
5666bf464f9SBarry Smith   ierr = MatDestroy(&mdn->A);CHKERRQ(ierr);
5676bf464f9SBarry Smith   ierr = VecDestroy(&mdn->lvec);CHKERRQ(ierr);
5686bf464f9SBarry Smith   ierr = VecScatterDestroy(&mdn->Mvctx);CHKERRQ(ierr);
56901b82886SBarry Smith 
570bf0cc555SLisandro Dalcin   ierr = PetscFree(mat->data);CHKERRQ(ierr);
571dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)mat,0);CHKERRQ(ierr);
5728baccfbdSHong Zhang 
5738baccfbdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetArray_C",NULL);CHKERRQ(ierr);
5748572280aSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreArray_C",NULL);CHKERRQ(ierr);
5758572280aSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetArrayRead_C",NULL);CHKERRQ(ierr);
5768572280aSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreArrayRead_C",NULL);CHKERRQ(ierr);
577d3042a70SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDensePlaceArray_C",NULL);CHKERRQ(ierr);
578d3042a70SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseResetArray_C",NULL);CHKERRQ(ierr);
5798baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
5808baccfbdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpidense_elemental_C",NULL);CHKERRQ(ierr);
5818baccfbdSHong Zhang #endif
582bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIDenseSetPreallocation_C",NULL);CHKERRQ(ierr);
583bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMult_mpiaij_mpidense_C",NULL);CHKERRQ(ierr);
584bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMultSymbolic_mpiaij_mpidense_C",NULL);CHKERRQ(ierr);
585bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMultNumeric_mpiaij_mpidense_C",NULL);CHKERRQ(ierr);
5868baccfbdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMult_mpiaij_mpidense_C",NULL);CHKERRQ(ierr);
5878baccfbdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultSymbolic_mpiaij_mpidense_C",NULL);CHKERRQ(ierr);
5888baccfbdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultNumeric_mpiaij_mpidense_C",NULL);CHKERRQ(ierr);
58986aefd0dSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetColumn_C",NULL);CHKERRQ(ierr);
59086aefd0dSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreColumn_C",NULL);CHKERRQ(ierr);
5913a40ed3dSBarry Smith   PetscFunctionReturn(0);
5928965ea79SLois Curfman McInnes }
59339ddd567SLois Curfman McInnes 
5946849ba73SBarry Smith static PetscErrorCode MatView_MPIDense_Binary(Mat mat,PetscViewer viewer)
5958965ea79SLois Curfman McInnes {
59639ddd567SLois Curfman McInnes   Mat_MPIDense      *mdn = (Mat_MPIDense*)mat->data;
597dfbe8321SBarry Smith   PetscErrorCode    ierr;
598aa05aa95SBarry Smith   PetscViewerFormat format;
599aa05aa95SBarry Smith   int               fd;
600d0f46423SBarry Smith   PetscInt          header[4],mmax,N = mat->cmap->N,i,j,m,k;
601aa05aa95SBarry Smith   PetscMPIInt       rank,tag  = ((PetscObject)viewer)->tag,size;
602578230a0SSatish Balay   PetscScalar       *work,*v,*vv;
603aa05aa95SBarry Smith   Mat_SeqDense      *a = (Mat_SeqDense*)mdn->A->data;
6047056b6fcSBarry Smith 
6053a40ed3dSBarry Smith   PetscFunctionBegin;
60639ddd567SLois Curfman McInnes   if (mdn->size == 1) {
60739ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer);CHKERRQ(ierr);
608aa05aa95SBarry Smith   } else {
609aa05aa95SBarry Smith     ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
610ce94432eSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
611ce94432eSBarry Smith     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
612aa05aa95SBarry Smith 
613aa05aa95SBarry Smith     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
614f4403165SShri Abhyankar     if (format == PETSC_VIEWER_NATIVE) {
615aa05aa95SBarry Smith 
616aa05aa95SBarry Smith       if (!rank) {
617aa05aa95SBarry Smith         /* store the matrix as a dense matrix */
6180700a824SBarry Smith         header[0] = MAT_FILE_CLASSID;
619d0f46423SBarry Smith         header[1] = mat->rmap->N;
620aa05aa95SBarry Smith         header[2] = N;
621aa05aa95SBarry Smith         header[3] = MATRIX_BINARY_FORMAT_DENSE;
622aa05aa95SBarry Smith         ierr      = PetscBinaryWrite(fd,header,4,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
623aa05aa95SBarry Smith 
624aa05aa95SBarry Smith         /* get largest work array needed for transposing array */
625d0f46423SBarry Smith         mmax = mat->rmap->n;
626aa05aa95SBarry Smith         for (i=1; i<size; i++) {
627d0f46423SBarry Smith           mmax = PetscMax(mmax,mat->rmap->range[i+1] - mat->rmap->range[i]);
6288965ea79SLois Curfman McInnes         }
629785e854fSJed Brown         ierr = PetscMalloc1(mmax*N,&work);CHKERRQ(ierr);
630aa05aa95SBarry Smith 
631aa05aa95SBarry Smith         /* write out local array, by rows */
632d0f46423SBarry Smith         m = mat->rmap->n;
633aa05aa95SBarry Smith         v = a->v;
634aa05aa95SBarry Smith         for (j=0; j<N; j++) {
635aa05aa95SBarry Smith           for (i=0; i<m; i++) {
636578230a0SSatish Balay             work[j + i*N] = *v++;
637aa05aa95SBarry Smith           }
638aa05aa95SBarry Smith         }
639aa05aa95SBarry Smith         ierr = PetscBinaryWrite(fd,work,m*N,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
640aa05aa95SBarry Smith         /* get largest work array to receive messages from other processes, excludes process zero */
641aa05aa95SBarry Smith         mmax = 0;
642aa05aa95SBarry Smith         for (i=1; i<size; i++) {
643d0f46423SBarry Smith           mmax = PetscMax(mmax,mat->rmap->range[i+1] - mat->rmap->range[i]);
644aa05aa95SBarry Smith         }
645785e854fSJed Brown         ierr = PetscMalloc1(mmax*N,&vv);CHKERRQ(ierr);
646aa05aa95SBarry Smith         for (k = 1; k < size; k++) {
647f8009846SMatthew Knepley           v    = vv;
648d0f46423SBarry Smith           m    = mat->rmap->range[k+1] - mat->rmap->range[k];
649ce94432eSBarry Smith           ierr = MPIULong_Recv(v,m*N,MPIU_SCALAR,k,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
650aa05aa95SBarry Smith 
651aa05aa95SBarry Smith           for (j = 0; j < N; j++) {
652aa05aa95SBarry Smith             for (i = 0; i < m; i++) {
653578230a0SSatish Balay               work[j + i*N] = *v++;
654aa05aa95SBarry Smith             }
655aa05aa95SBarry Smith           }
656aa05aa95SBarry Smith           ierr = PetscBinaryWrite(fd,work,m*N,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
657aa05aa95SBarry Smith         }
658aa05aa95SBarry Smith         ierr = PetscFree(work);CHKERRQ(ierr);
659578230a0SSatish Balay         ierr = PetscFree(vv);CHKERRQ(ierr);
660aa05aa95SBarry Smith       } else {
661ce94432eSBarry Smith         ierr = MPIULong_Send(a->v,mat->rmap->n*mat->cmap->N,MPIU_SCALAR,0,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
662aa05aa95SBarry Smith       }
6636a9046bcSBarry Smith     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"To store a parallel dense matrix you must first call PetscViewerPushFormat(viewer,PETSC_VIEWER_NATIVE)");
664aa05aa95SBarry Smith   }
6653a40ed3dSBarry Smith   PetscFunctionReturn(0);
6668965ea79SLois Curfman McInnes }
6678965ea79SLois Curfman McInnes 
6687da1fb6eSBarry Smith extern PetscErrorCode MatView_SeqDense(Mat,PetscViewer);
6699804daf3SBarry Smith #include <petscdraw.h>
6706849ba73SBarry Smith static PetscErrorCode MatView_MPIDense_ASCIIorDraworSocket(Mat mat,PetscViewer viewer)
6718965ea79SLois Curfman McInnes {
67239ddd567SLois Curfman McInnes   Mat_MPIDense      *mdn = (Mat_MPIDense*)mat->data;
673dfbe8321SBarry Smith   PetscErrorCode    ierr;
6747da1fb6eSBarry Smith   PetscMPIInt       rank = mdn->rank;
67519fd82e9SBarry Smith   PetscViewerType   vtype;
676ace3abfcSBarry Smith   PetscBool         iascii,isdraw;
677b0a32e0cSBarry Smith   PetscViewer       sviewer;
678f3ef73ceSBarry Smith   PetscViewerFormat format;
6798965ea79SLois Curfman McInnes 
6803a40ed3dSBarry Smith   PetscFunctionBegin;
681251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
682251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
68332077d6dSBarry Smith   if (iascii) {
684b0a32e0cSBarry Smith     ierr = PetscViewerGetType(viewer,&vtype);CHKERRQ(ierr);
685b0a32e0cSBarry Smith     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
686456192e2SBarry Smith     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
6874e220ebcSLois Curfman McInnes       MatInfo info;
688888f2ed8SSatish Balay       ierr = MatGetInfo(mat,MAT_LOCAL,&info);CHKERRQ(ierr);
6891575c14dSBarry Smith       ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
6907b23a99aSBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"  [%d] local rows %D nz %D nz alloced %D mem %D \n",rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr);
691b0a32e0cSBarry Smith       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
6921575c14dSBarry Smith       ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
6935d00a290SHong Zhang       ierr = VecScatterView(mdn->Mvctx,viewer);CHKERRQ(ierr);
6943a40ed3dSBarry Smith       PetscFunctionReturn(0);
695fb9695e5SSatish Balay     } else if (format == PETSC_VIEWER_ASCII_INFO) {
6963a40ed3dSBarry Smith       PetscFunctionReturn(0);
6978965ea79SLois Curfman McInnes     }
698f1af5d2fSBarry Smith   } else if (isdraw) {
699b0a32e0cSBarry Smith     PetscDraw draw;
700ace3abfcSBarry Smith     PetscBool isnull;
701f1af5d2fSBarry Smith 
702b0a32e0cSBarry Smith     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
703b0a32e0cSBarry Smith     ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
704f1af5d2fSBarry Smith     if (isnull) PetscFunctionReturn(0);
705f1af5d2fSBarry Smith   }
70677ed5343SBarry Smith 
7077da1fb6eSBarry Smith   {
7088965ea79SLois Curfman McInnes     /* assemble the entire matrix onto first processor. */
7098965ea79SLois Curfman McInnes     Mat         A;
710d0f46423SBarry Smith     PetscInt    M = mat->rmap->N,N = mat->cmap->N,m,row,i,nz;
711ba8c8a56SBarry Smith     PetscInt    *cols;
712ba8c8a56SBarry Smith     PetscScalar *vals;
7138965ea79SLois Curfman McInnes 
714ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)mat),&A);CHKERRQ(ierr);
7158965ea79SLois Curfman McInnes     if (!rank) {
716f69a0ea3SMatthew Knepley       ierr = MatSetSizes(A,M,N,M,N);CHKERRQ(ierr);
7173a40ed3dSBarry Smith     } else {
718f69a0ea3SMatthew Knepley       ierr = MatSetSizes(A,0,0,M,N);CHKERRQ(ierr);
7198965ea79SLois Curfman McInnes     }
7207adad957SLisandro Dalcin     /* Since this is a temporary matrix, MATMPIDENSE instead of ((PetscObject)A)->type_name here is probably acceptable. */
721878740d9SKris Buschelman     ierr = MatSetType(A,MATMPIDENSE);CHKERRQ(ierr);
7220298fd71SBarry Smith     ierr = MatMPIDenseSetPreallocation(A,NULL);CHKERRQ(ierr);
7233bb1ff40SBarry Smith     ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)A);CHKERRQ(ierr);
7248965ea79SLois Curfman McInnes 
72539ddd567SLois Curfman McInnes     /* Copy the matrix ... This isn't the most efficient means,
72639ddd567SLois Curfman McInnes        but it's quick for now */
72751022da4SBarry Smith     A->insertmode = INSERT_VALUES;
7282205254eSKarl Rupp 
7292205254eSKarl Rupp     row = mat->rmap->rstart;
7302205254eSKarl Rupp     m   = mdn->A->rmap->n;
7318965ea79SLois Curfman McInnes     for (i=0; i<m; i++) {
732ba8c8a56SBarry Smith       ierr = MatGetRow_MPIDense(mat,row,&nz,&cols,&vals);CHKERRQ(ierr);
733ba8c8a56SBarry Smith       ierr = MatSetValues_MPIDense(A,1,&row,nz,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
734ba8c8a56SBarry Smith       ierr = MatRestoreRow_MPIDense(mat,row,&nz,&cols,&vals);CHKERRQ(ierr);
73539ddd567SLois Curfman McInnes       row++;
7368965ea79SLois Curfman McInnes     }
7378965ea79SLois Curfman McInnes 
7386d4a8577SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7396d4a8577SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7403f08860eSBarry Smith     ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
741b9b97703SBarry Smith     if (!rank) {
7421a9d3c3cSBarry Smith       ierr = PetscObjectSetName((PetscObject)((Mat_MPIDense*)(A->data))->A,((PetscObject)mat)->name);CHKERRQ(ierr);
7437da1fb6eSBarry Smith       ierr = MatView_SeqDense(((Mat_MPIDense*)(A->data))->A,sviewer);CHKERRQ(ierr);
7448965ea79SLois Curfman McInnes     }
7453f08860eSBarry Smith     ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
746b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
7476bf464f9SBarry Smith     ierr = MatDestroy(&A);CHKERRQ(ierr);
7488965ea79SLois Curfman McInnes   }
7493a40ed3dSBarry Smith   PetscFunctionReturn(0);
7508965ea79SLois Curfman McInnes }
7518965ea79SLois Curfman McInnes 
752dfbe8321SBarry Smith PetscErrorCode MatView_MPIDense(Mat mat,PetscViewer viewer)
7538965ea79SLois Curfman McInnes {
754dfbe8321SBarry Smith   PetscErrorCode ierr;
755ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw,issocket;
7568965ea79SLois Curfman McInnes 
757433994e6SBarry Smith   PetscFunctionBegin;
758251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
759251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
760251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSOCKET,&issocket);CHKERRQ(ierr);
761251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
7620f5bd95cSBarry Smith 
76332077d6dSBarry Smith   if (iascii || issocket || isdraw) {
764f1af5d2fSBarry Smith     ierr = MatView_MPIDense_ASCIIorDraworSocket(mat,viewer);CHKERRQ(ierr);
7650f5bd95cSBarry Smith   } else if (isbinary) {
7663a40ed3dSBarry Smith     ierr = MatView_MPIDense_Binary(mat,viewer);CHKERRQ(ierr);
76711aeaf0aSBarry Smith   }
7683a40ed3dSBarry Smith   PetscFunctionReturn(0);
7698965ea79SLois Curfman McInnes }
7708965ea79SLois Curfman McInnes 
771dfbe8321SBarry Smith PetscErrorCode MatGetInfo_MPIDense(Mat A,MatInfoType flag,MatInfo *info)
7728965ea79SLois Curfman McInnes {
7733501a2bdSLois Curfman McInnes   Mat_MPIDense   *mat = (Mat_MPIDense*)A->data;
7743501a2bdSLois Curfman McInnes   Mat            mdn  = mat->A;
775dfbe8321SBarry Smith   PetscErrorCode ierr;
776329f5518SBarry Smith   PetscReal      isend[5],irecv[5];
7778965ea79SLois Curfman McInnes 
7783a40ed3dSBarry Smith   PetscFunctionBegin;
7794e220ebcSLois Curfman McInnes   info->block_size = 1.0;
7802205254eSKarl Rupp 
7814e220ebcSLois Curfman McInnes   ierr = MatGetInfo(mdn,MAT_LOCAL,info);CHKERRQ(ierr);
7822205254eSKarl Rupp 
7834e220ebcSLois Curfman McInnes   isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded;
7844e220ebcSLois Curfman McInnes   isend[3] = info->memory;  isend[4] = info->mallocs;
7858965ea79SLois Curfman McInnes   if (flag == MAT_LOCAL) {
7864e220ebcSLois Curfman McInnes     info->nz_used      = isend[0];
7874e220ebcSLois Curfman McInnes     info->nz_allocated = isend[1];
7884e220ebcSLois Curfman McInnes     info->nz_unneeded  = isend[2];
7894e220ebcSLois Curfman McInnes     info->memory       = isend[3];
7904e220ebcSLois Curfman McInnes     info->mallocs      = isend[4];
7918965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_MAX) {
792b2566f29SBarry Smith     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
7932205254eSKarl Rupp 
7944e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
7954e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
7964e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
7974e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
7984e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
7998965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_SUM) {
800b2566f29SBarry Smith     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
8012205254eSKarl Rupp 
8024e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
8034e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
8044e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
8054e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
8064e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
8078965ea79SLois Curfman McInnes   }
8084e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0; /* no parallel LU/ILU/Cholesky */
8094e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
8104e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
8113a40ed3dSBarry Smith   PetscFunctionReturn(0);
8128965ea79SLois Curfman McInnes }
8138965ea79SLois Curfman McInnes 
814ace3abfcSBarry Smith PetscErrorCode MatSetOption_MPIDense(Mat A,MatOption op,PetscBool flg)
8158965ea79SLois Curfman McInnes {
81639ddd567SLois Curfman McInnes   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
817dfbe8321SBarry Smith   PetscErrorCode ierr;
8188965ea79SLois Curfman McInnes 
8193a40ed3dSBarry Smith   PetscFunctionBegin;
82012c028f9SKris Buschelman   switch (op) {
821512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
82212c028f9SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
82312c028f9SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
82443674050SBarry Smith     MatCheckPreallocated(A,1);
8254e0d8c25SBarry Smith     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
82612c028f9SKris Buschelman     break;
82712c028f9SKris Buschelman   case MAT_ROW_ORIENTED:
82843674050SBarry Smith     MatCheckPreallocated(A,1);
8294e0d8c25SBarry Smith     a->roworiented = flg;
8304e0d8c25SBarry Smith     ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
83112c028f9SKris Buschelman     break;
8324e0d8c25SBarry Smith   case MAT_NEW_DIAGONALS:
83313fa8e87SLisandro Dalcin   case MAT_KEEP_NONZERO_PATTERN:
83412c028f9SKris Buschelman   case MAT_USE_HASH_TABLE:
835290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
83612c028f9SKris Buschelman     break;
83712c028f9SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
8384e0d8c25SBarry Smith     a->donotstash = flg;
83912c028f9SKris Buschelman     break;
84077e54ba9SKris Buschelman   case MAT_SYMMETRIC:
84177e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
8429a4540c5SBarry Smith   case MAT_HERMITIAN:
8439a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
844600fe468SBarry Smith   case MAT_IGNORE_LOWER_TRIANGULAR:
845290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
84677e54ba9SKris Buschelman     break;
84712c028f9SKris Buschelman   default:
848e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %s",MatOptions[op]);
8493a40ed3dSBarry Smith   }
8503a40ed3dSBarry Smith   PetscFunctionReturn(0);
8518965ea79SLois Curfman McInnes }
8528965ea79SLois Curfman McInnes 
8538965ea79SLois Curfman McInnes 
854dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_MPIDense(Mat A,Vec ll,Vec rr)
8555b2fa520SLois Curfman McInnes {
8565b2fa520SLois Curfman McInnes   Mat_MPIDense      *mdn = (Mat_MPIDense*)A->data;
8575b2fa520SLois Curfman McInnes   Mat_SeqDense      *mat = (Mat_SeqDense*)mdn->A->data;
858bca11509SBarry Smith   const PetscScalar *l,*r;
859bca11509SBarry Smith   PetscScalar       x,*v;
860dfbe8321SBarry Smith   PetscErrorCode    ierr;
861d0f46423SBarry Smith   PetscInt          i,j,s2a,s3a,s2,s3,m=mdn->A->rmap->n,n=mdn->A->cmap->n;
8625b2fa520SLois Curfman McInnes 
8635b2fa520SLois Curfman McInnes   PetscFunctionBegin;
86472d926a5SLois Curfman McInnes   ierr = MatGetLocalSize(A,&s2,&s3);CHKERRQ(ierr);
8655b2fa520SLois Curfman McInnes   if (ll) {
86672d926a5SLois Curfman McInnes     ierr = VecGetLocalSize(ll,&s2a);CHKERRQ(ierr);
867e32f2f54SBarry Smith     if (s2a != s2) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector non-conforming local size, %d != %d.", s2a, s2);
868bca11509SBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
8695b2fa520SLois Curfman McInnes     for (i=0; i<m; i++) {
8705b2fa520SLois Curfman McInnes       x = l[i];
8715b2fa520SLois Curfman McInnes       v = mat->v + i;
8725b2fa520SLois Curfman McInnes       for (j=0; j<n; j++) { (*v) *= x; v+= m;}
8735b2fa520SLois Curfman McInnes     }
874bca11509SBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
875efee365bSSatish Balay     ierr = PetscLogFlops(n*m);CHKERRQ(ierr);
8765b2fa520SLois Curfman McInnes   }
8775b2fa520SLois Curfman McInnes   if (rr) {
878175be7b4SMatthew Knepley     ierr = VecGetLocalSize(rr,&s3a);CHKERRQ(ierr);
879e32f2f54SBarry Smith     if (s3a != s3) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vec non-conforming local size, %d != %d.", s3a, s3);
880ca9f406cSSatish Balay     ierr = VecScatterBegin(mdn->Mvctx,rr,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
881ca9f406cSSatish Balay     ierr = VecScatterEnd(mdn->Mvctx,rr,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
882bca11509SBarry Smith     ierr = VecGetArrayRead(mdn->lvec,&r);CHKERRQ(ierr);
8835b2fa520SLois Curfman McInnes     for (i=0; i<n; i++) {
8845b2fa520SLois Curfman McInnes       x = r[i];
8855b2fa520SLois Curfman McInnes       v = mat->v + i*m;
8862205254eSKarl Rupp       for (j=0; j<m; j++) (*v++) *= x;
8875b2fa520SLois Curfman McInnes     }
888bca11509SBarry Smith     ierr = VecRestoreArrayRead(mdn->lvec,&r);CHKERRQ(ierr);
889efee365bSSatish Balay     ierr = PetscLogFlops(n*m);CHKERRQ(ierr);
8905b2fa520SLois Curfman McInnes   }
8915b2fa520SLois Curfman McInnes   PetscFunctionReturn(0);
8925b2fa520SLois Curfman McInnes }
8935b2fa520SLois Curfman McInnes 
894dfbe8321SBarry Smith PetscErrorCode MatNorm_MPIDense(Mat A,NormType type,PetscReal *nrm)
895096963f5SLois Curfman McInnes {
8963501a2bdSLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)A->data;
8973501a2bdSLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense*)mdn->A->data;
898dfbe8321SBarry Smith   PetscErrorCode ierr;
89913f74950SBarry Smith   PetscInt       i,j;
900329f5518SBarry Smith   PetscReal      sum = 0.0;
90187828ca2SBarry Smith   PetscScalar    *v  = mat->v;
9023501a2bdSLois Curfman McInnes 
9033a40ed3dSBarry Smith   PetscFunctionBegin;
9043501a2bdSLois Curfman McInnes   if (mdn->size == 1) {
905064f8208SBarry Smith     ierr =  MatNorm(mdn->A,type,nrm);CHKERRQ(ierr);
9063501a2bdSLois Curfman McInnes   } else {
9073501a2bdSLois Curfman McInnes     if (type == NORM_FROBENIUS) {
908d0f46423SBarry Smith       for (i=0; i<mdn->A->cmap->n*mdn->A->rmap->n; i++) {
909329f5518SBarry Smith         sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
9103501a2bdSLois Curfman McInnes       }
911b2566f29SBarry Smith       ierr = MPIU_Allreduce(&sum,nrm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
9128f1a2a5eSBarry Smith       *nrm = PetscSqrtReal(*nrm);
913dc0b31edSSatish Balay       ierr = PetscLogFlops(2.0*mdn->A->cmap->n*mdn->A->rmap->n);CHKERRQ(ierr);
9143a40ed3dSBarry Smith     } else if (type == NORM_1) {
915329f5518SBarry Smith       PetscReal *tmp,*tmp2;
916dcca6d9dSJed Brown       ierr = PetscMalloc2(A->cmap->N,&tmp,A->cmap->N,&tmp2);CHKERRQ(ierr);
91774ed9c26SBarry Smith       ierr = PetscMemzero(tmp,A->cmap->N*sizeof(PetscReal));CHKERRQ(ierr);
91874ed9c26SBarry Smith       ierr = PetscMemzero(tmp2,A->cmap->N*sizeof(PetscReal));CHKERRQ(ierr);
919064f8208SBarry Smith       *nrm = 0.0;
9203501a2bdSLois Curfman McInnes       v    = mat->v;
921d0f46423SBarry Smith       for (j=0; j<mdn->A->cmap->n; j++) {
922d0f46423SBarry Smith         for (i=0; i<mdn->A->rmap->n; i++) {
92367e560aaSBarry Smith           tmp[j] += PetscAbsScalar(*v);  v++;
9243501a2bdSLois Curfman McInnes         }
9253501a2bdSLois Curfman McInnes       }
926b2566f29SBarry Smith       ierr = MPIU_Allreduce(tmp,tmp2,A->cmap->N,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
927d0f46423SBarry Smith       for (j=0; j<A->cmap->N; j++) {
928064f8208SBarry Smith         if (tmp2[j] > *nrm) *nrm = tmp2[j];
9293501a2bdSLois Curfman McInnes       }
9308627564fSBarry Smith       ierr = PetscFree2(tmp,tmp2);CHKERRQ(ierr);
931d0f46423SBarry Smith       ierr = PetscLogFlops(A->cmap->n*A->rmap->n);CHKERRQ(ierr);
9323a40ed3dSBarry Smith     } else if (type == NORM_INFINITY) { /* max row norm */
933329f5518SBarry Smith       PetscReal ntemp;
9343501a2bdSLois Curfman McInnes       ierr = MatNorm(mdn->A,type,&ntemp);CHKERRQ(ierr);
935b2566f29SBarry Smith       ierr = MPIU_Allreduce(&ntemp,nrm,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
936ce94432eSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for two norm");
9373501a2bdSLois Curfman McInnes   }
9383a40ed3dSBarry Smith   PetscFunctionReturn(0);
9393501a2bdSLois Curfman McInnes }
9403501a2bdSLois Curfman McInnes 
941fc4dec0aSBarry Smith PetscErrorCode MatTranspose_MPIDense(Mat A,MatReuse reuse,Mat *matout)
9423501a2bdSLois Curfman McInnes {
9433501a2bdSLois Curfman McInnes   Mat_MPIDense   *a    = (Mat_MPIDense*)A->data;
9443501a2bdSLois Curfman McInnes   Mat_SeqDense   *Aloc = (Mat_SeqDense*)a->A->data;
9453501a2bdSLois Curfman McInnes   Mat            B;
946d0f46423SBarry Smith   PetscInt       M = A->rmap->N,N = A->cmap->N,m,n,*rwork,rstart = A->rmap->rstart;
9476849ba73SBarry Smith   PetscErrorCode ierr;
94813f74950SBarry Smith   PetscInt       j,i;
94987828ca2SBarry Smith   PetscScalar    *v;
9503501a2bdSLois Curfman McInnes 
9513a40ed3dSBarry Smith   PetscFunctionBegin;
952cf37664fSBarry Smith   if (reuse == MAT_INPLACE_MATRIX  && M != N) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Supports square matrix only in-place");
953cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
954ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
955d0f46423SBarry Smith     ierr = MatSetSizes(B,A->cmap->n,A->rmap->n,N,M);CHKERRQ(ierr);
9567adad957SLisandro Dalcin     ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr);
9570298fd71SBarry Smith     ierr = MatMPIDenseSetPreallocation(B,NULL);CHKERRQ(ierr);
958fc4dec0aSBarry Smith   } else {
959fc4dec0aSBarry Smith     B = *matout;
960fc4dec0aSBarry Smith   }
9613501a2bdSLois Curfman McInnes 
962d0f46423SBarry Smith   m    = a->A->rmap->n; n = a->A->cmap->n; v = Aloc->v;
963785e854fSJed Brown   ierr = PetscMalloc1(m,&rwork);CHKERRQ(ierr);
9643501a2bdSLois Curfman McInnes   for (i=0; i<m; i++) rwork[i] = rstart + i;
9651acff37aSSatish Balay   for (j=0; j<n; j++) {
9663501a2bdSLois Curfman McInnes     ierr = MatSetValues(B,1,&j,m,rwork,v,INSERT_VALUES);CHKERRQ(ierr);
9673501a2bdSLois Curfman McInnes     v   += m;
9683501a2bdSLois Curfman McInnes   }
969606d414cSSatish Balay   ierr = PetscFree(rwork);CHKERRQ(ierr);
9706d4a8577SBarry Smith   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9716d4a8577SBarry Smith   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
972cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
9733501a2bdSLois Curfman McInnes     *matout = B;
9743501a2bdSLois Curfman McInnes   } else {
97528be2f97SBarry Smith     ierr = MatHeaderMerge(A,&B);CHKERRQ(ierr);
9763501a2bdSLois Curfman McInnes   }
9773a40ed3dSBarry Smith   PetscFunctionReturn(0);
978096963f5SLois Curfman McInnes }
979096963f5SLois Curfman McInnes 
98044cd7ae7SLois Curfman McInnes 
9816849ba73SBarry Smith static PetscErrorCode MatDuplicate_MPIDense(Mat,MatDuplicateOption,Mat*);
982d84338a6SBarry Smith extern PetscErrorCode MatScale_MPIDense(Mat,PetscScalar);
9838965ea79SLois Curfman McInnes 
9844994cf47SJed Brown PetscErrorCode MatSetUp_MPIDense(Mat A)
985273d9f13SBarry Smith {
986dfbe8321SBarry Smith   PetscErrorCode ierr;
987273d9f13SBarry Smith 
988273d9f13SBarry Smith   PetscFunctionBegin;
989273d9f13SBarry Smith   ierr =  MatMPIDenseSetPreallocation(A,0);CHKERRQ(ierr);
990273d9f13SBarry Smith   PetscFunctionReturn(0);
991273d9f13SBarry Smith }
992273d9f13SBarry Smith 
993488007eeSBarry Smith PetscErrorCode MatAXPY_MPIDense(Mat Y,PetscScalar alpha,Mat X,MatStructure str)
994488007eeSBarry Smith {
995488007eeSBarry Smith   PetscErrorCode ierr;
996488007eeSBarry Smith   Mat_MPIDense   *A = (Mat_MPIDense*)Y->data, *B = (Mat_MPIDense*)X->data;
997488007eeSBarry Smith 
998488007eeSBarry Smith   PetscFunctionBegin;
999488007eeSBarry Smith   ierr = MatAXPY(A->A,alpha,B->A,str);CHKERRQ(ierr);
1000a3fa217bSJose E. Roman   ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
1001488007eeSBarry Smith   PetscFunctionReturn(0);
1002488007eeSBarry Smith }
1003488007eeSBarry Smith 
10047087cfbeSBarry Smith PetscErrorCode  MatConjugate_MPIDense(Mat mat)
1005ba337c44SJed Brown {
1006ba337c44SJed Brown   Mat_MPIDense   *a = (Mat_MPIDense*)mat->data;
1007ba337c44SJed Brown   PetscErrorCode ierr;
1008ba337c44SJed Brown 
1009ba337c44SJed Brown   PetscFunctionBegin;
1010ba337c44SJed Brown   ierr = MatConjugate(a->A);CHKERRQ(ierr);
1011ba337c44SJed Brown   PetscFunctionReturn(0);
1012ba337c44SJed Brown }
1013ba337c44SJed Brown 
1014ba337c44SJed Brown PetscErrorCode MatRealPart_MPIDense(Mat A)
1015ba337c44SJed Brown {
1016ba337c44SJed Brown   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
1017ba337c44SJed Brown   PetscErrorCode ierr;
1018ba337c44SJed Brown 
1019ba337c44SJed Brown   PetscFunctionBegin;
1020ba337c44SJed Brown   ierr = MatRealPart(a->A);CHKERRQ(ierr);
1021ba337c44SJed Brown   PetscFunctionReturn(0);
1022ba337c44SJed Brown }
1023ba337c44SJed Brown 
1024ba337c44SJed Brown PetscErrorCode MatImaginaryPart_MPIDense(Mat A)
1025ba337c44SJed Brown {
1026ba337c44SJed Brown   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
1027ba337c44SJed Brown   PetscErrorCode ierr;
1028ba337c44SJed Brown 
1029ba337c44SJed Brown   PetscFunctionBegin;
1030ba337c44SJed Brown   ierr = MatImaginaryPart(a->A);CHKERRQ(ierr);
1031ba337c44SJed Brown   PetscFunctionReturn(0);
1032ba337c44SJed Brown }
1033ba337c44SJed Brown 
10340716a85fSBarry Smith extern PetscErrorCode MatGetColumnNorms_SeqDense(Mat,NormType,PetscReal*);
10350716a85fSBarry Smith PetscErrorCode MatGetColumnNorms_MPIDense(Mat A,NormType type,PetscReal *norms)
10360716a85fSBarry Smith {
10370716a85fSBarry Smith   PetscErrorCode ierr;
10380716a85fSBarry Smith   PetscInt       i,n;
10390716a85fSBarry Smith   Mat_MPIDense   *a = (Mat_MPIDense*) A->data;
10400716a85fSBarry Smith   PetscReal      *work;
10410716a85fSBarry Smith 
10420716a85fSBarry Smith   PetscFunctionBegin;
10430298fd71SBarry Smith   ierr = MatGetSize(A,NULL,&n);CHKERRQ(ierr);
1044785e854fSJed Brown   ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
10450716a85fSBarry Smith   ierr = MatGetColumnNorms_SeqDense(a->A,type,work);CHKERRQ(ierr);
10460716a85fSBarry Smith   if (type == NORM_2) {
10470716a85fSBarry Smith     for (i=0; i<n; i++) work[i] *= work[i];
10480716a85fSBarry Smith   }
10490716a85fSBarry Smith   if (type == NORM_INFINITY) {
1050b2566f29SBarry Smith     ierr = MPIU_Allreduce(work,norms,n,MPIU_REAL,MPIU_MAX,A->hdr.comm);CHKERRQ(ierr);
10510716a85fSBarry Smith   } else {
1052b2566f29SBarry Smith     ierr = MPIU_Allreduce(work,norms,n,MPIU_REAL,MPIU_SUM,A->hdr.comm);CHKERRQ(ierr);
10530716a85fSBarry Smith   }
10540716a85fSBarry Smith   ierr = PetscFree(work);CHKERRQ(ierr);
10550716a85fSBarry Smith   if (type == NORM_2) {
10568f1a2a5eSBarry Smith     for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
10570716a85fSBarry Smith   }
10580716a85fSBarry Smith   PetscFunctionReturn(0);
10590716a85fSBarry Smith }
10600716a85fSBarry Smith 
106173a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_MPIDense(Mat x,PetscRandom rctx)
106273a71a0fSBarry Smith {
106373a71a0fSBarry Smith   Mat_MPIDense   *d = (Mat_MPIDense*)x->data;
106473a71a0fSBarry Smith   PetscErrorCode ierr;
106573a71a0fSBarry Smith   PetscScalar    *a;
106673a71a0fSBarry Smith   PetscInt       m,n,i;
106773a71a0fSBarry Smith 
106873a71a0fSBarry Smith   PetscFunctionBegin;
106973a71a0fSBarry Smith   ierr = MatGetSize(d->A,&m,&n);CHKERRQ(ierr);
10708c778c55SBarry Smith   ierr = MatDenseGetArray(d->A,&a);CHKERRQ(ierr);
107173a71a0fSBarry Smith   for (i=0; i<m*n; i++) {
107273a71a0fSBarry Smith     ierr = PetscRandomGetValue(rctx,a+i);CHKERRQ(ierr);
107373a71a0fSBarry Smith   }
10748c778c55SBarry Smith   ierr = MatDenseRestoreArray(d->A,&a);CHKERRQ(ierr);
107573a71a0fSBarry Smith   PetscFunctionReturn(0);
107673a71a0fSBarry Smith }
107773a71a0fSBarry Smith 
1078fd4e9aacSBarry Smith extern PetscErrorCode MatMatMultNumeric_MPIDense(Mat A,Mat,Mat);
1079fd4e9aacSBarry Smith 
10803b49f96aSBarry Smith static PetscErrorCode MatMissingDiagonal_MPIDense(Mat A,PetscBool  *missing,PetscInt *d)
10813b49f96aSBarry Smith {
10823b49f96aSBarry Smith   PetscFunctionBegin;
10833b49f96aSBarry Smith   *missing = PETSC_FALSE;
10843b49f96aSBarry Smith   PetscFunctionReturn(0);
10853b49f96aSBarry Smith }
10863b49f96aSBarry Smith 
10878965ea79SLois Curfman McInnes /* -------------------------------------------------------------------*/
108809dc0095SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_MPIDense,
108909dc0095SBarry Smith                                         MatGetRow_MPIDense,
109009dc0095SBarry Smith                                         MatRestoreRow_MPIDense,
109109dc0095SBarry Smith                                         MatMult_MPIDense,
109297304618SKris Buschelman                                 /*  4*/ MatMultAdd_MPIDense,
10937c922b88SBarry Smith                                         MatMultTranspose_MPIDense,
10947c922b88SBarry Smith                                         MatMultTransposeAdd_MPIDense,
10958965ea79SLois Curfman McInnes                                         0,
109609dc0095SBarry Smith                                         0,
109709dc0095SBarry Smith                                         0,
109897304618SKris Buschelman                                 /* 10*/ 0,
109909dc0095SBarry Smith                                         0,
110009dc0095SBarry Smith                                         0,
110109dc0095SBarry Smith                                         0,
110209dc0095SBarry Smith                                         MatTranspose_MPIDense,
110397304618SKris Buschelman                                 /* 15*/ MatGetInfo_MPIDense,
11046e4ee0c6SHong Zhang                                         MatEqual_MPIDense,
110509dc0095SBarry Smith                                         MatGetDiagonal_MPIDense,
11065b2fa520SLois Curfman McInnes                                         MatDiagonalScale_MPIDense,
110709dc0095SBarry Smith                                         MatNorm_MPIDense,
110897304618SKris Buschelman                                 /* 20*/ MatAssemblyBegin_MPIDense,
110909dc0095SBarry Smith                                         MatAssemblyEnd_MPIDense,
111009dc0095SBarry Smith                                         MatSetOption_MPIDense,
111109dc0095SBarry Smith                                         MatZeroEntries_MPIDense,
1112d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_MPIDense,
1113919b68f7SBarry Smith                                         0,
111401b82886SBarry Smith                                         0,
111501b82886SBarry Smith                                         0,
111601b82886SBarry Smith                                         0,
11174994cf47SJed Brown                                 /* 29*/ MatSetUp_MPIDense,
1118273d9f13SBarry Smith                                         0,
111909dc0095SBarry Smith                                         0,
1120c56a70eeSBarry Smith                                         MatGetDiagonalBlock_MPIDense,
11218c778c55SBarry Smith                                         0,
1122d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_MPIDense,
112309dc0095SBarry Smith                                         0,
112409dc0095SBarry Smith                                         0,
112509dc0095SBarry Smith                                         0,
112609dc0095SBarry Smith                                         0,
1127d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_MPIDense,
11287dae84e0SHong Zhang                                         MatCreateSubMatrices_MPIDense,
112909dc0095SBarry Smith                                         0,
113009dc0095SBarry Smith                                         MatGetValues_MPIDense,
113109dc0095SBarry Smith                                         0,
1132d519adbfSMatthew Knepley                                 /* 44*/ 0,
113309dc0095SBarry Smith                                         MatScale_MPIDense,
11347d68702bSBarry Smith                                         MatShift_Basic,
113509dc0095SBarry Smith                                         0,
113609dc0095SBarry Smith                                         0,
113773a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_MPIDense,
113809dc0095SBarry Smith                                         0,
113909dc0095SBarry Smith                                         0,
114009dc0095SBarry Smith                                         0,
114109dc0095SBarry Smith                                         0,
1142d519adbfSMatthew Knepley                                 /* 54*/ 0,
114309dc0095SBarry Smith                                         0,
114409dc0095SBarry Smith                                         0,
114509dc0095SBarry Smith                                         0,
114609dc0095SBarry Smith                                         0,
11477dae84e0SHong Zhang                                 /* 59*/ MatCreateSubMatrix_MPIDense,
1148b9b97703SBarry Smith                                         MatDestroy_MPIDense,
1149b9b97703SBarry Smith                                         MatView_MPIDense,
1150357abbc8SBarry Smith                                         0,
115197304618SKris Buschelman                                         0,
1152d519adbfSMatthew Knepley                                 /* 64*/ 0,
115397304618SKris Buschelman                                         0,
115497304618SKris Buschelman                                         0,
115597304618SKris Buschelman                                         0,
115697304618SKris Buschelman                                         0,
1157d519adbfSMatthew Knepley                                 /* 69*/ 0,
115897304618SKris Buschelman                                         0,
115997304618SKris Buschelman                                         0,
116097304618SKris Buschelman                                         0,
116197304618SKris Buschelman                                         0,
1162d519adbfSMatthew Knepley                                 /* 74*/ 0,
116397304618SKris Buschelman                                         0,
116497304618SKris Buschelman                                         0,
116597304618SKris Buschelman                                         0,
116697304618SKris Buschelman                                         0,
1167d519adbfSMatthew Knepley                                 /* 79*/ 0,
116897304618SKris Buschelman                                         0,
116997304618SKris Buschelman                                         0,
117097304618SKris Buschelman                                         0,
11715bba2384SShri Abhyankar                                 /* 83*/ MatLoad_MPIDense,
1172865e5f61SKris Buschelman                                         0,
1173865e5f61SKris Buschelman                                         0,
1174865e5f61SKris Buschelman                                         0,
1175865e5f61SKris Buschelman                                         0,
1176865e5f61SKris Buschelman                                         0,
11779775878aSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1178320f2790SHong Zhang                                 /* 89*/ MatMatMult_MPIDense_MPIDense,
1179320f2790SHong Zhang                                         MatMatMultSymbolic_MPIDense_MPIDense,
11809775878aSHong Zhang #else
11819775878aSHong Zhang                                 /* 89*/ 0,
1182865e5f61SKris Buschelman                                         0,
11839775878aSHong Zhang #endif
1184fd4e9aacSBarry Smith                                         MatMatMultNumeric_MPIDense,
11852fbe02b9SBarry Smith                                         0,
1186ba337c44SJed Brown                                         0,
1187d519adbfSMatthew Knepley                                 /* 94*/ 0,
1188865e5f61SKris Buschelman                                         0,
1189865e5f61SKris Buschelman                                         0,
1190ba337c44SJed Brown                                         0,
1191ba337c44SJed Brown                                         0,
1192ba337c44SJed Brown                                 /* 99*/ 0,
1193ba337c44SJed Brown                                         0,
1194ba337c44SJed Brown                                         0,
1195ba337c44SJed Brown                                         MatConjugate_MPIDense,
1196ba337c44SJed Brown                                         0,
1197ba337c44SJed Brown                                 /*104*/ 0,
1198ba337c44SJed Brown                                         MatRealPart_MPIDense,
1199ba337c44SJed Brown                                         MatImaginaryPart_MPIDense,
120086d161a7SShri Abhyankar                                         0,
120186d161a7SShri Abhyankar                                         0,
120286d161a7SShri Abhyankar                                 /*109*/ 0,
120386d161a7SShri Abhyankar                                         0,
120486d161a7SShri Abhyankar                                         0,
120586d161a7SShri Abhyankar                                         0,
12063b49f96aSBarry Smith                                         MatMissingDiagonal_MPIDense,
120786d161a7SShri Abhyankar                                 /*114*/ 0,
120886d161a7SShri Abhyankar                                         0,
120986d161a7SShri Abhyankar                                         0,
121086d161a7SShri Abhyankar                                         0,
121186d161a7SShri Abhyankar                                         0,
121286d161a7SShri Abhyankar                                 /*119*/ 0,
121386d161a7SShri Abhyankar                                         0,
121486d161a7SShri Abhyankar                                         0,
12150716a85fSBarry Smith                                         0,
12160716a85fSBarry Smith                                         0,
12170716a85fSBarry Smith                                 /*124*/ 0,
12183964eb88SJed Brown                                         MatGetColumnNorms_MPIDense,
12193964eb88SJed Brown                                         0,
12203964eb88SJed Brown                                         0,
12213964eb88SJed Brown                                         0,
12223964eb88SJed Brown                                 /*129*/ 0,
1223cb20be35SHong Zhang                                         MatTransposeMatMult_MPIDense_MPIDense,
1224cb20be35SHong Zhang                                         MatTransposeMatMultSymbolic_MPIDense_MPIDense,
1225cb20be35SHong Zhang                                         MatTransposeMatMultNumeric_MPIDense_MPIDense,
12263964eb88SJed Brown                                         0,
12273964eb88SJed Brown                                 /*134*/ 0,
12283964eb88SJed Brown                                         0,
12293964eb88SJed Brown                                         0,
12303964eb88SJed Brown                                         0,
12313964eb88SJed Brown                                         0,
12323964eb88SJed Brown                                 /*139*/ 0,
1233f9426fe0SMark Adams                                         0,
123494e2cb23SJakub Kruzik                                         0,
123594e2cb23SJakub Kruzik                                         0,
123694e2cb23SJakub Kruzik                                         0,
1237*1ae5eee8SJakub Kruzik                                 /*144*/ MatCreateMPIMatConcatenateSeqMat_MPIDense
1238ba337c44SJed Brown };
12398965ea79SLois Curfman McInnes 
12407087cfbeSBarry Smith PetscErrorCode  MatMPIDenseSetPreallocation_MPIDense(Mat mat,PetscScalar *data)
1241a23d5eceSKris Buschelman {
1242a23d5eceSKris Buschelman   Mat_MPIDense   *a;
1243dfbe8321SBarry Smith   PetscErrorCode ierr;
1244a23d5eceSKris Buschelman 
1245a23d5eceSKris Buschelman   PetscFunctionBegin;
1246a23d5eceSKris Buschelman   mat->preallocated = PETSC_TRUE;
1247a23d5eceSKris Buschelman   /* Note:  For now, when data is specified above, this assumes the user correctly
1248a23d5eceSKris Buschelman    allocates the local dense storage space.  We should add error checking. */
1249a23d5eceSKris Buschelman 
1250a23d5eceSKris Buschelman   a       = (Mat_MPIDense*)mat->data;
125134ef9618SShri Abhyankar   ierr    = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
125234ef9618SShri Abhyankar   ierr    = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
125334ef9618SShri Abhyankar   a->nvec = mat->cmap->n;
125434ef9618SShri Abhyankar 
1255f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&a->A);CHKERRQ(ierr);
1256d0f46423SBarry Smith   ierr = MatSetSizes(a->A,mat->rmap->n,mat->cmap->N,mat->rmap->n,mat->cmap->N);CHKERRQ(ierr);
12575c5985e7SKris Buschelman   ierr = MatSetType(a->A,MATSEQDENSE);CHKERRQ(ierr);
12585c5985e7SKris Buschelman   ierr = MatSeqDenseSetPreallocation(a->A,data);CHKERRQ(ierr);
12593bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->A);CHKERRQ(ierr);
1260a23d5eceSKris Buschelman   PetscFunctionReturn(0);
1261a23d5eceSKris Buschelman }
1262a23d5eceSKris Buschelman 
126365b80a83SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1264cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIDense_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
12658baccfbdSHong Zhang {
12668ea901baSHong Zhang   Mat            mat_elemental;
12678ea901baSHong Zhang   PetscErrorCode ierr;
126832d7a744SHong Zhang   PetscScalar    *v;
126932d7a744SHong Zhang   PetscInt       m=A->rmap->n,N=A->cmap->N,rstart=A->rmap->rstart,i,*rows,*cols;
12708ea901baSHong Zhang 
12718baccfbdSHong Zhang   PetscFunctionBegin;
1272378336b6SHong Zhang   if (reuse == MAT_REUSE_MATRIX) {
1273378336b6SHong Zhang     mat_elemental = *newmat;
1274378336b6SHong Zhang     ierr = MatZeroEntries(*newmat);CHKERRQ(ierr);
1275378336b6SHong Zhang   } else {
1276378336b6SHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
1277378336b6SHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
1278378336b6SHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
1279378336b6SHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
128032d7a744SHong Zhang     ierr = MatSetOption(mat_elemental,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1281378336b6SHong Zhang   }
1282378336b6SHong Zhang 
128332d7a744SHong Zhang   ierr = PetscMalloc2(m,&rows,N,&cols);CHKERRQ(ierr);
128432d7a744SHong Zhang   for (i=0; i<N; i++) cols[i] = i;
128532d7a744SHong Zhang   for (i=0; i<m; i++) rows[i] = rstart + i;
12868ea901baSHong Zhang 
12878ea901baSHong Zhang   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
128832d7a744SHong Zhang   ierr = MatDenseGetArray(A,&v);CHKERRQ(ierr);
128932d7a744SHong Zhang   ierr = MatSetValues(mat_elemental,m,rows,N,cols,v,ADD_VALUES);CHKERRQ(ierr);
12908ea901baSHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12918ea901baSHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
129232d7a744SHong Zhang   ierr = MatDenseRestoreArray(A,&v);CHKERRQ(ierr);
129332d7a744SHong Zhang   ierr = PetscFree2(rows,cols);CHKERRQ(ierr);
12948ea901baSHong Zhang 
1295511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
129628be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
12978ea901baSHong Zhang   } else {
12988ea901baSHong Zhang     *newmat = mat_elemental;
12998ea901baSHong Zhang   }
13008baccfbdSHong Zhang   PetscFunctionReturn(0);
13018baccfbdSHong Zhang }
130265b80a83SHong Zhang #endif
13038baccfbdSHong Zhang 
1304af53bab2SHong Zhang static PetscErrorCode MatDenseGetColumn_MPIDense(Mat A,PetscInt col,PetscScalar **vals)
130586aefd0dSHong Zhang {
130686aefd0dSHong Zhang   Mat_MPIDense   *mat = (Mat_MPIDense*)A->data;
130786aefd0dSHong Zhang   PetscErrorCode ierr;
130886aefd0dSHong Zhang 
130986aefd0dSHong Zhang   PetscFunctionBegin;
131086aefd0dSHong Zhang   ierr = MatDenseGetColumn(mat->A,col,vals);CHKERRQ(ierr);
131186aefd0dSHong Zhang   PetscFunctionReturn(0);
131286aefd0dSHong Zhang }
131386aefd0dSHong Zhang 
1314af53bab2SHong Zhang static PetscErrorCode MatDenseRestoreColumn_MPIDense(Mat A,PetscScalar **vals)
131586aefd0dSHong Zhang {
131686aefd0dSHong Zhang   Mat_MPIDense   *mat = (Mat_MPIDense*)A->data;
131786aefd0dSHong Zhang   PetscErrorCode ierr;
131886aefd0dSHong Zhang 
131986aefd0dSHong Zhang   PetscFunctionBegin;
132086aefd0dSHong Zhang   ierr = MatDenseRestoreColumn(mat->A,vals);CHKERRQ(ierr);
132186aefd0dSHong Zhang   PetscFunctionReturn(0);
132286aefd0dSHong Zhang }
132386aefd0dSHong Zhang 
132494e2cb23SJakub Kruzik PetscErrorCode MatCreateMPIMatConcatenateSeqMat_MPIDense(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
132594e2cb23SJakub Kruzik {
132694e2cb23SJakub Kruzik   PetscErrorCode ierr;
132794e2cb23SJakub Kruzik   Mat_MPIDense   *mat;
132894e2cb23SJakub Kruzik   PetscInt       m,nloc,N;
132994e2cb23SJakub Kruzik 
133094e2cb23SJakub Kruzik   PetscFunctionBegin;
133194e2cb23SJakub Kruzik   ierr = MatGetSize(inmat,&m,&N);CHKERRQ(ierr);
133294e2cb23SJakub Kruzik   ierr = MatGetLocalSize(inmat,NULL,&nloc);CHKERRQ(ierr);
133394e2cb23SJakub Kruzik   if (scall == MAT_INITIAL_MATRIX) { /* symbolic phase */
133494e2cb23SJakub Kruzik     PetscInt sum;
133594e2cb23SJakub Kruzik 
133694e2cb23SJakub Kruzik     if (n == PETSC_DECIDE) {
133794e2cb23SJakub Kruzik       ierr = PetscSplitOwnership(comm,&n,&N);CHKERRQ(ierr);
133894e2cb23SJakub Kruzik     }
133994e2cb23SJakub Kruzik     /* Check sum(n) = N */
134094e2cb23SJakub Kruzik     ierr = MPIU_Allreduce(&n,&sum,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
134194e2cb23SJakub Kruzik     if (sum != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Sum of local columns %D != global columns %D",sum,N);
134294e2cb23SJakub Kruzik 
134394e2cb23SJakub Kruzik     ierr = MatCreateDense(comm,m,n,PETSC_DETERMINE,N,NULL,outmat);CHKERRQ(ierr);
134494e2cb23SJakub Kruzik   }
134594e2cb23SJakub Kruzik 
134694e2cb23SJakub Kruzik   /* numeric phase */
134794e2cb23SJakub Kruzik   mat = (Mat_MPIDense*)(*outmat)->data;
134894e2cb23SJakub Kruzik   ierr = MatCopy(inmat,mat->A,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
134994e2cb23SJakub Kruzik   ierr = MatAssemblyBegin(*outmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
135094e2cb23SJakub Kruzik   ierr = MatAssemblyEnd(*outmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
135194e2cb23SJakub Kruzik   PetscFunctionReturn(0);
135294e2cb23SJakub Kruzik }
135394e2cb23SJakub Kruzik 
13548cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_MPIDense(Mat mat)
1355273d9f13SBarry Smith {
1356273d9f13SBarry Smith   Mat_MPIDense   *a;
1357dfbe8321SBarry Smith   PetscErrorCode ierr;
1358273d9f13SBarry Smith 
1359273d9f13SBarry Smith   PetscFunctionBegin;
1360b00a9115SJed Brown   ierr      = PetscNewLog(mat,&a);CHKERRQ(ierr);
1361b0a32e0cSBarry Smith   mat->data = (void*)a;
1362273d9f13SBarry Smith   ierr      = PetscMemcpy(mat->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1363273d9f13SBarry Smith 
1364273d9f13SBarry Smith   mat->insertmode = NOT_SET_VALUES;
1365ce94432eSBarry Smith   ierr            = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&a->rank);CHKERRQ(ierr);
1366ce94432eSBarry Smith   ierr            = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&a->size);CHKERRQ(ierr);
1367273d9f13SBarry Smith 
1368273d9f13SBarry Smith   /* build cache for off array entries formed */
1369273d9f13SBarry Smith   a->donotstash = PETSC_FALSE;
13702205254eSKarl Rupp 
1371ce94432eSBarry Smith   ierr = MatStashCreate_Private(PetscObjectComm((PetscObject)mat),1,&mat->stash);CHKERRQ(ierr);
1372273d9f13SBarry Smith 
1373273d9f13SBarry Smith   /* stuff used for matrix vector multiply */
1374273d9f13SBarry Smith   a->lvec        = 0;
1375273d9f13SBarry Smith   a->Mvctx       = 0;
1376273d9f13SBarry Smith   a->roworiented = PETSC_TRUE;
1377273d9f13SBarry Smith 
1378bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetArray_C",MatDenseGetArray_MPIDense);CHKERRQ(ierr);
13798572280aSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreArray_C",MatDenseRestoreArray_MPIDense);CHKERRQ(ierr);
13808572280aSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetArrayRead_C",MatDenseGetArrayRead_MPIDense);CHKERRQ(ierr);
13818572280aSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreArrayRead_C",MatDenseRestoreArrayRead_MPIDense);CHKERRQ(ierr);
1382d3042a70SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDensePlaceArray_C",MatDensePlaceArray_MPIDense);CHKERRQ(ierr);
1383d3042a70SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseResetArray_C",MatDenseResetArray_MPIDense);CHKERRQ(ierr);
13848baccfbdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
13858baccfbdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpidense_elemental_C",MatConvert_MPIDense_Elemental);CHKERRQ(ierr);
13868baccfbdSHong Zhang #endif
1387bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIDenseSetPreallocation_C",MatMPIDenseSetPreallocation_MPIDense);CHKERRQ(ierr);
1388bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMult_mpiaij_mpidense_C",MatMatMult_MPIAIJ_MPIDense);CHKERRQ(ierr);
1389bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMultSymbolic_mpiaij_mpidense_C",MatMatMultSymbolic_MPIAIJ_MPIDense);CHKERRQ(ierr);
1390bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMultNumeric_mpiaij_mpidense_C",MatMatMultNumeric_MPIAIJ_MPIDense);CHKERRQ(ierr);
13918949adfdSHong Zhang 
13928949adfdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMult_mpiaij_mpidense_C",MatTransposeMatMult_MPIAIJ_MPIDense);CHKERRQ(ierr);
13938949adfdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultSymbolic_mpiaij_mpidense_C",MatTransposeMatMultSymbolic_MPIAIJ_MPIDense);CHKERRQ(ierr);
13948949adfdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultNumeric_mpiaij_mpidense_C",MatTransposeMatMultNumeric_MPIAIJ_MPIDense);CHKERRQ(ierr);
1395af53bab2SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetColumn_C",MatDenseGetColumn_MPIDense);CHKERRQ(ierr);
1396af53bab2SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreColumn_C",MatDenseRestoreColumn_MPIDense);CHKERRQ(ierr);
139738aed534SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)mat,MATMPIDENSE);CHKERRQ(ierr);
1398273d9f13SBarry Smith   PetscFunctionReturn(0);
1399273d9f13SBarry Smith }
1400273d9f13SBarry Smith 
1401209238afSKris Buschelman /*MC
1402002d173eSKris Buschelman    MATDENSE - MATDENSE = "dense" - A matrix type to be used for dense matrices.
1403209238afSKris Buschelman 
1404209238afSKris Buschelman    This matrix type is identical to MATSEQDENSE when constructed with a single process communicator,
1405209238afSKris Buschelman    and MATMPIDENSE otherwise.
1406209238afSKris Buschelman 
1407209238afSKris Buschelman    Options Database Keys:
1408209238afSKris Buschelman . -mat_type dense - sets the matrix type to "dense" during a call to MatSetFromOptions()
1409209238afSKris Buschelman 
1410209238afSKris Buschelman   Level: beginner
1411209238afSKris Buschelman 
141201b82886SBarry Smith 
1413209238afSKris Buschelman .seealso: MatCreateMPIDense,MATSEQDENSE,MATMPIDENSE
1414209238afSKris Buschelman M*/
1415209238afSKris Buschelman 
1416273d9f13SBarry Smith /*@C
1417273d9f13SBarry Smith    MatMPIDenseSetPreallocation - Sets the array used to store the matrix entries
1418273d9f13SBarry Smith 
1419273d9f13SBarry Smith    Not collective
1420273d9f13SBarry Smith 
1421273d9f13SBarry Smith    Input Parameters:
14221c4f3114SJed Brown .  B - the matrix
14230298fd71SBarry Smith -  data - optional location of matrix data.  Set data=NULL for PETSc
1424273d9f13SBarry Smith    to control all matrix memory allocation.
1425273d9f13SBarry Smith 
1426273d9f13SBarry Smith    Notes:
1427273d9f13SBarry Smith    The dense format is fully compatible with standard Fortran 77
1428273d9f13SBarry Smith    storage by columns.
1429273d9f13SBarry Smith 
1430273d9f13SBarry Smith    The data input variable is intended primarily for Fortran programmers
1431273d9f13SBarry Smith    who wish to allocate their own matrix memory space.  Most users should
14320298fd71SBarry Smith    set data=NULL.
1433273d9f13SBarry Smith 
1434273d9f13SBarry Smith    Level: intermediate
1435273d9f13SBarry Smith 
1436273d9f13SBarry Smith .keywords: matrix,dense, parallel
1437273d9f13SBarry Smith 
1438273d9f13SBarry Smith .seealso: MatCreate(), MatCreateSeqDense(), MatSetValues()
1439273d9f13SBarry Smith @*/
14401c4f3114SJed Brown PetscErrorCode  MatMPIDenseSetPreallocation(Mat B,PetscScalar *data)
1441273d9f13SBarry Smith {
14424ac538c5SBarry Smith   PetscErrorCode ierr;
1443273d9f13SBarry Smith 
1444273d9f13SBarry Smith   PetscFunctionBegin;
14451c4f3114SJed Brown   ierr = PetscTryMethod(B,"MatMPIDenseSetPreallocation_C",(Mat,PetscScalar*),(B,data));CHKERRQ(ierr);
1446273d9f13SBarry Smith   PetscFunctionReturn(0);
1447273d9f13SBarry Smith }
1448273d9f13SBarry Smith 
1449d3042a70SBarry Smith /*@
1450d3042a70SBarry Smith    MatDensePlaceArray - Allows one to replace the array in a dense array with an
1451d3042a70SBarry Smith    array provided by the user. This is useful to avoid copying an array
1452d3042a70SBarry Smith    into a matrix
1453d3042a70SBarry Smith 
1454d3042a70SBarry Smith    Not Collective
1455d3042a70SBarry Smith 
1456d3042a70SBarry Smith    Input Parameters:
1457d3042a70SBarry Smith +  mat - the matrix
1458d3042a70SBarry Smith -  array - the array in column major order
1459d3042a70SBarry Smith 
1460d3042a70SBarry Smith    Notes:
1461d3042a70SBarry Smith    You can return to the original array with a call to MatDenseResetArray(). The user is responsible for freeing this array; it will not be
1462d3042a70SBarry Smith    freed when the matrix is destroyed.
1463d3042a70SBarry Smith 
1464d3042a70SBarry Smith    Level: developer
1465d3042a70SBarry Smith 
1466d3042a70SBarry Smith .seealso: MatDenseGetArray(), MatDenseResetArray(), VecPlaceArray(), VecGetArray(), VecRestoreArray(), VecReplaceArray(), VecResetArray()
1467d3042a70SBarry Smith 
1468d3042a70SBarry Smith @*/
1469d3042a70SBarry Smith PetscErrorCode  MatDensePlaceArray(Mat mat,const PetscScalar array[])
1470d3042a70SBarry Smith {
1471d3042a70SBarry Smith   PetscErrorCode ierr;
1472d3042a70SBarry Smith   PetscFunctionBegin;
1473d3042a70SBarry Smith   ierr = PetscUseMethod(mat,"MatDensePlaceArray_C",(Mat,const PetscScalar*),(mat,array));CHKERRQ(ierr);
1474d3042a70SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
1475d3042a70SBarry Smith   PetscFunctionReturn(0);
1476d3042a70SBarry Smith }
1477d3042a70SBarry Smith 
1478d3042a70SBarry Smith /*@
1479d3042a70SBarry Smith    MatDenseResetArray - Resets the matrix array to that it previously had before the call to MatDensePlaceArray()
1480d3042a70SBarry Smith 
1481d3042a70SBarry Smith    Not Collective
1482d3042a70SBarry Smith 
1483d3042a70SBarry Smith    Input Parameters:
1484d3042a70SBarry Smith .  mat - the matrix
1485d3042a70SBarry Smith 
1486d3042a70SBarry Smith    Notes:
1487d3042a70SBarry Smith    You can only call this after a call to MatDensePlaceArray()
1488d3042a70SBarry Smith 
1489d3042a70SBarry Smith    Level: developer
1490d3042a70SBarry Smith 
1491d3042a70SBarry Smith .seealso: MatDenseGetArray(), MatDensePlaceArray(), VecPlaceArray(), VecGetArray(), VecRestoreArray(), VecReplaceArray(), VecResetArray()
1492d3042a70SBarry Smith 
1493d3042a70SBarry Smith @*/
1494d3042a70SBarry Smith PetscErrorCode  MatDenseResetArray(Mat mat)
1495d3042a70SBarry Smith {
1496d3042a70SBarry Smith   PetscErrorCode ierr;
1497d3042a70SBarry Smith   PetscFunctionBegin;
1498d3042a70SBarry Smith   ierr = PetscUseMethod(mat,"MatDenseResetArray_C",(Mat),(mat));CHKERRQ(ierr);
1499d3042a70SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
1500d3042a70SBarry Smith   PetscFunctionReturn(0);
1501d3042a70SBarry Smith }
1502d3042a70SBarry Smith 
15038965ea79SLois Curfman McInnes /*@C
150469b1f4b7SBarry Smith    MatCreateDense - Creates a parallel matrix in dense format.
15058965ea79SLois Curfman McInnes 
1506db81eaa0SLois Curfman McInnes    Collective on MPI_Comm
1507db81eaa0SLois Curfman McInnes 
15088965ea79SLois Curfman McInnes    Input Parameters:
1509db81eaa0SLois Curfman McInnes +  comm - MPI communicator
15108965ea79SLois Curfman McInnes .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
1511db81eaa0SLois Curfman McInnes .  n - number of local columns (or PETSC_DECIDE to have calculated if N is given)
15128965ea79SLois Curfman McInnes .  M - number of global rows (or PETSC_DECIDE to have calculated if m is given)
1513db81eaa0SLois Curfman McInnes .  N - number of global columns (or PETSC_DECIDE to have calculated if n is given)
15146cfe35ddSJose E. Roman -  data - optional location of matrix data.  Set data=NULL (PETSC_NULL_SCALAR for Fortran users) for PETSc
1515dfc5480cSLois Curfman McInnes    to control all matrix memory allocation.
15168965ea79SLois Curfman McInnes 
15178965ea79SLois Curfman McInnes    Output Parameter:
1518477f1c0bSLois Curfman McInnes .  A - the matrix
15198965ea79SLois Curfman McInnes 
1520b259b22eSLois Curfman McInnes    Notes:
152139ddd567SLois Curfman McInnes    The dense format is fully compatible with standard Fortran 77
152239ddd567SLois Curfman McInnes    storage by columns.
15238965ea79SLois Curfman McInnes 
152418f449edSLois Curfman McInnes    The data input variable is intended primarily for Fortran programmers
152518f449edSLois Curfman McInnes    who wish to allocate their own matrix memory space.  Most users should
15266cfe35ddSJose E. Roman    set data=NULL (PETSC_NULL_SCALAR for Fortran users).
152718f449edSLois Curfman McInnes 
15288965ea79SLois Curfman McInnes    The user MUST specify either the local or global matrix dimensions
15298965ea79SLois Curfman McInnes    (possibly both).
15308965ea79SLois Curfman McInnes 
1531027ccd11SLois Curfman McInnes    Level: intermediate
1532027ccd11SLois Curfman McInnes 
153339ddd567SLois Curfman McInnes .keywords: matrix,dense, parallel
15348965ea79SLois Curfman McInnes 
153539ddd567SLois Curfman McInnes .seealso: MatCreate(), MatCreateSeqDense(), MatSetValues()
15368965ea79SLois Curfman McInnes @*/
153769b1f4b7SBarry Smith PetscErrorCode  MatCreateDense(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscScalar *data,Mat *A)
15388965ea79SLois Curfman McInnes {
15396849ba73SBarry Smith   PetscErrorCode ierr;
154013f74950SBarry Smith   PetscMPIInt    size;
15418965ea79SLois Curfman McInnes 
15423a40ed3dSBarry Smith   PetscFunctionBegin;
1543f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1544f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
1545273d9f13SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1546273d9f13SBarry Smith   if (size > 1) {
1547273d9f13SBarry Smith     ierr = MatSetType(*A,MATMPIDENSE);CHKERRQ(ierr);
1548273d9f13SBarry Smith     ierr = MatMPIDenseSetPreallocation(*A,data);CHKERRQ(ierr);
15496cfe35ddSJose E. Roman     if (data) {  /* user provided data array, so no need to assemble */
15506cfe35ddSJose E. Roman       ierr = MatSetUpMultiply_MPIDense(*A);CHKERRQ(ierr);
15516cfe35ddSJose E. Roman       (*A)->assembled = PETSC_TRUE;
15526cfe35ddSJose E. Roman     }
1553273d9f13SBarry Smith   } else {
1554273d9f13SBarry Smith     ierr = MatSetType(*A,MATSEQDENSE);CHKERRQ(ierr);
1555273d9f13SBarry Smith     ierr = MatSeqDenseSetPreallocation(*A,data);CHKERRQ(ierr);
15568c469469SLois Curfman McInnes   }
15573a40ed3dSBarry Smith   PetscFunctionReturn(0);
15588965ea79SLois Curfman McInnes }
15598965ea79SLois Curfman McInnes 
15606849ba73SBarry Smith static PetscErrorCode MatDuplicate_MPIDense(Mat A,MatDuplicateOption cpvalues,Mat *newmat)
15618965ea79SLois Curfman McInnes {
15628965ea79SLois Curfman McInnes   Mat            mat;
15633501a2bdSLois Curfman McInnes   Mat_MPIDense   *a,*oldmat = (Mat_MPIDense*)A->data;
1564dfbe8321SBarry Smith   PetscErrorCode ierr;
15658965ea79SLois Curfman McInnes 
15663a40ed3dSBarry Smith   PetscFunctionBegin;
15678965ea79SLois Curfman McInnes   *newmat = 0;
1568ce94432eSBarry Smith   ierr    = MatCreate(PetscObjectComm((PetscObject)A),&mat);CHKERRQ(ierr);
1569d0f46423SBarry Smith   ierr    = MatSetSizes(mat,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
15707adad957SLisandro Dalcin   ierr    = MatSetType(mat,((PetscObject)A)->type_name);CHKERRQ(ierr);
1571834f8fabSBarry Smith   a       = (Mat_MPIDense*)mat->data;
1572e04c1aa4SHong Zhang   ierr    = PetscMemcpy(mat->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
15735aa7edbeSHong Zhang 
1574d5f3da31SBarry Smith   mat->factortype   = A->factortype;
1575c456f294SBarry Smith   mat->assembled    = PETSC_TRUE;
1576273d9f13SBarry Smith   mat->preallocated = PETSC_TRUE;
15778965ea79SLois Curfman McInnes 
15788965ea79SLois Curfman McInnes   a->size         = oldmat->size;
15798965ea79SLois Curfman McInnes   a->rank         = oldmat->rank;
1580e0fa3b82SLois Curfman McInnes   mat->insertmode = NOT_SET_VALUES;
1581b9b97703SBarry Smith   a->nvec         = oldmat->nvec;
15823782ba37SSatish Balay   a->donotstash   = oldmat->donotstash;
1583e04c1aa4SHong Zhang 
15841e1e43feSBarry Smith   ierr = PetscLayoutReference(A->rmap,&mat->rmap);CHKERRQ(ierr);
15851e1e43feSBarry Smith   ierr = PetscLayoutReference(A->cmap,&mat->cmap);CHKERRQ(ierr);
15868965ea79SLois Curfman McInnes 
1587329f5518SBarry Smith   ierr = MatSetUpMultiply_MPIDense(mat);CHKERRQ(ierr);
15885609ef8eSBarry Smith   ierr = MatDuplicate(oldmat->A,cpvalues,&a->A);CHKERRQ(ierr);
15893bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->A);CHKERRQ(ierr);
159001b82886SBarry Smith 
15918965ea79SLois Curfman McInnes   *newmat = mat;
15923a40ed3dSBarry Smith   PetscFunctionReturn(0);
15938965ea79SLois Curfman McInnes }
15948965ea79SLois Curfman McInnes 
15959d36ed5fSBarry Smith PetscErrorCode MatLoad_MPIDense_DenseInFile(MPI_Comm comm,PetscInt fd,PetscInt M,PetscInt N,Mat newmat)
159686d161a7SShri Abhyankar {
159786d161a7SShri Abhyankar   PetscErrorCode ierr;
159886d161a7SShri Abhyankar   PetscMPIInt    rank,size;
159974c13d95SBarry Smith   const PetscInt *rowners;
160074c13d95SBarry Smith   PetscInt       i,m,n,nz,j,mMax;
160186d161a7SShri Abhyankar   PetscScalar    *array,*vals,*vals_ptr;
16029d36ed5fSBarry Smith   Mat_MPIDense   *a = (Mat_MPIDense*)newmat->data;
160386d161a7SShri Abhyankar 
160486d161a7SShri Abhyankar   PetscFunctionBegin;
160586d161a7SShri Abhyankar   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
160686d161a7SShri Abhyankar   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
160786d161a7SShri Abhyankar 
160874c13d95SBarry Smith   /* determine ownership of rows and columns */
160974c13d95SBarry Smith   m = (newmat->rmap->n < 0) ? PETSC_DECIDE : newmat->rmap->n;
161074c13d95SBarry Smith   n = (newmat->cmap->n < 0) ? PETSC_DECIDE : newmat->cmap->n;
161186d161a7SShri Abhyankar 
161274c13d95SBarry Smith   ierr = MatSetSizes(newmat,m,n,M,N);CHKERRQ(ierr);
16139d36ed5fSBarry Smith   if (!a->A || !((Mat_SeqDense*)(a->A->data))->user_alloc) {
16140298fd71SBarry Smith     ierr = MatMPIDenseSetPreallocation(newmat,NULL);CHKERRQ(ierr);
16159d36ed5fSBarry Smith   }
16168c778c55SBarry Smith   ierr = MatDenseGetArray(newmat,&array);CHKERRQ(ierr);
161749467e7dSBarry Smith   ierr = MatGetLocalSize(newmat,&m,NULL);CHKERRQ(ierr);
161874c13d95SBarry Smith   ierr = MatGetOwnershipRanges(newmat,&rowners);CHKERRQ(ierr);
1619396e826eSBarry Smith   ierr = MPI_Reduce(&m,&mMax,1,MPIU_INT,MPI_MAX,0,comm);CHKERRQ(ierr);
162086d161a7SShri Abhyankar   if (!rank) {
16219d36ed5fSBarry Smith     ierr = PetscMalloc1(mMax*N,&vals);CHKERRQ(ierr);
162286d161a7SShri Abhyankar 
162386d161a7SShri Abhyankar     /* read in my part of the matrix numerical values  */
162486d161a7SShri Abhyankar     ierr = PetscBinaryRead(fd,vals,m*N,PETSC_SCALAR);CHKERRQ(ierr);
162586d161a7SShri Abhyankar 
162686d161a7SShri Abhyankar     /* insert into matrix-by row (this is why cannot directly read into array */
162786d161a7SShri Abhyankar     vals_ptr = vals;
162886d161a7SShri Abhyankar     for (i=0; i<m; i++) {
162986d161a7SShri Abhyankar       for (j=0; j<N; j++) {
163086d161a7SShri Abhyankar         array[i + j*m] = *vals_ptr++;
163186d161a7SShri Abhyankar       }
163286d161a7SShri Abhyankar     }
163386d161a7SShri Abhyankar 
163486d161a7SShri Abhyankar     /* read in other processors and ship out */
163586d161a7SShri Abhyankar     for (i=1; i<size; i++) {
163686d161a7SShri Abhyankar       nz   = (rowners[i+1] - rowners[i])*N;
163786d161a7SShri Abhyankar       ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr);
1638a25532f0SBarry Smith       ierr = MPIULong_Send(vals,nz,MPIU_SCALAR,i,((PetscObject)(newmat))->tag,comm);CHKERRQ(ierr);
163986d161a7SShri Abhyankar     }
164086d161a7SShri Abhyankar   } else {
164186d161a7SShri Abhyankar     /* receive numeric values */
1642785e854fSJed Brown     ierr = PetscMalloc1(m*N,&vals);CHKERRQ(ierr);
164386d161a7SShri Abhyankar 
164486d161a7SShri Abhyankar     /* receive message of values*/
1645a25532f0SBarry Smith     ierr = MPIULong_Recv(vals,m*N,MPIU_SCALAR,0,((PetscObject)(newmat))->tag,comm);CHKERRQ(ierr);
164686d161a7SShri Abhyankar 
164786d161a7SShri Abhyankar     /* insert into matrix-by row (this is why cannot directly read into array */
164886d161a7SShri Abhyankar     vals_ptr = vals;
164986d161a7SShri Abhyankar     for (i=0; i<m; i++) {
165086d161a7SShri Abhyankar       for (j=0; j<N; j++) {
165186d161a7SShri Abhyankar         array[i + j*m] = *vals_ptr++;
165286d161a7SShri Abhyankar       }
165386d161a7SShri Abhyankar     }
165486d161a7SShri Abhyankar   }
16558c778c55SBarry Smith   ierr = MatDenseRestoreArray(newmat,&array);CHKERRQ(ierr);
165686d161a7SShri Abhyankar   ierr = PetscFree(vals);CHKERRQ(ierr);
165786d161a7SShri Abhyankar   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
165886d161a7SShri Abhyankar   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
165986d161a7SShri Abhyankar   PetscFunctionReturn(0);
166086d161a7SShri Abhyankar }
166186d161a7SShri Abhyankar 
1662112444f4SShri Abhyankar PetscErrorCode MatLoad_MPIDense(Mat newmat,PetscViewer viewer)
166386d161a7SShri Abhyankar {
1664dfdea288SBarry Smith   Mat_MPIDense   *a;
166586d161a7SShri Abhyankar   PetscScalar    *vals,*svals;
1666ce94432eSBarry Smith   MPI_Comm       comm;
166786d161a7SShri Abhyankar   MPI_Status     status;
166849467e7dSBarry Smith   PetscMPIInt    rank,size,tag = ((PetscObject)viewer)->tag,*rowners,*sndcounts,m,n,maxnz;
166986d161a7SShri Abhyankar   PetscInt       header[4],*rowlengths = 0,M,N,*cols;
167049467e7dSBarry Smith   PetscInt       *ourlens,*procsnz = 0,jj,*mycols,*smycols;
16719d36ed5fSBarry Smith   PetscInt       i,nz,j,rstart,rend;
167286d161a7SShri Abhyankar   int            fd;
167386d161a7SShri Abhyankar   PetscErrorCode ierr;
167486d161a7SShri Abhyankar 
167586d161a7SShri Abhyankar   PetscFunctionBegin;
1676c98fd787SBarry Smith   /* force binary viewer to load .info file if it has not yet done so */
1677c98fd787SBarry Smith   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1678ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
167986d161a7SShri Abhyankar   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
168086d161a7SShri Abhyankar   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
168186d161a7SShri Abhyankar   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
16825872f025SBarry Smith   if (!rank) {
168386d161a7SShri Abhyankar     ierr = PetscBinaryRead(fd,(char*)header,4,PETSC_INT);CHKERRQ(ierr);
168486d161a7SShri Abhyankar     if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object");
168586d161a7SShri Abhyankar   }
168686d161a7SShri Abhyankar   ierr = MPI_Bcast(header+1,3,MPIU_INT,0,comm);CHKERRQ(ierr);
168786d161a7SShri Abhyankar   M    = header[1]; N = header[2]; nz = header[3];
168886d161a7SShri Abhyankar 
168986d161a7SShri Abhyankar   /* If global rows/cols are set to PETSC_DECIDE, set it to the sizes given in the file */
16909d36ed5fSBarry Smith   if (newmat->rmap->N < 0) newmat->rmap->N = M;
16919d36ed5fSBarry Smith   if (newmat->cmap->N < 0) newmat->cmap->N = N;
169286d161a7SShri Abhyankar 
16939d36ed5fSBarry Smith   if (newmat->rmap->N != M) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Inconsistent # of rows:Matrix in file has (%D) and input matrix has (%D)",M,newmat->rmap->N);
16949d36ed5fSBarry Smith   if (newmat->cmap->N != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Inconsistent # of cols:Matrix in file has (%D) and input matrix has (%D)",N,newmat->cmap->N);
169586d161a7SShri Abhyankar 
169686d161a7SShri Abhyankar   /*
169786d161a7SShri Abhyankar        Handle case where matrix is stored on disk as a dense matrix
169886d161a7SShri Abhyankar   */
169986d161a7SShri Abhyankar   if (nz == MATRIX_BINARY_FORMAT_DENSE) {
17009d36ed5fSBarry Smith     ierr = MatLoad_MPIDense_DenseInFile(comm,fd,M,N,newmat);CHKERRQ(ierr);
170186d161a7SShri Abhyankar     PetscFunctionReturn(0);
170286d161a7SShri Abhyankar   }
170386d161a7SShri Abhyankar 
170486d161a7SShri Abhyankar   /* determine ownership of all rows */
17052205254eSKarl Rupp   if (newmat->rmap->n < 0) {
17062205254eSKarl Rupp     ierr = PetscMPIIntCast(M/size + ((M % size) > rank),&m);CHKERRQ(ierr);
17072205254eSKarl Rupp   } else {
17082205254eSKarl Rupp     ierr = PetscMPIIntCast(newmat->rmap->n,&m);CHKERRQ(ierr);
17092205254eSKarl Rupp   }
171049467e7dSBarry Smith   if (newmat->cmap->n < 0) {
171149467e7dSBarry Smith     n = PETSC_DECIDE;
171249467e7dSBarry Smith   } else {
171349467e7dSBarry Smith     ierr = PetscMPIIntCast(newmat->cmap->n,&n);CHKERRQ(ierr);
171449467e7dSBarry Smith   }
171549467e7dSBarry Smith 
1716854ce69bSBarry Smith   ierr       = PetscMalloc1(size+2,&rowners);CHKERRQ(ierr);
171786d161a7SShri Abhyankar   ierr       = MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
171886d161a7SShri Abhyankar   rowners[0] = 0;
171986d161a7SShri Abhyankar   for (i=2; i<=size; i++) {
172086d161a7SShri Abhyankar     rowners[i] += rowners[i-1];
172186d161a7SShri Abhyankar   }
172286d161a7SShri Abhyankar   rstart = rowners[rank];
172386d161a7SShri Abhyankar   rend   = rowners[rank+1];
172486d161a7SShri Abhyankar 
172586d161a7SShri Abhyankar   /* distribute row lengths to all processors */
172649467e7dSBarry Smith   ierr = PetscMalloc1(rend-rstart,&ourlens);CHKERRQ(ierr);
172786d161a7SShri Abhyankar   if (!rank) {
1728785e854fSJed Brown     ierr = PetscMalloc1(M,&rowlengths);CHKERRQ(ierr);
172986d161a7SShri Abhyankar     ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
1730785e854fSJed Brown     ierr = PetscMalloc1(size,&sndcounts);CHKERRQ(ierr);
173186d161a7SShri Abhyankar     for (i=0; i<size; i++) sndcounts[i] = rowners[i+1] - rowners[i];
173286d161a7SShri Abhyankar     ierr = MPI_Scatterv(rowlengths,sndcounts,rowners,MPIU_INT,ourlens,rend-rstart,MPIU_INT,0,comm);CHKERRQ(ierr);
173386d161a7SShri Abhyankar     ierr = PetscFree(sndcounts);CHKERRQ(ierr);
173486d161a7SShri Abhyankar   } else {
173586d161a7SShri Abhyankar     ierr = MPI_Scatterv(0,0,0,MPIU_INT,ourlens,rend-rstart,MPIU_INT,0,comm);CHKERRQ(ierr);
173686d161a7SShri Abhyankar   }
173786d161a7SShri Abhyankar 
173886d161a7SShri Abhyankar   if (!rank) {
173986d161a7SShri Abhyankar     /* calculate the number of nonzeros on each processor */
1740785e854fSJed Brown     ierr = PetscMalloc1(size,&procsnz);CHKERRQ(ierr);
174186d161a7SShri Abhyankar     ierr = PetscMemzero(procsnz,size*sizeof(PetscInt));CHKERRQ(ierr);
174286d161a7SShri Abhyankar     for (i=0; i<size; i++) {
174386d161a7SShri Abhyankar       for (j=rowners[i]; j< rowners[i+1]; j++) {
174486d161a7SShri Abhyankar         procsnz[i] += rowlengths[j];
174586d161a7SShri Abhyankar       }
174686d161a7SShri Abhyankar     }
174786d161a7SShri Abhyankar     ierr = PetscFree(rowlengths);CHKERRQ(ierr);
174886d161a7SShri Abhyankar 
174986d161a7SShri Abhyankar     /* determine max buffer needed and allocate it */
175086d161a7SShri Abhyankar     maxnz = 0;
175186d161a7SShri Abhyankar     for (i=0; i<size; i++) {
175286d161a7SShri Abhyankar       maxnz = PetscMax(maxnz,procsnz[i]);
175386d161a7SShri Abhyankar     }
1754785e854fSJed Brown     ierr = PetscMalloc1(maxnz,&cols);CHKERRQ(ierr);
175586d161a7SShri Abhyankar 
175686d161a7SShri Abhyankar     /* read in my part of the matrix column indices  */
175786d161a7SShri Abhyankar     nz   = procsnz[0];
1758785e854fSJed Brown     ierr = PetscMalloc1(nz,&mycols);CHKERRQ(ierr);
175986d161a7SShri Abhyankar     ierr = PetscBinaryRead(fd,mycols,nz,PETSC_INT);CHKERRQ(ierr);
176086d161a7SShri Abhyankar 
176186d161a7SShri Abhyankar     /* read in every one elses and ship off */
176286d161a7SShri Abhyankar     for (i=1; i<size; i++) {
176386d161a7SShri Abhyankar       nz   = procsnz[i];
176486d161a7SShri Abhyankar       ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT);CHKERRQ(ierr);
176586d161a7SShri Abhyankar       ierr = MPI_Send(cols,nz,MPIU_INT,i,tag,comm);CHKERRQ(ierr);
176686d161a7SShri Abhyankar     }
176786d161a7SShri Abhyankar     ierr = PetscFree(cols);CHKERRQ(ierr);
176886d161a7SShri Abhyankar   } else {
176986d161a7SShri Abhyankar     /* determine buffer space needed for message */
177086d161a7SShri Abhyankar     nz = 0;
177186d161a7SShri Abhyankar     for (i=0; i<m; i++) {
177286d161a7SShri Abhyankar       nz += ourlens[i];
177386d161a7SShri Abhyankar     }
1774854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&mycols);CHKERRQ(ierr);
177586d161a7SShri Abhyankar 
177686d161a7SShri Abhyankar     /* receive message of column indices*/
177786d161a7SShri Abhyankar     ierr = MPI_Recv(mycols,nz,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr);
177886d161a7SShri Abhyankar     ierr = MPI_Get_count(&status,MPIU_INT,&maxnz);CHKERRQ(ierr);
177986d161a7SShri Abhyankar     if (maxnz != nz) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"something is wrong with file");
178086d161a7SShri Abhyankar   }
178186d161a7SShri Abhyankar 
178249467e7dSBarry Smith   ierr = MatSetSizes(newmat,m,n,M,N);CHKERRQ(ierr);
1783dfdea288SBarry Smith   a = (Mat_MPIDense*)newmat->data;
17842e3566b0SBarry Smith   if (!a->A || !((Mat_SeqDense*)(a->A->data))->user_alloc) {
17850298fd71SBarry Smith     ierr = MatMPIDenseSetPreallocation(newmat,NULL);CHKERRQ(ierr);
1786dfdea288SBarry Smith   }
178786d161a7SShri Abhyankar 
178886d161a7SShri Abhyankar   if (!rank) {
1789785e854fSJed Brown     ierr = PetscMalloc1(maxnz,&vals);CHKERRQ(ierr);
179086d161a7SShri Abhyankar 
179186d161a7SShri Abhyankar     /* read in my part of the matrix numerical values  */
179286d161a7SShri Abhyankar     nz   = procsnz[0];
179386d161a7SShri Abhyankar     ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr);
179486d161a7SShri Abhyankar 
179586d161a7SShri Abhyankar     /* insert into matrix */
179686d161a7SShri Abhyankar     jj      = rstart;
179786d161a7SShri Abhyankar     smycols = mycols;
179886d161a7SShri Abhyankar     svals   = vals;
179986d161a7SShri Abhyankar     for (i=0; i<m; i++) {
180086d161a7SShri Abhyankar       ierr     = MatSetValues(newmat,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
180186d161a7SShri Abhyankar       smycols += ourlens[i];
180286d161a7SShri Abhyankar       svals   += ourlens[i];
180386d161a7SShri Abhyankar       jj++;
180486d161a7SShri Abhyankar     }
180586d161a7SShri Abhyankar 
180686d161a7SShri Abhyankar     /* read in other processors and ship out */
180786d161a7SShri Abhyankar     for (i=1; i<size; i++) {
180886d161a7SShri Abhyankar       nz   = procsnz[i];
180986d161a7SShri Abhyankar       ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr);
181086d161a7SShri Abhyankar       ierr = MPI_Send(vals,nz,MPIU_SCALAR,i,((PetscObject)newmat)->tag,comm);CHKERRQ(ierr);
181186d161a7SShri Abhyankar     }
181286d161a7SShri Abhyankar     ierr = PetscFree(procsnz);CHKERRQ(ierr);
181386d161a7SShri Abhyankar   } else {
181486d161a7SShri Abhyankar     /* receive numeric values */
1815854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&vals);CHKERRQ(ierr);
181686d161a7SShri Abhyankar 
181786d161a7SShri Abhyankar     /* receive message of values*/
181886d161a7SShri Abhyankar     ierr = MPI_Recv(vals,nz,MPIU_SCALAR,0,((PetscObject)newmat)->tag,comm,&status);CHKERRQ(ierr);
181986d161a7SShri Abhyankar     ierr = MPI_Get_count(&status,MPIU_SCALAR,&maxnz);CHKERRQ(ierr);
182086d161a7SShri Abhyankar     if (maxnz != nz) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"something is wrong with file");
182186d161a7SShri Abhyankar 
182286d161a7SShri Abhyankar     /* insert into matrix */
182386d161a7SShri Abhyankar     jj      = rstart;
182486d161a7SShri Abhyankar     smycols = mycols;
182586d161a7SShri Abhyankar     svals   = vals;
182686d161a7SShri Abhyankar     for (i=0; i<m; i++) {
182786d161a7SShri Abhyankar       ierr     = MatSetValues(newmat,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
182886d161a7SShri Abhyankar       smycols += ourlens[i];
182986d161a7SShri Abhyankar       svals   += ourlens[i];
183086d161a7SShri Abhyankar       jj++;
183186d161a7SShri Abhyankar     }
183286d161a7SShri Abhyankar   }
183349467e7dSBarry Smith   ierr = PetscFree(ourlens);CHKERRQ(ierr);
183486d161a7SShri Abhyankar   ierr = PetscFree(vals);CHKERRQ(ierr);
183586d161a7SShri Abhyankar   ierr = PetscFree(mycols);CHKERRQ(ierr);
183686d161a7SShri Abhyankar   ierr = PetscFree(rowners);CHKERRQ(ierr);
183786d161a7SShri Abhyankar 
183886d161a7SShri Abhyankar   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
183986d161a7SShri Abhyankar   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
184086d161a7SShri Abhyankar   PetscFunctionReturn(0);
184186d161a7SShri Abhyankar }
184286d161a7SShri Abhyankar 
1843ace3abfcSBarry Smith PetscErrorCode MatEqual_MPIDense(Mat A,Mat B,PetscBool  *flag)
18446e4ee0c6SHong Zhang {
18456e4ee0c6SHong Zhang   Mat_MPIDense   *matB = (Mat_MPIDense*)B->data,*matA = (Mat_MPIDense*)A->data;
18466e4ee0c6SHong Zhang   Mat            a,b;
1847ace3abfcSBarry Smith   PetscBool      flg;
18486e4ee0c6SHong Zhang   PetscErrorCode ierr;
184990ace30eSBarry Smith 
18506e4ee0c6SHong Zhang   PetscFunctionBegin;
18516e4ee0c6SHong Zhang   a    = matA->A;
18526e4ee0c6SHong Zhang   b    = matB->A;
18536e4ee0c6SHong Zhang   ierr = MatEqual(a,b,&flg);CHKERRQ(ierr);
1854b2566f29SBarry Smith   ierr = MPIU_Allreduce(&flg,flag,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
18556e4ee0c6SHong Zhang   PetscFunctionReturn(0);
18566e4ee0c6SHong Zhang }
185790ace30eSBarry Smith 
1858baa3c1c6SHong Zhang PetscErrorCode MatDestroy_MatTransMatMult_MPIDense_MPIDense(Mat A)
1859baa3c1c6SHong Zhang {
1860baa3c1c6SHong Zhang   PetscErrorCode        ierr;
1861baa3c1c6SHong Zhang   Mat_MPIDense          *a = (Mat_MPIDense*)A->data;
1862baa3c1c6SHong Zhang   Mat_TransMatMultDense *atb = a->atbdense;
1863baa3c1c6SHong Zhang 
1864baa3c1c6SHong Zhang   PetscFunctionBegin;
1865c5ef1628SHong Zhang   ierr = PetscFree3(atb->sendbuf,atb->atbarray,atb->recvcounts);CHKERRQ(ierr);
1866baa3c1c6SHong Zhang   ierr = (atb->destroy)(A);CHKERRQ(ierr);
1867baa3c1c6SHong Zhang   ierr = PetscFree(atb);CHKERRQ(ierr);
1868baa3c1c6SHong Zhang   PetscFunctionReturn(0);
1869baa3c1c6SHong Zhang }
1870baa3c1c6SHong Zhang 
1871cb20be35SHong Zhang PetscErrorCode MatTransposeMatMultNumeric_MPIDense_MPIDense(Mat A,Mat B,Mat C)
1872cb20be35SHong Zhang {
1873baa3c1c6SHong Zhang   Mat_MPIDense   *a=(Mat_MPIDense*)A->data, *b=(Mat_MPIDense*)B->data, *c=(Mat_MPIDense*)C->data;
1874660d5466SHong Zhang   Mat_SeqDense   *aseq=(Mat_SeqDense*)(a->A)->data, *bseq=(Mat_SeqDense*)(b->A)->data;
1875baa3c1c6SHong Zhang   Mat_TransMatMultDense *atb = c->atbdense;
1876cb20be35SHong Zhang   PetscErrorCode ierr;
1877cb20be35SHong Zhang   MPI_Comm       comm;
1878d5017740SHong Zhang   PetscMPIInt    rank,size,*recvcounts=atb->recvcounts;
1879c5ef1628SHong Zhang   PetscScalar    *carray,*atbarray=atb->atbarray,*sendbuf=atb->sendbuf;
1880d5017740SHong Zhang   PetscInt       i,cN=C->cmap->N,cM=C->rmap->N,proc,k,j;
1881660d5466SHong Zhang   PetscScalar    _DOne=1.0,_DZero=0.0;
1882adc7a786SHong Zhang   PetscBLASInt   am,an,bn,aN;
1883e68c0b26SHong Zhang   const PetscInt *ranges;
1884cb20be35SHong Zhang 
1885cb20be35SHong Zhang   PetscFunctionBegin;
1886cb20be35SHong Zhang   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1887cb20be35SHong Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1888cb20be35SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1889e68c0b26SHong Zhang 
1890c5ef1628SHong Zhang   /* compute atbarray = aseq^T * bseq */
1891660d5466SHong Zhang   ierr = PetscBLASIntCast(a->A->cmap->n,&an);CHKERRQ(ierr);
1892660d5466SHong Zhang   ierr = PetscBLASIntCast(b->A->cmap->n,&bn);CHKERRQ(ierr);
1893660d5466SHong Zhang   ierr = PetscBLASIntCast(a->A->rmap->n,&am);CHKERRQ(ierr);
1894adc7a786SHong Zhang   ierr = PetscBLASIntCast(A->cmap->N,&aN);CHKERRQ(ierr);
1895adc7a786SHong Zhang   PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&an,&bn,&am,&_DOne,aseq->v,&aseq->lda,bseq->v,&bseq->lda,&_DZero,atbarray,&aN));
1896cb20be35SHong Zhang 
1897cb20be35SHong Zhang   ierr = MatGetOwnershipRanges(C,&ranges);CHKERRQ(ierr);
1898c5ef1628SHong Zhang   for (i=0; i<size; i++) recvcounts[i] = (ranges[i+1] - ranges[i])*cN;
1899cb20be35SHong Zhang 
1900660d5466SHong Zhang   /* arrange atbarray into sendbuf */
1901cb20be35SHong Zhang   k = 0;
1902cb20be35SHong Zhang   for (proc=0; proc<size; proc++) {
1903baa3c1c6SHong Zhang     for (j=0; j<cN; j++) {
1904c5ef1628SHong Zhang       for (i=ranges[proc]; i<ranges[proc+1]; i++) sendbuf[k++] = atbarray[i+j*cM];
1905cb20be35SHong Zhang     }
1906cb20be35SHong Zhang   }
1907c5ef1628SHong Zhang   /* sum all atbarray to local values of C */
1908660d5466SHong Zhang   ierr = MatDenseGetArray(c->A,&carray);CHKERRQ(ierr);
19093462b7efSHong Zhang   ierr = MPI_Reduce_scatter(sendbuf,carray,recvcounts,MPIU_SCALAR,MPIU_SUM,comm);CHKERRQ(ierr);
1910660d5466SHong Zhang   ierr = MatDenseRestoreArray(c->A,&carray);CHKERRQ(ierr);
1911cb20be35SHong Zhang   PetscFunctionReturn(0);
1912cb20be35SHong Zhang }
1913cb20be35SHong Zhang 
1914cb20be35SHong Zhang PetscErrorCode MatTransposeMatMultSymbolic_MPIDense_MPIDense(Mat A,Mat B,PetscReal fill,Mat *C)
1915cb20be35SHong Zhang {
1916cb20be35SHong Zhang   PetscErrorCode        ierr;
1917baa3c1c6SHong Zhang   Mat                   Cdense;
1918cb20be35SHong Zhang   MPI_Comm              comm;
1919baa3c1c6SHong Zhang   PetscMPIInt           size;
1920660d5466SHong Zhang   PetscInt              cm=A->cmap->n,cM,cN=B->cmap->N;
1921baa3c1c6SHong Zhang   Mat_MPIDense          *c;
1922baa3c1c6SHong Zhang   Mat_TransMatMultDense *atb;
1923cb20be35SHong Zhang 
1924cb20be35SHong Zhang   PetscFunctionBegin;
1925baa3c1c6SHong Zhang   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1926cb20be35SHong Zhang   if (A->rmap->rstart != B->rmap->rstart || A->rmap->rend != B->rmap->rend) {
1927cb20be35SHong Zhang     SETERRQ4(comm,PETSC_ERR_ARG_SIZ,"Matrix local dimensions are incompatible, A (%D, %D) != B (%D,%D)",A->rmap->rstart,A->rmap->rend,B->rmap->rstart,B->rmap->rend);
1928cb20be35SHong Zhang   }
1929cb20be35SHong Zhang 
1930baa3c1c6SHong Zhang   /* create matrix product Cdense */
1931baa3c1c6SHong Zhang   ierr = MatCreate(comm,&Cdense);CHKERRQ(ierr);
1932660d5466SHong Zhang   ierr = MatSetSizes(Cdense,cm,B->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1933baa3c1c6SHong Zhang   ierr = MatSetType(Cdense,MATMPIDENSE);CHKERRQ(ierr);
1934baa3c1c6SHong Zhang   ierr = MatMPIDenseSetPreallocation(Cdense,NULL);CHKERRQ(ierr);
1935baa3c1c6SHong Zhang   ierr = MatAssemblyBegin(Cdense,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1936baa3c1c6SHong Zhang   ierr = MatAssemblyEnd(Cdense,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1937baa3c1c6SHong Zhang   *C   = Cdense;
1938baa3c1c6SHong Zhang 
1939baa3c1c6SHong Zhang   /* create data structure for reuse Cdense */
1940baa3c1c6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1941baa3c1c6SHong Zhang   ierr = PetscNew(&atb);CHKERRQ(ierr);
1942660d5466SHong Zhang   cM = Cdense->rmap->N;
1943c5ef1628SHong Zhang   ierr = PetscMalloc3(cM*cN,&atb->sendbuf,cM*cN,&atb->atbarray,size,&atb->recvcounts);CHKERRQ(ierr);
1944baa3c1c6SHong Zhang 
1945baa3c1c6SHong Zhang   c                    = (Mat_MPIDense*)Cdense->data;
1946baa3c1c6SHong Zhang   c->atbdense          = atb;
1947baa3c1c6SHong Zhang   atb->destroy         = Cdense->ops->destroy;
1948baa3c1c6SHong Zhang   Cdense->ops->destroy = MatDestroy_MatTransMatMult_MPIDense_MPIDense;
1949cb20be35SHong Zhang   PetscFunctionReturn(0);
1950cb20be35SHong Zhang }
1951cb20be35SHong Zhang 
1952cb20be35SHong Zhang PetscErrorCode MatTransposeMatMult_MPIDense_MPIDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
1953cb20be35SHong Zhang {
1954cb20be35SHong Zhang   PetscErrorCode ierr;
1955cb20be35SHong Zhang 
1956cb20be35SHong Zhang   PetscFunctionBegin;
1957cb20be35SHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
1958cb20be35SHong Zhang     ierr = MatTransposeMatMultSymbolic_MPIDense_MPIDense(A,B,fill,C);CHKERRQ(ierr);
1959cb20be35SHong Zhang   }
1960cb20be35SHong Zhang   ierr = MatTransposeMatMultNumeric_MPIDense_MPIDense(A,B,*C);CHKERRQ(ierr);
1961cb20be35SHong Zhang   PetscFunctionReturn(0);
1962cb20be35SHong Zhang }
1963320f2790SHong Zhang 
1964320f2790SHong Zhang PetscErrorCode MatDestroy_MatMatMult_MPIDense_MPIDense(Mat A)
1965320f2790SHong Zhang {
1966320f2790SHong Zhang   PetscErrorCode   ierr;
1967320f2790SHong Zhang   Mat_MPIDense     *a = (Mat_MPIDense*)A->data;
1968320f2790SHong Zhang   Mat_MatMultDense *ab = a->abdense;
1969320f2790SHong Zhang 
1970320f2790SHong Zhang   PetscFunctionBegin;
1971320f2790SHong Zhang   ierr = MatDestroy(&ab->Ce);CHKERRQ(ierr);
1972320f2790SHong Zhang   ierr = MatDestroy(&ab->Ae);CHKERRQ(ierr);
1973320f2790SHong Zhang   ierr = MatDestroy(&ab->Be);CHKERRQ(ierr);
1974320f2790SHong Zhang 
1975320f2790SHong Zhang   ierr = (ab->destroy)(A);CHKERRQ(ierr);
1976320f2790SHong Zhang   ierr = PetscFree(ab);CHKERRQ(ierr);
1977320f2790SHong Zhang   PetscFunctionReturn(0);
1978320f2790SHong Zhang }
1979320f2790SHong Zhang 
19805242a7b1SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1981320f2790SHong Zhang PetscErrorCode MatMatMultNumeric_MPIDense_MPIDense(Mat A,Mat B,Mat C)
1982320f2790SHong Zhang {
1983320f2790SHong Zhang   PetscErrorCode   ierr;
1984320f2790SHong Zhang   Mat_MPIDense     *c=(Mat_MPIDense*)C->data;
1985320f2790SHong Zhang   Mat_MatMultDense *ab=c->abdense;
1986320f2790SHong Zhang 
1987320f2790SHong Zhang   PetscFunctionBegin;
1988de0a22f0SHong Zhang   ierr = MatConvert_MPIDense_Elemental(A,MATELEMENTAL,MAT_REUSE_MATRIX, &ab->Ae);CHKERRQ(ierr);
1989de0a22f0SHong Zhang   ierr = MatConvert_MPIDense_Elemental(B,MATELEMENTAL,MAT_REUSE_MATRIX, &ab->Be);CHKERRQ(ierr);
1990320f2790SHong Zhang   ierr = MatMatMultNumeric(ab->Ae,ab->Be,ab->Ce);CHKERRQ(ierr);
1991de0a22f0SHong Zhang   ierr = MatConvert(ab->Ce,MATMPIDENSE,MAT_REUSE_MATRIX,&C);CHKERRQ(ierr);
1992320f2790SHong Zhang   PetscFunctionReturn(0);
1993320f2790SHong Zhang }
1994320f2790SHong Zhang 
1995320f2790SHong Zhang PetscErrorCode MatMatMultSymbolic_MPIDense_MPIDense(Mat A,Mat B,PetscReal fill,Mat *C)
1996320f2790SHong Zhang {
1997320f2790SHong Zhang   PetscErrorCode   ierr;
1998320f2790SHong Zhang   Mat              Ae,Be,Ce;
1999320f2790SHong Zhang   Mat_MPIDense     *c;
2000320f2790SHong Zhang   Mat_MatMultDense *ab;
2001320f2790SHong Zhang 
2002320f2790SHong Zhang   PetscFunctionBegin;
2003320f2790SHong Zhang   if (A->cmap->rstart != B->rmap->rstart || A->cmap->rend != B->rmap->rend) {
2004378336b6SHong Zhang     SETERRQ4(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Matrix local dimensions are incompatible, A (%D, %D) != B (%D,%D)",A->rmap->rstart,A->rmap->rend,B->rmap->rstart,B->rmap->rend);
2005320f2790SHong Zhang   }
2006320f2790SHong Zhang 
2007320f2790SHong Zhang   /* convert A and B to Elemental matrices Ae and Be */
2008320f2790SHong Zhang   ierr = MatConvert(A,MATELEMENTAL,MAT_INITIAL_MATRIX, &Ae);CHKERRQ(ierr);
2009320f2790SHong Zhang   ierr = MatConvert(B,MATELEMENTAL,MAT_INITIAL_MATRIX, &Be);CHKERRQ(ierr);
2010320f2790SHong Zhang 
2011320f2790SHong Zhang   /* Ce = Ae*Be */
2012320f2790SHong Zhang   ierr = MatMatMultSymbolic(Ae,Be,fill,&Ce);CHKERRQ(ierr);
2013320f2790SHong Zhang   ierr = MatMatMultNumeric(Ae,Be,Ce);CHKERRQ(ierr);
2014320f2790SHong Zhang 
2015320f2790SHong Zhang   /* convert Ce to C */
2016320f2790SHong Zhang   ierr = MatConvert(Ce,MATMPIDENSE,MAT_INITIAL_MATRIX,C);CHKERRQ(ierr);
2017320f2790SHong Zhang 
2018320f2790SHong Zhang   /* create data structure for reuse Cdense */
2019320f2790SHong Zhang   ierr = PetscNew(&ab);CHKERRQ(ierr);
2020320f2790SHong Zhang   c                  = (Mat_MPIDense*)(*C)->data;
2021320f2790SHong Zhang   c->abdense         = ab;
2022320f2790SHong Zhang 
2023320f2790SHong Zhang   ab->Ae             = Ae;
2024320f2790SHong Zhang   ab->Be             = Be;
2025320f2790SHong Zhang   ab->Ce             = Ce;
2026320f2790SHong Zhang   ab->destroy        = (*C)->ops->destroy;
2027320f2790SHong Zhang   (*C)->ops->destroy        = MatDestroy_MatMatMult_MPIDense_MPIDense;
20289775878aSHong Zhang   (*C)->ops->matmultnumeric = MatMatMultNumeric_MPIDense_MPIDense;
2029320f2790SHong Zhang   PetscFunctionReturn(0);
2030320f2790SHong Zhang }
2031320f2790SHong Zhang 
2032150d2497SBarry Smith PETSC_INTERN PetscErrorCode MatMatMult_MPIDense_MPIDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
2033320f2790SHong Zhang {
2034320f2790SHong Zhang   PetscErrorCode ierr;
2035320f2790SHong Zhang 
2036320f2790SHong Zhang   PetscFunctionBegin;
2037320f2790SHong Zhang   if (scall == MAT_INITIAL_MATRIX) { /* simbolic product includes numeric product */
203857299f2fSHong Zhang     ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
2039320f2790SHong Zhang     ierr = MatMatMultSymbolic_MPIDense_MPIDense(A,B,fill,C);CHKERRQ(ierr);
204057299f2fSHong Zhang     ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
2041320f2790SHong Zhang   } else {
204257299f2fSHong Zhang     ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
2043320f2790SHong Zhang     ierr = MatMatMultNumeric_MPIDense_MPIDense(A,B,*C);CHKERRQ(ierr);
204457299f2fSHong Zhang     ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
2045320f2790SHong Zhang   }
2046320f2790SHong Zhang   PetscFunctionReturn(0);
2047320f2790SHong Zhang }
20485242a7b1SHong Zhang #endif
204986aefd0dSHong Zhang 
2050