xref: /petsc/src/mat/impls/dense/mpi/mpidense.c (revision 14459f091ed32b600f4cb73c4e9a18d8907fe886)
1be1d678aSKris Buschelman #define PETSCMAT_DLL
2be1d678aSKris Buschelman 
3ed3cc1f0SBarry Smith /*
4ed3cc1f0SBarry Smith    Basic functions for basic parallel dense matrices.
5ed3cc1f0SBarry Smith */
6ed3cc1f0SBarry Smith 
789ac3759SBarry Smith #include "src/mat/impls/dense/mpi/mpidense.h"    /*I   "petscmat.h"  I*/
88965ea79SLois Curfman McInnes 
9ba8c8a56SBarry Smith #undef __FUNCT__
100ad19415SHong Zhang #define __FUNCT__ "MatLUFactorSymbolic_MPIDense"
110ad19415SHong Zhang PetscErrorCode MatLUFactorSymbolic_MPIDense(Mat A,IS row,IS col,MatFactorInfo *info,Mat *fact)
120ad19415SHong Zhang {
130ad19415SHong Zhang   PetscErrorCode ierr;
140ad19415SHong Zhang 
150ad19415SHong Zhang   PetscFunctionBegin;
166017fc9fSHong Zhang   ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,fact);CHKERRQ(ierr);
170ad19415SHong Zhang   PetscFunctionReturn(0);
180ad19415SHong Zhang }
190ad19415SHong Zhang 
200ad19415SHong Zhang #undef __FUNCT__
210ad19415SHong Zhang #define __FUNCT__ "MatCholeskyFactorSymbolic_MPIDense"
226017fc9fSHong Zhang PetscErrorCode MatCholeskyFactorSymbolic_MPIDense(Mat A,IS perm,MatFactorInfo *info,Mat *fact)
230ad19415SHong Zhang {
240ad19415SHong Zhang   PetscErrorCode ierr;
250ad19415SHong Zhang 
260ad19415SHong Zhang   PetscFunctionBegin;
276017fc9fSHong Zhang   ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,fact);CHKERRQ(ierr);
280ad19415SHong Zhang   PetscFunctionReturn(0);
290ad19415SHong Zhang }
300ad19415SHong Zhang 
310ad19415SHong Zhang #undef __FUNCT__
32ab92ecdeSBarry Smith #define __FUNCT__ "MatDenseGetLocalMatrix"
33ab92ecdeSBarry Smith /*@
34ab92ecdeSBarry Smith 
35ab92ecdeSBarry Smith       MatDenseGetLocalMatrix - For a MATMPIDENSE or MATSEQDENSE matrix returns the sequential
36ab92ecdeSBarry Smith               matrix that represents the operator. For sequential matrices it returns itself.
37ab92ecdeSBarry Smith 
38ab92ecdeSBarry Smith     Input Parameter:
39ab92ecdeSBarry Smith .      A - the Seq or MPI dense matrix
40ab92ecdeSBarry Smith 
41ab92ecdeSBarry Smith     Output Parameter:
42ab92ecdeSBarry Smith .      B - the inner matrix
43ab92ecdeSBarry Smith 
448e6c10adSSatish Balay     Level: intermediate
458e6c10adSSatish Balay 
46ab92ecdeSBarry Smith @*/
47ab92ecdeSBarry Smith PetscErrorCode MatDenseGetLocalMatrix(Mat A,Mat *B)
48ab92ecdeSBarry Smith {
49ab92ecdeSBarry Smith   Mat_MPIDense   *mat = (Mat_MPIDense*)A->data;
50ab92ecdeSBarry Smith   PetscErrorCode ierr;
51ab92ecdeSBarry Smith   PetscTruth     flg;
52ab92ecdeSBarry Smith   PetscMPIInt    size;
53ab92ecdeSBarry Smith 
54ab92ecdeSBarry Smith   PetscFunctionBegin;
55ab92ecdeSBarry Smith   ierr = PetscTypeCompare((PetscObject)A,MATMPIDENSE,&flg);CHKERRQ(ierr);
56ab92ecdeSBarry Smith   if (!flg) {  /* this check sucks! */
57ab92ecdeSBarry Smith     ierr = PetscTypeCompare((PetscObject)A,MATDENSE,&flg);CHKERRQ(ierr);
58ab92ecdeSBarry Smith     if (flg) {
59ab92ecdeSBarry Smith       ierr = MPI_Comm_size(A->comm,&size);CHKERRQ(ierr);
60ab92ecdeSBarry Smith       if (size == 1) flg = PETSC_FALSE;
61ab92ecdeSBarry Smith     }
62ab92ecdeSBarry Smith   }
63ab92ecdeSBarry Smith   if (flg) {
64ab92ecdeSBarry Smith     *B = mat->A;
65ab92ecdeSBarry Smith   } else {
66ab92ecdeSBarry Smith     *B = A;
67ab92ecdeSBarry Smith   }
68ab92ecdeSBarry Smith   PetscFunctionReturn(0);
69ab92ecdeSBarry Smith }
70ab92ecdeSBarry Smith 
71ab92ecdeSBarry Smith #undef __FUNCT__
72ba8c8a56SBarry Smith #define __FUNCT__ "MatGetRow_MPIDense"
73ba8c8a56SBarry Smith PetscErrorCode MatGetRow_MPIDense(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
74ba8c8a56SBarry Smith {
75ba8c8a56SBarry Smith   Mat_MPIDense   *mat = (Mat_MPIDense*)A->data;
76ba8c8a56SBarry Smith   PetscErrorCode ierr;
77899cda47SBarry Smith   PetscInt       lrow,rstart = A->rmap.rstart,rend = A->rmap.rend;
78ba8c8a56SBarry Smith 
79ba8c8a56SBarry Smith   PetscFunctionBegin;
80ba8c8a56SBarry Smith   if (row < rstart || row >= rend) SETERRQ(PETSC_ERR_SUP,"only local rows")
81ba8c8a56SBarry Smith   lrow = row - rstart;
82ba8c8a56SBarry Smith   ierr = MatGetRow(mat->A,lrow,nz,(const PetscInt **)idx,(const PetscScalar **)v);CHKERRQ(ierr);
83ba8c8a56SBarry Smith   PetscFunctionReturn(0);
84ba8c8a56SBarry Smith }
85ba8c8a56SBarry Smith 
86ba8c8a56SBarry Smith #undef __FUNCT__
87ba8c8a56SBarry Smith #define __FUNCT__ "MatRestoreRow_MPIDense"
88ba8c8a56SBarry Smith PetscErrorCode MatRestoreRow_MPIDense(Mat mat,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
89ba8c8a56SBarry Smith {
90ba8c8a56SBarry Smith   PetscErrorCode ierr;
91ba8c8a56SBarry Smith 
92ba8c8a56SBarry Smith   PetscFunctionBegin;
93ba8c8a56SBarry Smith   if (idx) {ierr = PetscFree(*idx);CHKERRQ(ierr);}
94ba8c8a56SBarry Smith   if (v) {ierr = PetscFree(*v);CHKERRQ(ierr);}
95ba8c8a56SBarry Smith   PetscFunctionReturn(0);
96ba8c8a56SBarry Smith }
97ba8c8a56SBarry Smith 
980de54da6SSatish Balay EXTERN_C_BEGIN
994a2ae208SSatish Balay #undef __FUNCT__
1004a2ae208SSatish Balay #define __FUNCT__ "MatGetDiagonalBlock_MPIDense"
101be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatGetDiagonalBlock_MPIDense(Mat A,PetscTruth *iscopy,MatReuse reuse,Mat *B)
1020de54da6SSatish Balay {
1030de54da6SSatish Balay   Mat_MPIDense   *mdn = (Mat_MPIDense*)A->data;
1046849ba73SBarry Smith   PetscErrorCode ierr;
105899cda47SBarry Smith   PetscInt       m = A->rmap.n,rstart = A->rmap.rstart;
10687828ca2SBarry Smith   PetscScalar    *array;
1070de54da6SSatish Balay   MPI_Comm       comm;
1080de54da6SSatish Balay 
1090de54da6SSatish Balay   PetscFunctionBegin;
110899cda47SBarry Smith   if (A->rmap.N != A->cmap.N) SETERRQ(PETSC_ERR_SUP,"Only square matrices supported.");
1110de54da6SSatish Balay 
1120de54da6SSatish Balay   /* The reuse aspect is not implemented efficiently */
1130de54da6SSatish Balay   if (reuse) { ierr = MatDestroy(*B);CHKERRQ(ierr);}
1140de54da6SSatish Balay 
1150de54da6SSatish Balay   ierr = PetscObjectGetComm((PetscObject)(mdn->A),&comm);CHKERRQ(ierr);
1160de54da6SSatish Balay   ierr = MatGetArray(mdn->A,&array);CHKERRQ(ierr);
117f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,B);CHKERRQ(ierr);
118f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,m,m,m);CHKERRQ(ierr);
1195c5985e7SKris Buschelman   ierr = MatSetType(*B,mdn->A->type_name);CHKERRQ(ierr);
1205c5985e7SKris Buschelman   ierr = MatSeqDenseSetPreallocation(*B,array+m*rstart);CHKERRQ(ierr);
1210de54da6SSatish Balay   ierr = MatRestoreArray(mdn->A,&array);CHKERRQ(ierr);
1220de54da6SSatish Balay   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1230de54da6SSatish Balay   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1240de54da6SSatish Balay 
1250de54da6SSatish Balay   *iscopy = PETSC_TRUE;
1260de54da6SSatish Balay   PetscFunctionReturn(0);
1270de54da6SSatish Balay }
1280de54da6SSatish Balay EXTERN_C_END
1290de54da6SSatish Balay 
1304a2ae208SSatish Balay #undef __FUNCT__
1314a2ae208SSatish Balay #define __FUNCT__ "MatSetValues_MPIDense"
13213f74950SBarry Smith PetscErrorCode MatSetValues_MPIDense(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],const PetscScalar v[],InsertMode addv)
1338965ea79SLois Curfman McInnes {
13439b7565bSBarry Smith   Mat_MPIDense   *A = (Mat_MPIDense*)mat->data;
135dfbe8321SBarry Smith   PetscErrorCode ierr;
136899cda47SBarry Smith   PetscInt       i,j,rstart = mat->rmap.rstart,rend = mat->rmap.rend,row;
137273d9f13SBarry Smith   PetscTruth     roworiented = A->roworiented;
1388965ea79SLois Curfman McInnes 
1393a40ed3dSBarry Smith   PetscFunctionBegin;
1408965ea79SLois Curfman McInnes   for (i=0; i<m; i++) {
1415ef9f2a5SBarry Smith     if (idxm[i] < 0) continue;
142899cda47SBarry Smith     if (idxm[i] >= mat->rmap.N) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
1438965ea79SLois Curfman McInnes     if (idxm[i] >= rstart && idxm[i] < rend) {
1448965ea79SLois Curfman McInnes       row = idxm[i] - rstart;
14539b7565bSBarry Smith       if (roworiented) {
14639b7565bSBarry Smith         ierr = MatSetValues(A->A,1,&row,n,idxn,v+i*n,addv);CHKERRQ(ierr);
1473a40ed3dSBarry Smith       } else {
1488965ea79SLois Curfman McInnes         for (j=0; j<n; j++) {
1495ef9f2a5SBarry Smith           if (idxn[j] < 0) continue;
150899cda47SBarry Smith           if (idxn[j] >= mat->cmap.N) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
15139b7565bSBarry Smith           ierr = MatSetValues(A->A,1,&row,1,&idxn[j],v+i+j*m,addv);CHKERRQ(ierr);
15239b7565bSBarry Smith         }
1538965ea79SLois Curfman McInnes       }
1543a40ed3dSBarry Smith     } else {
1553782ba37SSatish Balay       if (!A->donotstash) {
15639b7565bSBarry Smith         if (roworiented) {
1578798bf22SSatish Balay           ierr = MatStashValuesRow_Private(&mat->stash,idxm[i],n,idxn,v+i*n);CHKERRQ(ierr);
158d36fbae8SSatish Balay         } else {
1598798bf22SSatish Balay           ierr = MatStashValuesCol_Private(&mat->stash,idxm[i],n,idxn,v+i,m);CHKERRQ(ierr);
16039b7565bSBarry Smith         }
161b49de8d1SLois Curfman McInnes       }
162b49de8d1SLois Curfman McInnes     }
1633782ba37SSatish Balay   }
1643a40ed3dSBarry Smith   PetscFunctionReturn(0);
165b49de8d1SLois Curfman McInnes }
166b49de8d1SLois Curfman McInnes 
1674a2ae208SSatish Balay #undef __FUNCT__
1684a2ae208SSatish Balay #define __FUNCT__ "MatGetValues_MPIDense"
16913f74950SBarry Smith PetscErrorCode MatGetValues_MPIDense(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
170b49de8d1SLois Curfman McInnes {
171b49de8d1SLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)mat->data;
172dfbe8321SBarry Smith   PetscErrorCode ierr;
173899cda47SBarry Smith   PetscInt       i,j,rstart = mat->rmap.rstart,rend = mat->rmap.rend,row;
174b49de8d1SLois Curfman McInnes 
1753a40ed3dSBarry Smith   PetscFunctionBegin;
176b49de8d1SLois Curfman McInnes   for (i=0; i<m; i++) {
17729bbc08cSBarry Smith     if (idxm[i] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative row");
178899cda47SBarry Smith     if (idxm[i] >= mat->rmap.N) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
179b49de8d1SLois Curfman McInnes     if (idxm[i] >= rstart && idxm[i] < rend) {
180b49de8d1SLois Curfman McInnes       row = idxm[i] - rstart;
181b49de8d1SLois Curfman McInnes       for (j=0; j<n; j++) {
18229bbc08cSBarry Smith         if (idxn[j] < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative column");
183899cda47SBarry Smith         if (idxn[j] >= mat->cmap.N) {
18429bbc08cSBarry Smith           SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
185a8c6a408SBarry Smith         }
186b49de8d1SLois Curfman McInnes         ierr = MatGetValues(mdn->A,1,&row,1,&idxn[j],v+i*n+j);CHKERRQ(ierr);
187b49de8d1SLois Curfman McInnes       }
188a8c6a408SBarry Smith     } else {
18929bbc08cSBarry Smith       SETERRQ(PETSC_ERR_SUP,"Only local values currently supported");
1908965ea79SLois Curfman McInnes     }
1918965ea79SLois Curfman McInnes   }
1923a40ed3dSBarry Smith   PetscFunctionReturn(0);
1938965ea79SLois Curfman McInnes }
1948965ea79SLois Curfman McInnes 
1954a2ae208SSatish Balay #undef __FUNCT__
1964a2ae208SSatish Balay #define __FUNCT__ "MatGetArray_MPIDense"
197dfbe8321SBarry Smith PetscErrorCode MatGetArray_MPIDense(Mat A,PetscScalar *array[])
198ff14e315SSatish Balay {
199ff14e315SSatish Balay   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
200dfbe8321SBarry Smith   PetscErrorCode ierr;
201ff14e315SSatish Balay 
2023a40ed3dSBarry Smith   PetscFunctionBegin;
203ff14e315SSatish Balay   ierr = MatGetArray(a->A,array);CHKERRQ(ierr);
2043a40ed3dSBarry Smith   PetscFunctionReturn(0);
205ff14e315SSatish Balay }
206ff14e315SSatish Balay 
2074a2ae208SSatish Balay #undef __FUNCT__
2084a2ae208SSatish Balay #define __FUNCT__ "MatGetSubMatrix_MPIDense"
20913f74950SBarry Smith static PetscErrorCode MatGetSubMatrix_MPIDense(Mat A,IS isrow,IS iscol,PetscInt cs,MatReuse scall,Mat *B)
210ca3fa75bSLois Curfman McInnes {
211ca3fa75bSLois Curfman McInnes   Mat_MPIDense   *mat = (Mat_MPIDense*)A->data,*newmatd;
212ca3fa75bSLois Curfman McInnes   Mat_SeqDense   *lmat = (Mat_SeqDense*)mat->A->data;
2136849ba73SBarry Smith   PetscErrorCode ierr;
21413f74950SBarry Smith   PetscInt       i,j,*irow,*icol,rstart,rend,nrows,ncols,nlrows,nlcols;
21587828ca2SBarry Smith   PetscScalar    *av,*bv,*v = lmat->v;
216ca3fa75bSLois Curfman McInnes   Mat            newmat;
217ca3fa75bSLois Curfman McInnes 
218ca3fa75bSLois Curfman McInnes   PetscFunctionBegin;
219ca3fa75bSLois Curfman McInnes   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
220ca3fa75bSLois Curfman McInnes   ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
221b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
222b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
223ca3fa75bSLois Curfman McInnes 
224ca3fa75bSLois Curfman McInnes   /* No parallel redistribution currently supported! Should really check each index set
2257eba5e9cSLois Curfman McInnes      to comfirm that it is OK.  ... Currently supports only submatrix same partitioning as
2267eba5e9cSLois Curfman McInnes      original matrix! */
227ca3fa75bSLois Curfman McInnes 
228ca3fa75bSLois Curfman McInnes   ierr = MatGetLocalSize(A,&nlrows,&nlcols);CHKERRQ(ierr);
2297eba5e9cSLois Curfman McInnes   ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr);
230ca3fa75bSLois Curfman McInnes 
231ca3fa75bSLois Curfman McInnes   /* Check submatrix call */
232ca3fa75bSLois Curfman McInnes   if (scall == MAT_REUSE_MATRIX) {
23329bbc08cSBarry Smith     /* SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size"); */
2347eba5e9cSLois Curfman McInnes     /* Really need to test rows and column sizes! */
235ca3fa75bSLois Curfman McInnes     newmat = *B;
236ca3fa75bSLois Curfman McInnes   } else {
237ca3fa75bSLois Curfman McInnes     /* Create and fill new matrix */
238f69a0ea3SMatthew Knepley     ierr = MatCreate(A->comm,&newmat);CHKERRQ(ierr);
239f69a0ea3SMatthew Knepley     ierr = MatSetSizes(newmat,nrows,cs,PETSC_DECIDE,ncols);CHKERRQ(ierr);
240878740d9SKris Buschelman     ierr = MatSetType(newmat,A->type_name);CHKERRQ(ierr);
241878740d9SKris Buschelman     ierr = MatMPIDenseSetPreallocation(newmat,PETSC_NULL);CHKERRQ(ierr);
242ca3fa75bSLois Curfman McInnes   }
243ca3fa75bSLois Curfman McInnes 
244ca3fa75bSLois Curfman McInnes   /* Now extract the data pointers and do the copy, column at a time */
245ca3fa75bSLois Curfman McInnes   newmatd = (Mat_MPIDense*)newmat->data;
246ca3fa75bSLois Curfman McInnes   bv      = ((Mat_SeqDense *)newmatd->A->data)->v;
247ca3fa75bSLois Curfman McInnes 
248ca3fa75bSLois Curfman McInnes   for (i=0; i<ncols; i++) {
249ca3fa75bSLois Curfman McInnes     av = v + nlrows*icol[i];
250ca3fa75bSLois Curfman McInnes     for (j=0; j<nrows; j++) {
2517eba5e9cSLois Curfman McInnes       *bv++ = av[irow[j] - rstart];
252ca3fa75bSLois Curfman McInnes     }
253ca3fa75bSLois Curfman McInnes   }
254ca3fa75bSLois Curfman McInnes 
255ca3fa75bSLois Curfman McInnes   /* Assemble the matrices so that the correct flags are set */
256ca3fa75bSLois Curfman McInnes   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
257ca3fa75bSLois Curfman McInnes   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
258ca3fa75bSLois Curfman McInnes 
259ca3fa75bSLois Curfman McInnes   /* Free work space */
260ca3fa75bSLois Curfman McInnes   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
261ca3fa75bSLois Curfman McInnes   ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
262ca3fa75bSLois Curfman McInnes   *B = newmat;
263ca3fa75bSLois Curfman McInnes   PetscFunctionReturn(0);
264ca3fa75bSLois Curfman McInnes }
265ca3fa75bSLois Curfman McInnes 
2664a2ae208SSatish Balay #undef __FUNCT__
2674a2ae208SSatish Balay #define __FUNCT__ "MatRestoreArray_MPIDense"
268dfbe8321SBarry Smith PetscErrorCode MatRestoreArray_MPIDense(Mat A,PetscScalar *array[])
269ff14e315SSatish Balay {
2703a40ed3dSBarry Smith   PetscFunctionBegin;
2713a40ed3dSBarry Smith   PetscFunctionReturn(0);
272ff14e315SSatish Balay }
273ff14e315SSatish Balay 
2744a2ae208SSatish Balay #undef __FUNCT__
2754a2ae208SSatish Balay #define __FUNCT__ "MatAssemblyBegin_MPIDense"
276dfbe8321SBarry Smith PetscErrorCode MatAssemblyBegin_MPIDense(Mat mat,MatAssemblyType mode)
2778965ea79SLois Curfman McInnes {
27839ddd567SLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)mat->data;
2798965ea79SLois Curfman McInnes   MPI_Comm       comm = mat->comm;
280dfbe8321SBarry Smith   PetscErrorCode ierr;
28113f74950SBarry Smith   PetscInt       nstash,reallocs;
2828965ea79SLois Curfman McInnes   InsertMode     addv;
2838965ea79SLois Curfman McInnes 
2843a40ed3dSBarry Smith   PetscFunctionBegin;
2858965ea79SLois Curfman McInnes   /* make sure all processors are either in INSERTMODE or ADDMODE */
286ca161407SBarry Smith   ierr = MPI_Allreduce(&mat->insertmode,&addv,1,MPI_INT,MPI_BOR,comm);CHKERRQ(ierr);
2877056b6fcSBarry Smith   if (addv == (ADD_VALUES|INSERT_VALUES)) {
28829bbc08cSBarry Smith     SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Cannot mix adds/inserts on different procs");
2898965ea79SLois Curfman McInnes   }
290e0fa3b82SLois Curfman McInnes   mat->insertmode = addv; /* in case this processor had no cache */
2918965ea79SLois Curfman McInnes 
292899cda47SBarry Smith   ierr = MatStashScatterBegin_Private(&mat->stash,mat->rmap.range);CHKERRQ(ierr);
2938798bf22SSatish Balay   ierr = MatStashGetInfo_Private(&mat->stash,&nstash,&reallocs);CHKERRQ(ierr);
294ae15b995SBarry Smith   ierr = PetscInfo2(mdn->A,"Stash has %D entries, uses %D mallocs.\n",nstash,reallocs);CHKERRQ(ierr);
2953a40ed3dSBarry Smith   PetscFunctionReturn(0);
2968965ea79SLois Curfman McInnes }
2978965ea79SLois Curfman McInnes 
2984a2ae208SSatish Balay #undef __FUNCT__
2994a2ae208SSatish Balay #define __FUNCT__ "MatAssemblyEnd_MPIDense"
300dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_MPIDense(Mat mat,MatAssemblyType mode)
3018965ea79SLois Curfman McInnes {
30239ddd567SLois Curfman McInnes   Mat_MPIDense    *mdn=(Mat_MPIDense*)mat->data;
3036849ba73SBarry Smith   PetscErrorCode  ierr;
30413f74950SBarry Smith   PetscInt        i,*row,*col,flg,j,rstart,ncols;
30513f74950SBarry Smith   PetscMPIInt     n;
30687828ca2SBarry Smith   PetscScalar     *val;
307e0fa3b82SLois Curfman McInnes   InsertMode      addv=mat->insertmode;
3088965ea79SLois Curfman McInnes 
3093a40ed3dSBarry Smith   PetscFunctionBegin;
3108965ea79SLois Curfman McInnes   /*  wait on receives */
3117ef1d9bdSSatish Balay   while (1) {
3128798bf22SSatish Balay     ierr = MatStashScatterGetMesg_Private(&mat->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr);
3137ef1d9bdSSatish Balay     if (!flg) break;
3148965ea79SLois Curfman McInnes 
3157ef1d9bdSSatish Balay     for (i=0; i<n;) {
3167ef1d9bdSSatish Balay       /* Now identify the consecutive vals belonging to the same row */
3177ef1d9bdSSatish Balay       for (j=i,rstart=row[j]; j<n; j++) { if (row[j] != rstart) break; }
3187ef1d9bdSSatish Balay       if (j < n) ncols = j-i;
3197ef1d9bdSSatish Balay       else       ncols = n-i;
3207ef1d9bdSSatish Balay       /* Now assemble all these values with a single function call */
3217ef1d9bdSSatish Balay       ierr = MatSetValues_MPIDense(mat,1,row+i,ncols,col+i,val+i,addv);CHKERRQ(ierr);
3227ef1d9bdSSatish Balay       i = j;
3238965ea79SLois Curfman McInnes     }
3247ef1d9bdSSatish Balay   }
3258798bf22SSatish Balay   ierr = MatStashScatterEnd_Private(&mat->stash);CHKERRQ(ierr);
3268965ea79SLois Curfman McInnes 
32739ddd567SLois Curfman McInnes   ierr = MatAssemblyBegin(mdn->A,mode);CHKERRQ(ierr);
32839ddd567SLois Curfman McInnes   ierr = MatAssemblyEnd(mdn->A,mode);CHKERRQ(ierr);
3298965ea79SLois Curfman McInnes 
3306d4a8577SBarry Smith   if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) {
33139ddd567SLois Curfman McInnes     ierr = MatSetUpMultiply_MPIDense(mat);CHKERRQ(ierr);
3328965ea79SLois Curfman McInnes   }
3333a40ed3dSBarry Smith   PetscFunctionReturn(0);
3348965ea79SLois Curfman McInnes }
3358965ea79SLois Curfman McInnes 
3364a2ae208SSatish Balay #undef __FUNCT__
3374a2ae208SSatish Balay #define __FUNCT__ "MatZeroEntries_MPIDense"
338dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_MPIDense(Mat A)
3398965ea79SLois Curfman McInnes {
340dfbe8321SBarry Smith   PetscErrorCode ierr;
34139ddd567SLois Curfman McInnes   Mat_MPIDense   *l = (Mat_MPIDense*)A->data;
3423a40ed3dSBarry Smith 
3433a40ed3dSBarry Smith   PetscFunctionBegin;
3443a40ed3dSBarry Smith   ierr = MatZeroEntries(l->A);CHKERRQ(ierr);
3453a40ed3dSBarry Smith   PetscFunctionReturn(0);
3468965ea79SLois Curfman McInnes }
3478965ea79SLois Curfman McInnes 
3488965ea79SLois Curfman McInnes /* the code does not do the diagonal entries correctly unless the
3498965ea79SLois Curfman McInnes    matrix is square and the column and row owerships are identical.
3508965ea79SLois Curfman McInnes    This is a BUG. The only way to fix it seems to be to access
3513501a2bdSLois Curfman McInnes    mdn->A and mdn->B directly and not through the MatZeroRows()
3528965ea79SLois Curfman McInnes    routine.
3538965ea79SLois Curfman McInnes */
3544a2ae208SSatish Balay #undef __FUNCT__
3554a2ae208SSatish Balay #define __FUNCT__ "MatZeroRows_MPIDense"
356f4df32b1SMatthew Knepley PetscErrorCode MatZeroRows_MPIDense(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag)
3578965ea79SLois Curfman McInnes {
35839ddd567SLois Curfman McInnes   Mat_MPIDense   *l = (Mat_MPIDense*)A->data;
3596849ba73SBarry Smith   PetscErrorCode ierr;
360899cda47SBarry Smith   PetscInt       i,*owners = A->rmap.range;
36113f74950SBarry Smith   PetscInt       *nprocs,j,idx,nsends;
36213f74950SBarry Smith   PetscInt       nmax,*svalues,*starts,*owner,nrecvs;
36313f74950SBarry Smith   PetscInt       *rvalues,tag = A->tag,count,base,slen,*source;
36413f74950SBarry Smith   PetscInt       *lens,*lrows,*values;
36513f74950SBarry Smith   PetscMPIInt    n,imdex,rank = l->rank,size = l->size;
3668965ea79SLois Curfman McInnes   MPI_Comm       comm = A->comm;
3678965ea79SLois Curfman McInnes   MPI_Request    *send_waits,*recv_waits;
3688965ea79SLois Curfman McInnes   MPI_Status     recv_status,*send_status;
36935d8aa7fSBarry Smith   PetscTruth     found;
3708965ea79SLois Curfman McInnes 
3713a40ed3dSBarry Smith   PetscFunctionBegin;
3728965ea79SLois Curfman McInnes   /*  first count number of contributors to each processor */
37313f74950SBarry Smith   ierr  = PetscMalloc(2*size*sizeof(PetscInt),&nprocs);CHKERRQ(ierr);
37413f74950SBarry Smith   ierr  = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr);
37513f74950SBarry Smith   ierr  = PetscMalloc((N+1)*sizeof(PetscInt),&owner);CHKERRQ(ierr); /* see note*/
3768965ea79SLois Curfman McInnes   for (i=0; i<N; i++) {
3778965ea79SLois Curfman McInnes     idx = rows[i];
37835d8aa7fSBarry Smith     found = PETSC_FALSE;
3798965ea79SLois Curfman McInnes     for (j=0; j<size; j++) {
3808965ea79SLois Curfman McInnes       if (idx >= owners[j] && idx < owners[j+1]) {
381c1dc657dSBarry Smith         nprocs[2*j]++; nprocs[2*j+1] = 1; owner[i] = j; found = PETSC_TRUE; break;
3828965ea79SLois Curfman McInnes       }
3838965ea79SLois Curfman McInnes     }
38429bbc08cSBarry Smith     if (!found) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Index out of range");
3858965ea79SLois Curfman McInnes   }
386c1dc657dSBarry Smith   nsends = 0;  for (i=0; i<size; i++) { nsends += nprocs[2*i+1];}
3878965ea79SLois Curfman McInnes 
3888965ea79SLois Curfman McInnes   /* inform other processors of number of messages and max length*/
389c1dc657dSBarry Smith   ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr);
3908965ea79SLois Curfman McInnes 
3918965ea79SLois Curfman McInnes   /* post receives:   */
39213f74950SBarry Smith   ierr = PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(PetscInt),&rvalues);CHKERRQ(ierr);
393b0a32e0cSBarry Smith   ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr);
3948965ea79SLois Curfman McInnes   for (i=0; i<nrecvs; i++) {
39513f74950SBarry Smith     ierr = MPI_Irecv(rvalues+nmax*i,nmax,MPIU_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr);
3968965ea79SLois Curfman McInnes   }
3978965ea79SLois Curfman McInnes 
3988965ea79SLois Curfman McInnes   /* do sends:
3998965ea79SLois Curfman McInnes       1) starts[i] gives the starting index in svalues for stuff going to
4008965ea79SLois Curfman McInnes          the ith processor
4018965ea79SLois Curfman McInnes   */
40213f74950SBarry Smith   ierr = PetscMalloc((N+1)*sizeof(PetscInt),&svalues);CHKERRQ(ierr);
403b0a32e0cSBarry Smith   ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr);
40413f74950SBarry Smith   ierr = PetscMalloc((size+1)*sizeof(PetscInt),&starts);CHKERRQ(ierr);
4058965ea79SLois Curfman McInnes   starts[0]  = 0;
406c1dc657dSBarry Smith   for (i=1; i<size; i++) { starts[i] = starts[i-1] + nprocs[2*i-2];}
4078965ea79SLois Curfman McInnes   for (i=0; i<N; i++) {
4088965ea79SLois Curfman McInnes     svalues[starts[owner[i]]++] = rows[i];
4098965ea79SLois Curfman McInnes   }
4108965ea79SLois Curfman McInnes 
4118965ea79SLois Curfman McInnes   starts[0] = 0;
412c1dc657dSBarry Smith   for (i=1; i<size+1; i++) { starts[i] = starts[i-1] + nprocs[2*i-2];}
4138965ea79SLois Curfman McInnes   count = 0;
4148965ea79SLois Curfman McInnes   for (i=0; i<size; i++) {
415c1dc657dSBarry Smith     if (nprocs[2*i+1]) {
41613f74950SBarry Smith       ierr = MPI_Isend(svalues+starts[i],nprocs[2*i],MPIU_INT,i,tag,comm,send_waits+count++);CHKERRQ(ierr);
4178965ea79SLois Curfman McInnes     }
4188965ea79SLois Curfman McInnes   }
419606d414cSSatish Balay   ierr = PetscFree(starts);CHKERRQ(ierr);
4208965ea79SLois Curfman McInnes 
4218965ea79SLois Curfman McInnes   base = owners[rank];
4228965ea79SLois Curfman McInnes 
4238965ea79SLois Curfman McInnes   /*  wait on receives */
42413f74950SBarry Smith   ierr   = PetscMalloc(2*(nrecvs+1)*sizeof(PetscInt),&lens);CHKERRQ(ierr);
4258965ea79SLois Curfman McInnes   source = lens + nrecvs;
4268965ea79SLois Curfman McInnes   count  = nrecvs; slen = 0;
4278965ea79SLois Curfman McInnes   while (count) {
428ca161407SBarry Smith     ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr);
4298965ea79SLois Curfman McInnes     /* unpack receives into our local space */
43013f74950SBarry Smith     ierr = MPI_Get_count(&recv_status,MPIU_INT,&n);CHKERRQ(ierr);
4318965ea79SLois Curfman McInnes     source[imdex]  = recv_status.MPI_SOURCE;
4328965ea79SLois Curfman McInnes     lens[imdex]    = n;
4338965ea79SLois Curfman McInnes     slen += n;
4348965ea79SLois Curfman McInnes     count--;
4358965ea79SLois Curfman McInnes   }
436606d414cSSatish Balay   ierr = PetscFree(recv_waits);CHKERRQ(ierr);
4378965ea79SLois Curfman McInnes 
4388965ea79SLois Curfman McInnes   /* move the data into the send scatter */
43913f74950SBarry Smith   ierr = PetscMalloc((slen+1)*sizeof(PetscInt),&lrows);CHKERRQ(ierr);
4408965ea79SLois Curfman McInnes   count = 0;
4418965ea79SLois Curfman McInnes   for (i=0; i<nrecvs; i++) {
4428965ea79SLois Curfman McInnes     values = rvalues + i*nmax;
4438965ea79SLois Curfman McInnes     for (j=0; j<lens[i]; j++) {
4448965ea79SLois Curfman McInnes       lrows[count++] = values[j] - base;
4458965ea79SLois Curfman McInnes     }
4468965ea79SLois Curfman McInnes   }
447606d414cSSatish Balay   ierr = PetscFree(rvalues);CHKERRQ(ierr);
448606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
449606d414cSSatish Balay   ierr = PetscFree(owner);CHKERRQ(ierr);
450606d414cSSatish Balay   ierr = PetscFree(nprocs);CHKERRQ(ierr);
4518965ea79SLois Curfman McInnes 
4528965ea79SLois Curfman McInnes   /* actually zap the local rows */
453f4df32b1SMatthew Knepley   ierr = MatZeroRows(l->A,slen,lrows,diag);CHKERRQ(ierr);
454606d414cSSatish Balay   ierr = PetscFree(lrows);CHKERRQ(ierr);
4558965ea79SLois Curfman McInnes 
4568965ea79SLois Curfman McInnes   /* wait on sends */
4578965ea79SLois Curfman McInnes   if (nsends) {
458b0a32e0cSBarry Smith     ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr);
459ca161407SBarry Smith     ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr);
460606d414cSSatish Balay     ierr = PetscFree(send_status);CHKERRQ(ierr);
4618965ea79SLois Curfman McInnes   }
462606d414cSSatish Balay   ierr = PetscFree(send_waits);CHKERRQ(ierr);
463606d414cSSatish Balay   ierr = PetscFree(svalues);CHKERRQ(ierr);
4648965ea79SLois Curfman McInnes 
4653a40ed3dSBarry Smith   PetscFunctionReturn(0);
4668965ea79SLois Curfman McInnes }
4678965ea79SLois Curfman McInnes 
4684a2ae208SSatish Balay #undef __FUNCT__
4694a2ae208SSatish Balay #define __FUNCT__ "MatMult_MPIDense"
470dfbe8321SBarry Smith PetscErrorCode MatMult_MPIDense(Mat mat,Vec xx,Vec yy)
4718965ea79SLois Curfman McInnes {
47239ddd567SLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)mat->data;
473dfbe8321SBarry Smith   PetscErrorCode ierr;
474c456f294SBarry Smith 
4753a40ed3dSBarry Smith   PetscFunctionBegin;
47643a90d84SBarry Smith   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
47743a90d84SBarry Smith   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
47844cd7ae7SLois Curfman McInnes   ierr = MatMult_SeqDense(mdn->A,mdn->lvec,yy);CHKERRQ(ierr);
4793a40ed3dSBarry Smith   PetscFunctionReturn(0);
4808965ea79SLois Curfman McInnes }
4818965ea79SLois Curfman McInnes 
4824a2ae208SSatish Balay #undef __FUNCT__
4834a2ae208SSatish Balay #define __FUNCT__ "MatMultAdd_MPIDense"
484dfbe8321SBarry Smith PetscErrorCode MatMultAdd_MPIDense(Mat mat,Vec xx,Vec yy,Vec zz)
4858965ea79SLois Curfman McInnes {
48639ddd567SLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)mat->data;
487dfbe8321SBarry Smith   PetscErrorCode ierr;
488c456f294SBarry Smith 
4893a40ed3dSBarry Smith   PetscFunctionBegin;
49043a90d84SBarry Smith   ierr = VecScatterBegin(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
49143a90d84SBarry Smith   ierr = VecScatterEnd(xx,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
49244cd7ae7SLois Curfman McInnes   ierr = MatMultAdd_SeqDense(mdn->A,mdn->lvec,yy,zz);CHKERRQ(ierr);
4933a40ed3dSBarry Smith   PetscFunctionReturn(0);
4948965ea79SLois Curfman McInnes }
4958965ea79SLois Curfman McInnes 
4964a2ae208SSatish Balay #undef __FUNCT__
4974a2ae208SSatish Balay #define __FUNCT__ "MatMultTranspose_MPIDense"
498dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_MPIDense(Mat A,Vec xx,Vec yy)
499096963f5SLois Curfman McInnes {
500096963f5SLois Curfman McInnes   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
501dfbe8321SBarry Smith   PetscErrorCode ierr;
50287828ca2SBarry Smith   PetscScalar    zero = 0.0;
503096963f5SLois Curfman McInnes 
5043a40ed3dSBarry Smith   PetscFunctionBegin;
5052dcb1b2aSMatthew Knepley   ierr = VecSet(yy,zero);CHKERRQ(ierr);
5067c922b88SBarry Smith   ierr = MatMultTranspose_SeqDense(a->A,xx,a->lvec);CHKERRQ(ierr);
507537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx);CHKERRQ(ierr);
508537820f0SBarry Smith   ierr = VecScatterEnd(a->lvec,yy,ADD_VALUES,SCATTER_REVERSE,a->Mvctx);CHKERRQ(ierr);
5093a40ed3dSBarry Smith   PetscFunctionReturn(0);
510096963f5SLois Curfman McInnes }
511096963f5SLois Curfman McInnes 
5124a2ae208SSatish Balay #undef __FUNCT__
5134a2ae208SSatish Balay #define __FUNCT__ "MatMultTransposeAdd_MPIDense"
514dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_MPIDense(Mat A,Vec xx,Vec yy,Vec zz)
515096963f5SLois Curfman McInnes {
516096963f5SLois Curfman McInnes   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
517dfbe8321SBarry Smith   PetscErrorCode ierr;
518096963f5SLois Curfman McInnes 
5193a40ed3dSBarry Smith   PetscFunctionBegin;
5203501a2bdSLois Curfman McInnes   ierr = VecCopy(yy,zz);CHKERRQ(ierr);
5217c922b88SBarry Smith   ierr = MatMultTranspose_SeqDense(a->A,xx,a->lvec);CHKERRQ(ierr);
522537820f0SBarry Smith   ierr = VecScatterBegin(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx);CHKERRQ(ierr);
523537820f0SBarry Smith   ierr = VecScatterEnd(a->lvec,zz,ADD_VALUES,SCATTER_REVERSE,a->Mvctx);CHKERRQ(ierr);
5243a40ed3dSBarry Smith   PetscFunctionReturn(0);
525096963f5SLois Curfman McInnes }
526096963f5SLois Curfman McInnes 
5274a2ae208SSatish Balay #undef __FUNCT__
5284a2ae208SSatish Balay #define __FUNCT__ "MatGetDiagonal_MPIDense"
529dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_MPIDense(Mat A,Vec v)
5308965ea79SLois Curfman McInnes {
53139ddd567SLois Curfman McInnes   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
532096963f5SLois Curfman McInnes   Mat_SeqDense   *aloc = (Mat_SeqDense*)a->A->data;
533dfbe8321SBarry Smith   PetscErrorCode ierr;
534899cda47SBarry Smith   PetscInt       len,i,n,m = A->rmap.n,radd;
53587828ca2SBarry Smith   PetscScalar    *x,zero = 0.0;
536ed3cc1f0SBarry Smith 
5373a40ed3dSBarry Smith   PetscFunctionBegin;
5382dcb1b2aSMatthew Knepley   ierr = VecSet(v,zero);CHKERRQ(ierr);
5391ebc52fbSHong Zhang   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
540096963f5SLois Curfman McInnes   ierr = VecGetSize(v,&n);CHKERRQ(ierr);
541899cda47SBarry Smith   if (n != A->rmap.N) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming mat and vec");
542899cda47SBarry Smith   len  = PetscMin(a->A->rmap.n,a->A->cmap.n);
543899cda47SBarry Smith   radd = A->rmap.rstart*m;
54444cd7ae7SLois Curfman McInnes   for (i=0; i<len; i++) {
545096963f5SLois Curfman McInnes     x[i] = aloc->v[radd + i*m + i];
546096963f5SLois Curfman McInnes   }
5471ebc52fbSHong Zhang   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
5483a40ed3dSBarry Smith   PetscFunctionReturn(0);
5498965ea79SLois Curfman McInnes }
5508965ea79SLois Curfman McInnes 
5514a2ae208SSatish Balay #undef __FUNCT__
5524a2ae208SSatish Balay #define __FUNCT__ "MatDestroy_MPIDense"
553dfbe8321SBarry Smith PetscErrorCode MatDestroy_MPIDense(Mat mat)
5548965ea79SLois Curfman McInnes {
5553501a2bdSLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)mat->data;
556dfbe8321SBarry Smith   PetscErrorCode ierr;
557ed3cc1f0SBarry Smith 
5583a40ed3dSBarry Smith   PetscFunctionBegin;
55994d884c6SBarry Smith 
560aa482453SBarry Smith #if defined(PETSC_USE_LOG)
561899cda47SBarry Smith   PetscLogObjectState((PetscObject)mat,"Rows=%D, Cols=%D",mat->rmap.N,mat->cmap.N);
5628965ea79SLois Curfman McInnes #endif
5638798bf22SSatish Balay   ierr = MatStashDestroy_Private(&mat->stash);CHKERRQ(ierr);
5643501a2bdSLois Curfman McInnes   ierr = MatDestroy(mdn->A);CHKERRQ(ierr);
56505b42c5fSBarry Smith   if (mdn->lvec)   {ierr = VecDestroy(mdn->lvec);CHKERRQ(ierr);}
56605b42c5fSBarry Smith   if (mdn->Mvctx)  {ierr = VecScatterDestroy(mdn->Mvctx);CHKERRQ(ierr);}
567622d7880SLois Curfman McInnes   if (mdn->factor) {
56805b42c5fSBarry Smith     ierr = PetscFree(mdn->factor->temp);CHKERRQ(ierr);
56905b42c5fSBarry Smith     ierr = PetscFree(mdn->factor->tag);CHKERRQ(ierr);
57005b42c5fSBarry Smith     ierr = PetscFree(mdn->factor->pivots);CHKERRQ(ierr);
571606d414cSSatish Balay     ierr = PetscFree(mdn->factor);CHKERRQ(ierr);
572622d7880SLois Curfman McInnes   }
573606d414cSSatish Balay   ierr = PetscFree(mdn);CHKERRQ(ierr);
574dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)mat,0);CHKERRQ(ierr);
575901853e0SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatGetDiagonalBlock_C","",PETSC_NULL);CHKERRQ(ierr);
576901853e0SKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatMPIDenseSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr);
5774ae313f4SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMult_mpiaij_mpidense_C","",PETSC_NULL);CHKERRQ(ierr);
5784ae313f4SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMultSymbolic_mpiaij_mpidense_C","",PETSC_NULL);CHKERRQ(ierr);
5794ae313f4SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMultNumeric_mpiaij_mpidense_C","",PETSC_NULL);CHKERRQ(ierr);
5803a40ed3dSBarry Smith   PetscFunctionReturn(0);
5818965ea79SLois Curfman McInnes }
58239ddd567SLois Curfman McInnes 
5834a2ae208SSatish Balay #undef __FUNCT__
5844a2ae208SSatish Balay #define __FUNCT__ "MatView_MPIDense_Binary"
5856849ba73SBarry Smith static PetscErrorCode MatView_MPIDense_Binary(Mat mat,PetscViewer viewer)
5868965ea79SLois Curfman McInnes {
58739ddd567SLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)mat->data;
588dfbe8321SBarry Smith   PetscErrorCode ierr;
5897056b6fcSBarry Smith 
5903a40ed3dSBarry Smith   PetscFunctionBegin;
59139ddd567SLois Curfman McInnes   if (mdn->size == 1) {
59239ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer);CHKERRQ(ierr);
5938965ea79SLois Curfman McInnes   }
59429bbc08cSBarry Smith   else SETERRQ(PETSC_ERR_SUP,"Only uniprocessor output supported");
5953a40ed3dSBarry Smith   PetscFunctionReturn(0);
5968965ea79SLois Curfman McInnes }
5978965ea79SLois Curfman McInnes 
5984a2ae208SSatish Balay #undef __FUNCT__
5994a2ae208SSatish Balay #define __FUNCT__ "MatView_MPIDense_ASCIIorDraworSocket"
6006849ba73SBarry Smith static PetscErrorCode MatView_MPIDense_ASCIIorDraworSocket(Mat mat,PetscViewer viewer)
6018965ea79SLois Curfman McInnes {
60239ddd567SLois Curfman McInnes   Mat_MPIDense      *mdn = (Mat_MPIDense*)mat->data;
603dfbe8321SBarry Smith   PetscErrorCode    ierr;
60432dcc486SBarry Smith   PetscMPIInt       size = mdn->size,rank = mdn->rank;
605b0a32e0cSBarry Smith   PetscViewerType   vtype;
60632077d6dSBarry Smith   PetscTruth        iascii,isdraw;
607b0a32e0cSBarry Smith   PetscViewer       sviewer;
608f3ef73ceSBarry Smith   PetscViewerFormat format;
6098965ea79SLois Curfman McInnes 
6103a40ed3dSBarry Smith   PetscFunctionBegin;
61132077d6dSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
612fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
61332077d6dSBarry Smith   if (iascii) {
614b0a32e0cSBarry Smith     ierr = PetscViewerGetType(viewer,&vtype);CHKERRQ(ierr);
615b0a32e0cSBarry Smith     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
616456192e2SBarry Smith     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
6174e220ebcSLois Curfman McInnes       MatInfo info;
618888f2ed8SSatish Balay       ierr = MatGetInfo(mat,MAT_LOCAL,&info);CHKERRQ(ierr);
619899cda47SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"  [%d] local rows %D nz %D nz alloced %D mem %D \n",rank,mat->rmap.n,
62077431f27SBarry Smith                    (PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr);
621b0a32e0cSBarry Smith       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
6223501a2bdSLois Curfman McInnes       ierr = VecScatterView(mdn->Mvctx,viewer);CHKERRQ(ierr);
6233a40ed3dSBarry Smith       PetscFunctionReturn(0);
624fb9695e5SSatish Balay     } else if (format == PETSC_VIEWER_ASCII_INFO) {
6253a40ed3dSBarry Smith       PetscFunctionReturn(0);
6268965ea79SLois Curfman McInnes     }
627f1af5d2fSBarry Smith   } else if (isdraw) {
628b0a32e0cSBarry Smith     PetscDraw  draw;
629f1af5d2fSBarry Smith     PetscTruth isnull;
630f1af5d2fSBarry Smith 
631b0a32e0cSBarry Smith     ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
632b0a32e0cSBarry Smith     ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
633f1af5d2fSBarry Smith     if (isnull) PetscFunctionReturn(0);
634f1af5d2fSBarry Smith   }
63577ed5343SBarry Smith 
6368965ea79SLois Curfman McInnes   if (size == 1) {
63739ddd567SLois Curfman McInnes     ierr = MatView(mdn->A,viewer);CHKERRQ(ierr);
6383a40ed3dSBarry Smith   } else {
6398965ea79SLois Curfman McInnes     /* assemble the entire matrix onto first processor. */
6408965ea79SLois Curfman McInnes     Mat         A;
641899cda47SBarry Smith     PetscInt    M = mat->rmap.N,N = mat->cmap.N,m,row,i,nz;
642ba8c8a56SBarry Smith     PetscInt    *cols;
643ba8c8a56SBarry Smith     PetscScalar *vals;
6448965ea79SLois Curfman McInnes 
645f69a0ea3SMatthew Knepley     ierr = MatCreate(mat->comm,&A);CHKERRQ(ierr);
6468965ea79SLois Curfman McInnes     if (!rank) {
647f69a0ea3SMatthew Knepley       ierr = MatSetSizes(A,M,N,M,N);CHKERRQ(ierr);
6483a40ed3dSBarry Smith     } else {
649f69a0ea3SMatthew Knepley       ierr = MatSetSizes(A,0,0,M,N);CHKERRQ(ierr);
6508965ea79SLois Curfman McInnes     }
651be5d1d56SKris Buschelman     /* Since this is a temporary matrix, MATMPIDENSE instead of A->type_name here is probably acceptable. */
652878740d9SKris Buschelman     ierr = MatSetType(A,MATMPIDENSE);CHKERRQ(ierr);
653878740d9SKris Buschelman     ierr = MatMPIDenseSetPreallocation(A,PETSC_NULL);
65452e6d16bSBarry Smith     ierr = PetscLogObjectParent(mat,A);CHKERRQ(ierr);
6558965ea79SLois Curfman McInnes 
65639ddd567SLois Curfman McInnes     /* Copy the matrix ... This isn't the most efficient means,
65739ddd567SLois Curfman McInnes        but it's quick for now */
65851022da4SBarry Smith     A->insertmode = INSERT_VALUES;
659899cda47SBarry Smith     row = mat->rmap.rstart; m = mdn->A->rmap.n;
6608965ea79SLois Curfman McInnes     for (i=0; i<m; i++) {
661ba8c8a56SBarry Smith       ierr = MatGetRow_MPIDense(mat,row,&nz,&cols,&vals);CHKERRQ(ierr);
662ba8c8a56SBarry Smith       ierr = MatSetValues_MPIDense(A,1,&row,nz,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
663ba8c8a56SBarry Smith       ierr = MatRestoreRow_MPIDense(mat,row,&nz,&cols,&vals);CHKERRQ(ierr);
66439ddd567SLois Curfman McInnes       row++;
6658965ea79SLois Curfman McInnes     }
6668965ea79SLois Curfman McInnes 
6676d4a8577SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6686d4a8577SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
669b0a32e0cSBarry Smith     ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr);
670b9b97703SBarry Smith     if (!rank) {
6716831982aSBarry Smith       ierr = MatView(((Mat_MPIDense*)(A->data))->A,sviewer);CHKERRQ(ierr);
6728965ea79SLois Curfman McInnes     }
673b0a32e0cSBarry Smith     ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr);
674b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
6758965ea79SLois Curfman McInnes     ierr = MatDestroy(A);CHKERRQ(ierr);
6768965ea79SLois Curfman McInnes   }
6773a40ed3dSBarry Smith   PetscFunctionReturn(0);
6788965ea79SLois Curfman McInnes }
6798965ea79SLois Curfman McInnes 
6804a2ae208SSatish Balay #undef __FUNCT__
6814a2ae208SSatish Balay #define __FUNCT__ "MatView_MPIDense"
682dfbe8321SBarry Smith PetscErrorCode MatView_MPIDense(Mat mat,PetscViewer viewer)
6838965ea79SLois Curfman McInnes {
684dfbe8321SBarry Smith   PetscErrorCode ierr;
68532077d6dSBarry Smith   PetscTruth     iascii,isbinary,isdraw,issocket;
6868965ea79SLois Curfman McInnes 
687433994e6SBarry Smith   PetscFunctionBegin;
6880f5bd95cSBarry Smith 
68932077d6dSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
690fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);CHKERRQ(ierr);
691b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);CHKERRQ(ierr);
692fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
6930f5bd95cSBarry Smith 
69432077d6dSBarry Smith   if (iascii || issocket || isdraw) {
695f1af5d2fSBarry Smith     ierr = MatView_MPIDense_ASCIIorDraworSocket(mat,viewer);CHKERRQ(ierr);
6960f5bd95cSBarry Smith   } else if (isbinary) {
6973a40ed3dSBarry Smith     ierr = MatView_MPIDense_Binary(mat,viewer);CHKERRQ(ierr);
6985cd90555SBarry Smith   } else {
699958c9bccSBarry Smith     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by MPI dense matrix",((PetscObject)viewer)->type_name);
7008965ea79SLois Curfman McInnes   }
7013a40ed3dSBarry Smith   PetscFunctionReturn(0);
7028965ea79SLois Curfman McInnes }
7038965ea79SLois Curfman McInnes 
7044a2ae208SSatish Balay #undef __FUNCT__
7054a2ae208SSatish Balay #define __FUNCT__ "MatGetInfo_MPIDense"
706dfbe8321SBarry Smith PetscErrorCode MatGetInfo_MPIDense(Mat A,MatInfoType flag,MatInfo *info)
7078965ea79SLois Curfman McInnes {
7083501a2bdSLois Curfman McInnes   Mat_MPIDense   *mat = (Mat_MPIDense*)A->data;
7093501a2bdSLois Curfman McInnes   Mat            mdn = mat->A;
710dfbe8321SBarry Smith   PetscErrorCode ierr;
711329f5518SBarry Smith   PetscReal      isend[5],irecv[5];
7128965ea79SLois Curfman McInnes 
7133a40ed3dSBarry Smith   PetscFunctionBegin;
714899cda47SBarry Smith   info->rows_global    = (double)A->rmap.N;
715899cda47SBarry Smith   info->columns_global = (double)A->cmap.N;
716899cda47SBarry Smith   info->rows_local     = (double)A->rmap.n;
717899cda47SBarry Smith   info->columns_local  = (double)A->cmap.N;
7184e220ebcSLois Curfman McInnes   info->block_size     = 1.0;
7194e220ebcSLois Curfman McInnes   ierr = MatGetInfo(mdn,MAT_LOCAL,info);CHKERRQ(ierr);
7204e220ebcSLois Curfman McInnes   isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded;
7214e220ebcSLois Curfman McInnes   isend[3] = info->memory;  isend[4] = info->mallocs;
7228965ea79SLois Curfman McInnes   if (flag == MAT_LOCAL) {
7234e220ebcSLois Curfman McInnes     info->nz_used      = isend[0];
7244e220ebcSLois Curfman McInnes     info->nz_allocated = isend[1];
7254e220ebcSLois Curfman McInnes     info->nz_unneeded  = isend[2];
7264e220ebcSLois Curfman McInnes     info->memory       = isend[3];
7274e220ebcSLois Curfman McInnes     info->mallocs      = isend[4];
7288965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_MAX) {
729d7d1e502SBarry Smith     ierr = MPI_Allreduce(isend,irecv,5,MPIU_REAL,MPI_MAX,A->comm);CHKERRQ(ierr);
7304e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
7314e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
7324e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
7334e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
7344e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
7358965ea79SLois Curfman McInnes   } else if (flag == MAT_GLOBAL_SUM) {
736d7d1e502SBarry Smith     ierr = MPI_Allreduce(isend,irecv,5,MPIU_REAL,MPI_SUM,A->comm);CHKERRQ(ierr);
7374e220ebcSLois Curfman McInnes     info->nz_used      = irecv[0];
7384e220ebcSLois Curfman McInnes     info->nz_allocated = irecv[1];
7394e220ebcSLois Curfman McInnes     info->nz_unneeded  = irecv[2];
7404e220ebcSLois Curfman McInnes     info->memory       = irecv[3];
7414e220ebcSLois Curfman McInnes     info->mallocs      = irecv[4];
7428965ea79SLois Curfman McInnes   }
7434e220ebcSLois Curfman McInnes   info->fill_ratio_given  = 0; /* no parallel LU/ILU/Cholesky */
7444e220ebcSLois Curfman McInnes   info->fill_ratio_needed = 0;
7454e220ebcSLois Curfman McInnes   info->factor_mallocs    = 0;
7463a40ed3dSBarry Smith   PetscFunctionReturn(0);
7478965ea79SLois Curfman McInnes }
7488965ea79SLois Curfman McInnes 
7494a2ae208SSatish Balay #undef __FUNCT__
7504a2ae208SSatish Balay #define __FUNCT__ "MatSetOption_MPIDense"
751dfbe8321SBarry Smith PetscErrorCode MatSetOption_MPIDense(Mat A,MatOption op)
7528965ea79SLois Curfman McInnes {
75339ddd567SLois Curfman McInnes   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
754dfbe8321SBarry Smith   PetscErrorCode ierr;
7558965ea79SLois Curfman McInnes 
7563a40ed3dSBarry Smith   PetscFunctionBegin;
75712c028f9SKris Buschelman   switch (op) {
75812c028f9SKris Buschelman   case MAT_NO_NEW_NONZERO_LOCATIONS:
75912c028f9SKris Buschelman   case MAT_YES_NEW_NONZERO_LOCATIONS:
76012c028f9SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
76112c028f9SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
76212c028f9SKris Buschelman   case MAT_COLUMNS_SORTED:
76312c028f9SKris Buschelman   case MAT_COLUMNS_UNSORTED:
764273d9f13SBarry Smith     ierr = MatSetOption(a->A,op);CHKERRQ(ierr);
76512c028f9SKris Buschelman     break;
76612c028f9SKris Buschelman   case MAT_ROW_ORIENTED:
767273d9f13SBarry Smith     a->roworiented = PETSC_TRUE;
768273d9f13SBarry Smith     ierr = MatSetOption(a->A,op);CHKERRQ(ierr);
76912c028f9SKris Buschelman     break;
77012c028f9SKris Buschelman   case MAT_ROWS_SORTED:
77112c028f9SKris Buschelman   case MAT_ROWS_UNSORTED:
77212c028f9SKris Buschelman   case MAT_YES_NEW_DIAGONALS:
77312c028f9SKris Buschelman   case MAT_USE_HASH_TABLE:
774290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
77512c028f9SKris Buschelman     break;
77612c028f9SKris Buschelman   case MAT_COLUMN_ORIENTED:
777273d9f13SBarry Smith     a->roworiented = PETSC_FALSE;
778273d9f13SBarry Smith     ierr = MatSetOption(a->A,op);CHKERRQ(ierr);
77912c028f9SKris Buschelman     break;
78012c028f9SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
781273d9f13SBarry Smith     a->donotstash = PETSC_TRUE;
78212c028f9SKris Buschelman     break;
78312c028f9SKris Buschelman   case MAT_NO_NEW_DIAGONALS:
78429bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"MAT_NO_NEW_DIAGONALS");
78577e54ba9SKris Buschelman   case MAT_SYMMETRIC:
78677e54ba9SKris Buschelman   case MAT_STRUCTURALLY_SYMMETRIC:
7879a4540c5SBarry Smith   case MAT_NOT_SYMMETRIC:
7889a4540c5SBarry Smith   case MAT_NOT_STRUCTURALLY_SYMMETRIC:
7899a4540c5SBarry Smith   case MAT_HERMITIAN:
7909a4540c5SBarry Smith   case MAT_NOT_HERMITIAN:
7919a4540c5SBarry Smith   case MAT_SYMMETRY_ETERNAL:
7929a4540c5SBarry Smith   case MAT_NOT_SYMMETRY_ETERNAL:
793290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
79477e54ba9SKris Buschelman     break;
79512c028f9SKris Buschelman   default:
796ad86a440SBarry Smith     SETERRQ1(PETSC_ERR_SUP,"unknown option %d",op);
7973a40ed3dSBarry Smith   }
7983a40ed3dSBarry Smith   PetscFunctionReturn(0);
7998965ea79SLois Curfman McInnes }
8008965ea79SLois Curfman McInnes 
8018965ea79SLois Curfman McInnes 
8024a2ae208SSatish Balay #undef __FUNCT__
8034a2ae208SSatish Balay #define __FUNCT__ "MatDiagonalScale_MPIDense"
804dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_MPIDense(Mat A,Vec ll,Vec rr)
8055b2fa520SLois Curfman McInnes {
8065b2fa520SLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)A->data;
8075b2fa520SLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense*)mdn->A->data;
80887828ca2SBarry Smith   PetscScalar    *l,*r,x,*v;
809dfbe8321SBarry Smith   PetscErrorCode ierr;
810899cda47SBarry Smith   PetscInt       i,j,s2a,s3a,s2,s3,m=mdn->A->rmap.n,n=mdn->A->cmap.n;
8115b2fa520SLois Curfman McInnes 
8125b2fa520SLois Curfman McInnes   PetscFunctionBegin;
81372d926a5SLois Curfman McInnes   ierr = MatGetLocalSize(A,&s2,&s3);CHKERRQ(ierr);
8145b2fa520SLois Curfman McInnes   if (ll) {
81572d926a5SLois Curfman McInnes     ierr = VecGetLocalSize(ll,&s2a);CHKERRQ(ierr);
816175be7b4SMatthew Knepley     if (s2a != s2) SETERRQ2(PETSC_ERR_ARG_SIZ,"Left scaling vector non-conforming local size, %d != %d.", s2a, s2);
8171ebc52fbSHong Zhang     ierr = VecGetArray(ll,&l);CHKERRQ(ierr);
8185b2fa520SLois Curfman McInnes     for (i=0; i<m; i++) {
8195b2fa520SLois Curfman McInnes       x = l[i];
8205b2fa520SLois Curfman McInnes       v = mat->v + i;
8215b2fa520SLois Curfman McInnes       for (j=0; j<n; j++) { (*v) *= x; v+= m;}
8225b2fa520SLois Curfman McInnes     }
8231ebc52fbSHong Zhang     ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr);
824efee365bSSatish Balay     ierr = PetscLogFlops(n*m);CHKERRQ(ierr);
8255b2fa520SLois Curfman McInnes   }
8265b2fa520SLois Curfman McInnes   if (rr) {
827175be7b4SMatthew Knepley     ierr = VecGetLocalSize(rr,&s3a);CHKERRQ(ierr);
828175be7b4SMatthew Knepley     if (s3a != s3) SETERRQ2(PETSC_ERR_ARG_SIZ,"Right scaling vec non-conforming local size, %d != %d.", s3a, s3);
8295b2fa520SLois Curfman McInnes     ierr = VecScatterBegin(rr,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
8305b2fa520SLois Curfman McInnes     ierr = VecScatterEnd(rr,mdn->lvec,INSERT_VALUES,SCATTER_FORWARD,mdn->Mvctx);CHKERRQ(ierr);
8311ebc52fbSHong Zhang     ierr = VecGetArray(mdn->lvec,&r);CHKERRQ(ierr);
8325b2fa520SLois Curfman McInnes     for (i=0; i<n; i++) {
8335b2fa520SLois Curfman McInnes       x = r[i];
8345b2fa520SLois Curfman McInnes       v = mat->v + i*m;
8355b2fa520SLois Curfman McInnes       for (j=0; j<m; j++) { (*v++) *= x;}
8365b2fa520SLois Curfman McInnes     }
8371ebc52fbSHong Zhang     ierr = VecRestoreArray(mdn->lvec,&r);CHKERRQ(ierr);
838efee365bSSatish Balay     ierr = PetscLogFlops(n*m);CHKERRQ(ierr);
8395b2fa520SLois Curfman McInnes   }
8405b2fa520SLois Curfman McInnes   PetscFunctionReturn(0);
8415b2fa520SLois Curfman McInnes }
8425b2fa520SLois Curfman McInnes 
8434a2ae208SSatish Balay #undef __FUNCT__
8444a2ae208SSatish Balay #define __FUNCT__ "MatNorm_MPIDense"
845dfbe8321SBarry Smith PetscErrorCode MatNorm_MPIDense(Mat A,NormType type,PetscReal *nrm)
846096963f5SLois Curfman McInnes {
8473501a2bdSLois Curfman McInnes   Mat_MPIDense   *mdn = (Mat_MPIDense*)A->data;
8483501a2bdSLois Curfman McInnes   Mat_SeqDense   *mat = (Mat_SeqDense*)mdn->A->data;
849dfbe8321SBarry Smith   PetscErrorCode ierr;
85013f74950SBarry Smith   PetscInt       i,j;
851329f5518SBarry Smith   PetscReal      sum = 0.0;
85287828ca2SBarry Smith   PetscScalar    *v = mat->v;
8533501a2bdSLois Curfman McInnes 
8543a40ed3dSBarry Smith   PetscFunctionBegin;
8553501a2bdSLois Curfman McInnes   if (mdn->size == 1) {
856064f8208SBarry Smith     ierr =  MatNorm(mdn->A,type,nrm);CHKERRQ(ierr);
8573501a2bdSLois Curfman McInnes   } else {
8583501a2bdSLois Curfman McInnes     if (type == NORM_FROBENIUS) {
859899cda47SBarry Smith       for (i=0; i<mdn->A->cmap.n*mdn->A->rmap.n; i++) {
860aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
861329f5518SBarry Smith         sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
8623501a2bdSLois Curfman McInnes #else
8633501a2bdSLois Curfman McInnes         sum += (*v)*(*v); v++;
8643501a2bdSLois Curfman McInnes #endif
8653501a2bdSLois Curfman McInnes       }
866064f8208SBarry Smith       ierr = MPI_Allreduce(&sum,nrm,1,MPIU_REAL,MPI_SUM,A->comm);CHKERRQ(ierr);
867064f8208SBarry Smith       *nrm = sqrt(*nrm);
868899cda47SBarry Smith       ierr = PetscLogFlops(2*mdn->A->cmap.n*mdn->A->rmap.n);CHKERRQ(ierr);
8693a40ed3dSBarry Smith     } else if (type == NORM_1) {
870329f5518SBarry Smith       PetscReal *tmp,*tmp2;
871899cda47SBarry Smith       ierr = PetscMalloc(2*A->cmap.N*sizeof(PetscReal),&tmp);CHKERRQ(ierr);
872899cda47SBarry Smith       tmp2 = tmp + A->cmap.N;
873899cda47SBarry Smith       ierr = PetscMemzero(tmp,2*A->cmap.N*sizeof(PetscReal));CHKERRQ(ierr);
874064f8208SBarry Smith       *nrm = 0.0;
8753501a2bdSLois Curfman McInnes       v = mat->v;
876899cda47SBarry Smith       for (j=0; j<mdn->A->cmap.n; j++) {
877899cda47SBarry Smith         for (i=0; i<mdn->A->rmap.n; i++) {
87867e560aaSBarry Smith           tmp[j] += PetscAbsScalar(*v);  v++;
8793501a2bdSLois Curfman McInnes         }
8803501a2bdSLois Curfman McInnes       }
881899cda47SBarry Smith       ierr = MPI_Allreduce(tmp,tmp2,A->cmap.N,MPIU_REAL,MPI_SUM,A->comm);CHKERRQ(ierr);
882899cda47SBarry Smith       for (j=0; j<A->cmap.N; j++) {
883064f8208SBarry Smith         if (tmp2[j] > *nrm) *nrm = tmp2[j];
8843501a2bdSLois Curfman McInnes       }
885606d414cSSatish Balay       ierr = PetscFree(tmp);CHKERRQ(ierr);
886899cda47SBarry Smith       ierr = PetscLogFlops(A->cmap.n*A->rmap.n);CHKERRQ(ierr);
8873a40ed3dSBarry Smith     } else if (type == NORM_INFINITY) { /* max row norm */
888329f5518SBarry Smith       PetscReal ntemp;
8893501a2bdSLois Curfman McInnes       ierr = MatNorm(mdn->A,type,&ntemp);CHKERRQ(ierr);
890064f8208SBarry Smith       ierr = MPI_Allreduce(&ntemp,nrm,1,MPIU_REAL,MPI_MAX,A->comm);CHKERRQ(ierr);
8913a40ed3dSBarry Smith     } else {
89229bbc08cSBarry Smith       SETERRQ(PETSC_ERR_SUP,"No support for two norm");
8933501a2bdSLois Curfman McInnes     }
8943501a2bdSLois Curfman McInnes   }
8953a40ed3dSBarry Smith   PetscFunctionReturn(0);
8963501a2bdSLois Curfman McInnes }
8973501a2bdSLois Curfman McInnes 
8984a2ae208SSatish Balay #undef __FUNCT__
8994a2ae208SSatish Balay #define __FUNCT__ "MatTranspose_MPIDense"
900dfbe8321SBarry Smith PetscErrorCode MatTranspose_MPIDense(Mat A,Mat *matout)
9013501a2bdSLois Curfman McInnes {
9023501a2bdSLois Curfman McInnes   Mat_MPIDense   *a = (Mat_MPIDense*)A->data;
9033501a2bdSLois Curfman McInnes   Mat_SeqDense   *Aloc = (Mat_SeqDense*)a->A->data;
9043501a2bdSLois Curfman McInnes   Mat            B;
905899cda47SBarry Smith   PetscInt       M = A->rmap.N,N = A->cmap.N,m,n,*rwork,rstart = A->rmap.rstart;
9066849ba73SBarry Smith   PetscErrorCode ierr;
90713f74950SBarry Smith   PetscInt       j,i;
90887828ca2SBarry Smith   PetscScalar    *v;
9093501a2bdSLois Curfman McInnes 
9103a40ed3dSBarry Smith   PetscFunctionBegin;
9117c922b88SBarry Smith   if (!matout && M != N) {
91229bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"Supports square matrix only in-place");
9137056b6fcSBarry Smith   }
914f69a0ea3SMatthew Knepley   ierr = MatCreate(A->comm,&B);CHKERRQ(ierr);
915f69a0ea3SMatthew Knepley   ierr = MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,N,M);CHKERRQ(ierr);
916878740d9SKris Buschelman   ierr = MatSetType(B,A->type_name);CHKERRQ(ierr);
917878740d9SKris Buschelman   ierr = MatMPIDenseSetPreallocation(B,PETSC_NULL);CHKERRQ(ierr);
9183501a2bdSLois Curfman McInnes 
919899cda47SBarry Smith   m = a->A->rmap.n; n = a->A->cmap.n; v = Aloc->v;
92013f74950SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&rwork);CHKERRQ(ierr);
9213501a2bdSLois Curfman McInnes   for (j=0; j<n; j++) {
9223501a2bdSLois Curfman McInnes     for (i=0; i<m; i++) rwork[i] = rstart + i;
9233501a2bdSLois Curfman McInnes     ierr = MatSetValues(B,1,&j,m,rwork,v,INSERT_VALUES);CHKERRQ(ierr);
9243501a2bdSLois Curfman McInnes     v   += m;
9253501a2bdSLois Curfman McInnes   }
926606d414cSSatish Balay   ierr = PetscFree(rwork);CHKERRQ(ierr);
9276d4a8577SBarry Smith   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9286d4a8577SBarry Smith   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9297c922b88SBarry Smith   if (matout) {
9303501a2bdSLois Curfman McInnes     *matout = B;
9313501a2bdSLois Curfman McInnes   } else {
932273d9f13SBarry Smith     ierr = MatHeaderCopy(A,B);CHKERRQ(ierr);
9333501a2bdSLois Curfman McInnes   }
9343a40ed3dSBarry Smith   PetscFunctionReturn(0);
935096963f5SLois Curfman McInnes }
936096963f5SLois Curfman McInnes 
937d9eff348SSatish Balay #include "petscblaslapack.h"
9384a2ae208SSatish Balay #undef __FUNCT__
9394a2ae208SSatish Balay #define __FUNCT__ "MatScale_MPIDense"
940f4df32b1SMatthew Knepley PetscErrorCode MatScale_MPIDense(Mat inA,PetscScalar alpha)
94144cd7ae7SLois Curfman McInnes {
94244cd7ae7SLois Curfman McInnes   Mat_MPIDense   *A = (Mat_MPIDense*)inA->data;
94344cd7ae7SLois Curfman McInnes   Mat_SeqDense   *a = (Mat_SeqDense*)A->A->data;
944f4df32b1SMatthew Knepley   PetscScalar    oalpha = alpha;
945899cda47SBarry Smith   PetscBLASInt   one = 1,nz = (PetscBLASInt)inA->rmap.n*inA->cmap.N;
946efee365bSSatish Balay   PetscErrorCode ierr;
94744cd7ae7SLois Curfman McInnes 
9483a40ed3dSBarry Smith   PetscFunctionBegin;
949f4df32b1SMatthew Knepley   BLASscal_(&nz,&oalpha,a->v,&one);
950efee365bSSatish Balay   ierr = PetscLogFlops(nz);CHKERRQ(ierr);
9513a40ed3dSBarry Smith   PetscFunctionReturn(0);
95244cd7ae7SLois Curfman McInnes }
95344cd7ae7SLois Curfman McInnes 
9546849ba73SBarry Smith static PetscErrorCode MatDuplicate_MPIDense(Mat,MatDuplicateOption,Mat *);
9558965ea79SLois Curfman McInnes 
9564a2ae208SSatish Balay #undef __FUNCT__
9574a2ae208SSatish Balay #define __FUNCT__ "MatSetUpPreallocation_MPIDense"
958dfbe8321SBarry Smith PetscErrorCode MatSetUpPreallocation_MPIDense(Mat A)
959273d9f13SBarry Smith {
960dfbe8321SBarry Smith   PetscErrorCode ierr;
961273d9f13SBarry Smith 
962273d9f13SBarry Smith   PetscFunctionBegin;
963273d9f13SBarry Smith   ierr =  MatMPIDenseSetPreallocation(A,0);CHKERRQ(ierr);
964273d9f13SBarry Smith   PetscFunctionReturn(0);
965273d9f13SBarry Smith }
966273d9f13SBarry Smith 
9674ae313f4SHong Zhang #undef __FUNCT__
9684ae313f4SHong Zhang #define __FUNCT__ "MatMatMultSymbolic_MPIDense_MPIDense"
9694ae313f4SHong Zhang PetscErrorCode MatMatMultSymbolic_MPIDense_MPIDense(Mat A,Mat B,PetscReal fill,Mat *C)
9704ae313f4SHong Zhang {
9714ae313f4SHong Zhang   PetscErrorCode ierr;
9724ae313f4SHong Zhang   PetscInt       m=A->rmap.n,n=B->cmap.n;
9734ae313f4SHong Zhang   Mat            Cmat;
9744ae313f4SHong Zhang 
9754ae313f4SHong Zhang   PetscFunctionBegin;
9764ae313f4SHong Zhang   if (A->cmap.n != B->rmap.n) SETERRQ2(PETSC_ERR_ARG_SIZ,"A->cmap.n %d != B->rmap.n %d\n",A->cmap.n,B->rmap.n);
9774ae313f4SHong Zhang   ierr = MatCreate(B->comm,&Cmat);CHKERRQ(ierr);
9784ae313f4SHong Zhang   ierr = MatSetSizes(Cmat,m,n,A->rmap.N,B->cmap.N);CHKERRQ(ierr);
9794ae313f4SHong Zhang   ierr = MatSetType(Cmat,MATMPIDENSE);CHKERRQ(ierr);
9804ae313f4SHong Zhang   ierr = MatMPIDenseSetPreallocation(Cmat,PETSC_NULL);CHKERRQ(ierr);
9812a6744ebSBarry Smith   ierr = MatAssemblyBegin(Cmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9820a71e23eSMatthew Knepley   ierr = MatAssemblyEnd(Cmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9834ae313f4SHong Zhang   *C = Cmat;
9844ae313f4SHong Zhang   PetscFunctionReturn(0);
9854ae313f4SHong Zhang }
9864ae313f4SHong Zhang 
9878965ea79SLois Curfman McInnes /* -------------------------------------------------------------------*/
98809dc0095SBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_MPIDense,
98909dc0095SBarry Smith        MatGetRow_MPIDense,
99009dc0095SBarry Smith        MatRestoreRow_MPIDense,
99109dc0095SBarry Smith        MatMult_MPIDense,
99297304618SKris Buschelman /* 4*/ MatMultAdd_MPIDense,
9937c922b88SBarry Smith        MatMultTranspose_MPIDense,
9947c922b88SBarry Smith        MatMultTransposeAdd_MPIDense,
9958965ea79SLois Curfman McInnes        0,
99609dc0095SBarry Smith        0,
99709dc0095SBarry Smith        0,
99897304618SKris Buschelman /*10*/ 0,
99909dc0095SBarry Smith        0,
100009dc0095SBarry Smith        0,
100109dc0095SBarry Smith        0,
100209dc0095SBarry Smith        MatTranspose_MPIDense,
100397304618SKris Buschelman /*15*/ MatGetInfo_MPIDense,
10046e4ee0c6SHong Zhang        MatEqual_MPIDense,
100509dc0095SBarry Smith        MatGetDiagonal_MPIDense,
10065b2fa520SLois Curfman McInnes        MatDiagonalScale_MPIDense,
100709dc0095SBarry Smith        MatNorm_MPIDense,
100897304618SKris Buschelman /*20*/ MatAssemblyBegin_MPIDense,
100909dc0095SBarry Smith        MatAssemblyEnd_MPIDense,
101009dc0095SBarry Smith        0,
101109dc0095SBarry Smith        MatSetOption_MPIDense,
101209dc0095SBarry Smith        MatZeroEntries_MPIDense,
101397304618SKris Buschelman /*25*/ MatZeroRows_MPIDense,
10140ad19415SHong Zhang        MatLUFactorSymbolic_MPIDense,
1015919b68f7SBarry Smith        0,
10160ad19415SHong Zhang        MatCholeskyFactorSymbolic_MPIDense,
1017919b68f7SBarry Smith        0,
101897304618SKris Buschelman /*30*/ MatSetUpPreallocation_MPIDense,
1019273d9f13SBarry Smith        0,
102009dc0095SBarry Smith        0,
102109dc0095SBarry Smith        MatGetArray_MPIDense,
102209dc0095SBarry Smith        MatRestoreArray_MPIDense,
102397304618SKris Buschelman /*35*/ MatDuplicate_MPIDense,
102409dc0095SBarry Smith        0,
102509dc0095SBarry Smith        0,
102609dc0095SBarry Smith        0,
102709dc0095SBarry Smith        0,
102897304618SKris Buschelman /*40*/ 0,
10292ce60cd0SSatish Balay        MatGetSubMatrices_MPIDense,
103009dc0095SBarry Smith        0,
103109dc0095SBarry Smith        MatGetValues_MPIDense,
103209dc0095SBarry Smith        0,
103397304618SKris Buschelman /*45*/ 0,
103409dc0095SBarry Smith        MatScale_MPIDense,
103509dc0095SBarry Smith        0,
103609dc0095SBarry Smith        0,
103709dc0095SBarry Smith        0,
1038521d7252SBarry Smith /*50*/ 0,
103909dc0095SBarry Smith        0,
104009dc0095SBarry Smith        0,
104109dc0095SBarry Smith        0,
104209dc0095SBarry Smith        0,
104397304618SKris Buschelman /*55*/ 0,
104409dc0095SBarry Smith        0,
104509dc0095SBarry Smith        0,
104609dc0095SBarry Smith        0,
104709dc0095SBarry Smith        0,
104897304618SKris Buschelman /*60*/ MatGetSubMatrix_MPIDense,
1049b9b97703SBarry Smith        MatDestroy_MPIDense,
1050b9b97703SBarry Smith        MatView_MPIDense,
1051357abbc8SBarry Smith        0,
105297304618SKris Buschelman        0,
105397304618SKris Buschelman /*65*/ 0,
105497304618SKris Buschelman        0,
105597304618SKris Buschelman        0,
105697304618SKris Buschelman        0,
105797304618SKris Buschelman        0,
105897304618SKris Buschelman /*70*/ 0,
105997304618SKris Buschelman        0,
106097304618SKris Buschelman        0,
106197304618SKris Buschelman        0,
106297304618SKris Buschelman        0,
106397304618SKris Buschelman /*75*/ 0,
106497304618SKris Buschelman        0,
106597304618SKris Buschelman        0,
106697304618SKris Buschelman        0,
106797304618SKris Buschelman        0,
106897304618SKris Buschelman /*80*/ 0,
106997304618SKris Buschelman        0,
107097304618SKris Buschelman        0,
107197304618SKris Buschelman        0,
1072865e5f61SKris Buschelman /*84*/ MatLoad_MPIDense,
1073865e5f61SKris Buschelman        0,
1074865e5f61SKris Buschelman        0,
1075865e5f61SKris Buschelman        0,
1076865e5f61SKris Buschelman        0,
1077865e5f61SKris Buschelman        0,
1078865e5f61SKris Buschelman /*90*/ 0,
10794ae313f4SHong Zhang        MatMatMultSymbolic_MPIDense_MPIDense,
1080865e5f61SKris Buschelman        0,
1081865e5f61SKris Buschelman        0,
1082865e5f61SKris Buschelman        0,
1083865e5f61SKris Buschelman /*95*/ 0,
1084865e5f61SKris Buschelman        0,
1085865e5f61SKris Buschelman        0,
1086865e5f61SKris Buschelman        0};
10878965ea79SLois Curfman McInnes 
1088273d9f13SBarry Smith EXTERN_C_BEGIN
10894a2ae208SSatish Balay #undef __FUNCT__
1090a23d5eceSKris Buschelman #define __FUNCT__ "MatMPIDenseSetPreallocation_MPIDense"
1091be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatMPIDenseSetPreallocation_MPIDense(Mat mat,PetscScalar *data)
1092a23d5eceSKris Buschelman {
1093a23d5eceSKris Buschelman   Mat_MPIDense   *a;
1094dfbe8321SBarry Smith   PetscErrorCode ierr;
1095a23d5eceSKris Buschelman 
1096a23d5eceSKris Buschelman   PetscFunctionBegin;
1097a23d5eceSKris Buschelman   mat->preallocated = PETSC_TRUE;
1098a23d5eceSKris Buschelman   /* Note:  For now, when data is specified above, this assumes the user correctly
1099a23d5eceSKris Buschelman    allocates the local dense storage space.  We should add error checking. */
1100a23d5eceSKris Buschelman 
1101a23d5eceSKris Buschelman   a    = (Mat_MPIDense*)mat->data;
1102f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&a->A);CHKERRQ(ierr);
1103899cda47SBarry Smith   ierr = MatSetSizes(a->A,mat->rmap.n,mat->cmap.N,mat->rmap.n,mat->cmap.N);CHKERRQ(ierr);
11045c5985e7SKris Buschelman   ierr = MatSetType(a->A,MATSEQDENSE);CHKERRQ(ierr);
11055c5985e7SKris Buschelman   ierr = MatSeqDenseSetPreallocation(a->A,data);CHKERRQ(ierr);
110652e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,a->A);CHKERRQ(ierr);
1107a23d5eceSKris Buschelman   PetscFunctionReturn(0);
1108a23d5eceSKris Buschelman }
1109a23d5eceSKris Buschelman EXTERN_C_END
1110a23d5eceSKris Buschelman 
11110bad9183SKris Buschelman /*MC
1112fafad747SKris Buschelman    MATMPIDENSE - MATMPIDENSE = "mpidense" - A matrix type to be used for distributed dense matrices.
11130bad9183SKris Buschelman 
11140bad9183SKris Buschelman    Options Database Keys:
11150bad9183SKris Buschelman . -mat_type mpidense - sets the matrix type to "mpidense" during a call to MatSetFromOptions()
11160bad9183SKris Buschelman 
11170bad9183SKris Buschelman   Level: beginner
11180bad9183SKris Buschelman 
11190bad9183SKris Buschelman .seealso: MatCreateMPIDense
11200bad9183SKris Buschelman M*/
11210bad9183SKris Buschelman 
1122a23d5eceSKris Buschelman EXTERN_C_BEGIN
1123a23d5eceSKris Buschelman #undef __FUNCT__
11244a2ae208SSatish Balay #define __FUNCT__ "MatCreate_MPIDense"
1125be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_MPIDense(Mat mat)
1126273d9f13SBarry Smith {
1127273d9f13SBarry Smith   Mat_MPIDense   *a;
1128dfbe8321SBarry Smith   PetscErrorCode ierr;
1129273d9f13SBarry Smith 
1130273d9f13SBarry Smith   PetscFunctionBegin;
1131b0a32e0cSBarry Smith   ierr              = PetscNew(Mat_MPIDense,&a);CHKERRQ(ierr);
1132b0a32e0cSBarry Smith   mat->data         = (void*)a;
1133273d9f13SBarry Smith   ierr              = PetscMemcpy(mat->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1134273d9f13SBarry Smith   mat->factor       = 0;
1135273d9f13SBarry Smith   mat->mapping      = 0;
1136273d9f13SBarry Smith 
1137273d9f13SBarry Smith   a->factor       = 0;
1138273d9f13SBarry Smith   mat->insertmode = NOT_SET_VALUES;
1139273d9f13SBarry Smith   ierr = MPI_Comm_rank(mat->comm,&a->rank);CHKERRQ(ierr);
1140273d9f13SBarry Smith   ierr = MPI_Comm_size(mat->comm,&a->size);CHKERRQ(ierr);
1141273d9f13SBarry Smith 
1142899cda47SBarry Smith   mat->rmap.bs = mat->cmap.bs = 1;
11436148ca0dSBarry Smith   ierr = PetscMapSetUp(&mat->rmap);CHKERRQ(ierr);
11446148ca0dSBarry Smith   ierr = PetscMapSetUp(&mat->cmap);CHKERRQ(ierr);
1145899cda47SBarry Smith   a->nvec = mat->cmap.n;
1146273d9f13SBarry Smith 
1147273d9f13SBarry Smith   /* build cache for off array entries formed */
1148273d9f13SBarry Smith   a->donotstash = PETSC_FALSE;
1149273d9f13SBarry Smith   ierr = MatStashCreate_Private(mat->comm,1,&mat->stash);CHKERRQ(ierr);
1150273d9f13SBarry Smith 
1151273d9f13SBarry Smith   /* stuff used for matrix vector multiply */
1152273d9f13SBarry Smith   a->lvec        = 0;
1153273d9f13SBarry Smith   a->Mvctx       = 0;
1154273d9f13SBarry Smith   a->roworiented = PETSC_TRUE;
1155273d9f13SBarry Smith 
1156273d9f13SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatGetDiagonalBlock_C",
1157273d9f13SBarry Smith                                      "MatGetDiagonalBlock_MPIDense",
1158273d9f13SBarry Smith                                      MatGetDiagonalBlock_MPIDense);CHKERRQ(ierr);
1159a23d5eceSKris Buschelman   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatMPIDenseSetPreallocation_C",
1160a23d5eceSKris Buschelman                                      "MatMPIDenseSetPreallocation_MPIDense",
1161a23d5eceSKris Buschelman                                      MatMPIDenseSetPreallocation_MPIDense);CHKERRQ(ierr);
11624ae313f4SHong Zhang   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatMatMult_mpiaij_mpidense_C",
11634ae313f4SHong Zhang                                      "MatMatMult_MPIAIJ_MPIDense",
11644ae313f4SHong Zhang                                       MatMatMult_MPIAIJ_MPIDense);CHKERRQ(ierr);
11654ae313f4SHong Zhang   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatMatMultSymbolic_mpiaij_mpidense_C",
11664ae313f4SHong Zhang                                      "MatMatMultSymbolic_MPIAIJ_MPIDense",
11674ae313f4SHong Zhang                                       MatMatMultSymbolic_MPIAIJ_MPIDense);CHKERRQ(ierr);
11684ae313f4SHong Zhang   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatMatMultNumeric_mpiaij_mpidense_C",
11694ae313f4SHong Zhang                                      "MatMatMultNumeric_MPIAIJ_MPIDense",
11704ae313f4SHong Zhang                                       MatMatMultNumeric_MPIAIJ_MPIDense);CHKERRQ(ierr);
117117667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)mat,MATMPIDENSE);CHKERRQ(ierr);
1172273d9f13SBarry Smith   PetscFunctionReturn(0);
1173273d9f13SBarry Smith }
1174273d9f13SBarry Smith EXTERN_C_END
1175273d9f13SBarry Smith 
1176209238afSKris Buschelman /*MC
1177002d173eSKris Buschelman    MATDENSE - MATDENSE = "dense" - A matrix type to be used for dense matrices.
1178209238afSKris Buschelman 
1179209238afSKris Buschelman    This matrix type is identical to MATSEQDENSE when constructed with a single process communicator,
1180209238afSKris Buschelman    and MATMPIDENSE otherwise.
1181209238afSKris Buschelman 
1182209238afSKris Buschelman    Options Database Keys:
1183209238afSKris Buschelman . -mat_type dense - sets the matrix type to "dense" during a call to MatSetFromOptions()
1184209238afSKris Buschelman 
1185209238afSKris Buschelman   Level: beginner
1186209238afSKris Buschelman 
1187209238afSKris Buschelman .seealso: MatCreateMPIDense,MATSEQDENSE,MATMPIDENSE
1188209238afSKris Buschelman M*/
1189209238afSKris Buschelman 
1190209238afSKris Buschelman EXTERN_C_BEGIN
1191209238afSKris Buschelman #undef __FUNCT__
1192209238afSKris Buschelman #define __FUNCT__ "MatCreate_Dense"
1193be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_Dense(Mat A)
1194dfbe8321SBarry Smith {
11956849ba73SBarry Smith   PetscErrorCode ierr;
119613f74950SBarry Smith   PetscMPIInt    size;
1197209238afSKris Buschelman 
1198209238afSKris Buschelman   PetscFunctionBegin;
1199209238afSKris Buschelman   ierr = MPI_Comm_size(A->comm,&size);CHKERRQ(ierr);
1200209238afSKris Buschelman   if (size == 1) {
1201209238afSKris Buschelman     ierr = MatSetType(A,MATSEQDENSE);CHKERRQ(ierr);
1202209238afSKris Buschelman   } else {
1203209238afSKris Buschelman     ierr = MatSetType(A,MATMPIDENSE);CHKERRQ(ierr);
1204209238afSKris Buschelman   }
1205209238afSKris Buschelman   PetscFunctionReturn(0);
1206209238afSKris Buschelman }
1207209238afSKris Buschelman EXTERN_C_END
1208209238afSKris Buschelman 
12094a2ae208SSatish Balay #undef __FUNCT__
12104a2ae208SSatish Balay #define __FUNCT__ "MatMPIDenseSetPreallocation"
1211273d9f13SBarry Smith /*@C
1212273d9f13SBarry Smith    MatMPIDenseSetPreallocation - Sets the array used to store the matrix entries
1213273d9f13SBarry Smith 
1214273d9f13SBarry Smith    Not collective
1215273d9f13SBarry Smith 
1216273d9f13SBarry Smith    Input Parameters:
1217273d9f13SBarry Smith .  A - the matrix
1218273d9f13SBarry Smith -  data - optional location of matrix data.  Set data=PETSC_NULL for PETSc
1219273d9f13SBarry Smith    to control all matrix memory allocation.
1220273d9f13SBarry Smith 
1221273d9f13SBarry Smith    Notes:
1222273d9f13SBarry Smith    The dense format is fully compatible with standard Fortran 77
1223273d9f13SBarry Smith    storage by columns.
1224273d9f13SBarry Smith 
1225273d9f13SBarry Smith    The data input variable is intended primarily for Fortran programmers
1226273d9f13SBarry Smith    who wish to allocate their own matrix memory space.  Most users should
1227273d9f13SBarry Smith    set data=PETSC_NULL.
1228273d9f13SBarry Smith 
1229273d9f13SBarry Smith    Level: intermediate
1230273d9f13SBarry Smith 
1231273d9f13SBarry Smith .keywords: matrix,dense, parallel
1232273d9f13SBarry Smith 
1233273d9f13SBarry Smith .seealso: MatCreate(), MatCreateSeqDense(), MatSetValues()
1234273d9f13SBarry Smith @*/
1235be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatMPIDenseSetPreallocation(Mat mat,PetscScalar *data)
1236273d9f13SBarry Smith {
1237dfbe8321SBarry Smith   PetscErrorCode ierr,(*f)(Mat,PetscScalar *);
1238273d9f13SBarry Smith 
1239273d9f13SBarry Smith   PetscFunctionBegin;
1240565567f0SKris Buschelman   ierr = PetscObjectQueryFunction((PetscObject)mat,"MatMPIDenseSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
1241a23d5eceSKris Buschelman   if (f) {
1242a23d5eceSKris Buschelman     ierr = (*f)(mat,data);CHKERRQ(ierr);
1243a23d5eceSKris Buschelman   }
1244273d9f13SBarry Smith   PetscFunctionReturn(0);
1245273d9f13SBarry Smith }
1246273d9f13SBarry Smith 
12474a2ae208SSatish Balay #undef __FUNCT__
12484a2ae208SSatish Balay #define __FUNCT__ "MatCreateMPIDense"
12498965ea79SLois Curfman McInnes /*@C
125039ddd567SLois Curfman McInnes    MatCreateMPIDense - Creates a sparse parallel matrix in dense format.
12518965ea79SLois Curfman McInnes 
1252db81eaa0SLois Curfman McInnes    Collective on MPI_Comm
1253db81eaa0SLois Curfman McInnes 
12548965ea79SLois Curfman McInnes    Input Parameters:
1255db81eaa0SLois Curfman McInnes +  comm - MPI communicator
12568965ea79SLois Curfman McInnes .  m - number of local rows (or PETSC_DECIDE to have calculated if M is given)
1257db81eaa0SLois Curfman McInnes .  n - number of local columns (or PETSC_DECIDE to have calculated if N is given)
12588965ea79SLois Curfman McInnes .  M - number of global rows (or PETSC_DECIDE to have calculated if m is given)
1259db81eaa0SLois Curfman McInnes .  N - number of global columns (or PETSC_DECIDE to have calculated if n is given)
12607f5ff6fdSBarry Smith -  data - optional location of matrix data.  Set data=PETSC_NULL (PETSC_NULL_SCALAR for Fortran users) for PETSc
1261dfc5480cSLois Curfman McInnes    to control all matrix memory allocation.
12628965ea79SLois Curfman McInnes 
12638965ea79SLois Curfman McInnes    Output Parameter:
1264477f1c0bSLois Curfman McInnes .  A - the matrix
12658965ea79SLois Curfman McInnes 
1266b259b22eSLois Curfman McInnes    Notes:
126739ddd567SLois Curfman McInnes    The dense format is fully compatible with standard Fortran 77
126839ddd567SLois Curfman McInnes    storage by columns.
12698965ea79SLois Curfman McInnes 
127018f449edSLois Curfman McInnes    The data input variable is intended primarily for Fortran programmers
127118f449edSLois Curfman McInnes    who wish to allocate their own matrix memory space.  Most users should
12727f5ff6fdSBarry Smith    set data=PETSC_NULL (PETSC_NULL_SCALAR for Fortran users).
127318f449edSLois Curfman McInnes 
12748965ea79SLois Curfman McInnes    The user MUST specify either the local or global matrix dimensions
12758965ea79SLois Curfman McInnes    (possibly both).
12768965ea79SLois Curfman McInnes 
1277027ccd11SLois Curfman McInnes    Level: intermediate
1278027ccd11SLois Curfman McInnes 
127939ddd567SLois Curfman McInnes .keywords: matrix,dense, parallel
12808965ea79SLois Curfman McInnes 
128139ddd567SLois Curfman McInnes .seealso: MatCreate(), MatCreateSeqDense(), MatSetValues()
12828965ea79SLois Curfman McInnes @*/
1283be1d678aSKris Buschelman PetscErrorCode PETSCMAT_DLLEXPORT MatCreateMPIDense(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscScalar *data,Mat *A)
12848965ea79SLois Curfman McInnes {
12856849ba73SBarry Smith   PetscErrorCode ierr;
128613f74950SBarry Smith   PetscMPIInt    size;
12878965ea79SLois Curfman McInnes 
12883a40ed3dSBarry Smith   PetscFunctionBegin;
1289f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1290f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
1291273d9f13SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1292273d9f13SBarry Smith   if (size > 1) {
1293273d9f13SBarry Smith     ierr = MatSetType(*A,MATMPIDENSE);CHKERRQ(ierr);
1294273d9f13SBarry Smith     ierr = MatMPIDenseSetPreallocation(*A,data);CHKERRQ(ierr);
1295273d9f13SBarry Smith   } else {
1296273d9f13SBarry Smith     ierr = MatSetType(*A,MATSEQDENSE);CHKERRQ(ierr);
1297273d9f13SBarry Smith     ierr = MatSeqDenseSetPreallocation(*A,data);CHKERRQ(ierr);
12988c469469SLois Curfman McInnes   }
12993a40ed3dSBarry Smith   PetscFunctionReturn(0);
13008965ea79SLois Curfman McInnes }
13018965ea79SLois Curfman McInnes 
13024a2ae208SSatish Balay #undef __FUNCT__
13034a2ae208SSatish Balay #define __FUNCT__ "MatDuplicate_MPIDense"
13046849ba73SBarry Smith static PetscErrorCode MatDuplicate_MPIDense(Mat A,MatDuplicateOption cpvalues,Mat *newmat)
13058965ea79SLois Curfman McInnes {
13068965ea79SLois Curfman McInnes   Mat            mat;
13073501a2bdSLois Curfman McInnes   Mat_MPIDense   *a,*oldmat = (Mat_MPIDense*)A->data;
1308dfbe8321SBarry Smith   PetscErrorCode ierr;
13098965ea79SLois Curfman McInnes 
13103a40ed3dSBarry Smith   PetscFunctionBegin;
13118965ea79SLois Curfman McInnes   *newmat       = 0;
1312f69a0ea3SMatthew Knepley   ierr = MatCreate(A->comm,&mat);CHKERRQ(ierr);
1313899cda47SBarry Smith   ierr = MatSetSizes(mat,A->rmap.n,A->cmap.n,A->rmap.N,A->cmap.N);CHKERRQ(ierr);
1314be5d1d56SKris Buschelman   ierr = MatSetType(mat,A->type_name);CHKERRQ(ierr);
1315834f8fabSBarry Smith   a                 = (Mat_MPIDense*)mat->data;
1316e04c1aa4SHong Zhang   ierr              = PetscMemcpy(mat->ops,A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
13173501a2bdSLois Curfman McInnes   mat->factor       = A->factor;
1318c456f294SBarry Smith   mat->assembled    = PETSC_TRUE;
1319273d9f13SBarry Smith   mat->preallocated = PETSC_TRUE;
13208965ea79SLois Curfman McInnes 
1321899cda47SBarry Smith   mat->rmap.rstart     = A->rmap.rstart;
1322899cda47SBarry Smith   mat->rmap.rend       = A->rmap.rend;
13238965ea79SLois Curfman McInnes   a->size              = oldmat->size;
13248965ea79SLois Curfman McInnes   a->rank              = oldmat->rank;
1325e0fa3b82SLois Curfman McInnes   mat->insertmode      = NOT_SET_VALUES;
1326b9b97703SBarry Smith   a->nvec              = oldmat->nvec;
13273782ba37SSatish Balay   a->donotstash        = oldmat->donotstash;
1328e04c1aa4SHong Zhang 
1329899cda47SBarry Smith   ierr = PetscMemcpy(mat->rmap.range,A->rmap.range,(a->size+1)*sizeof(PetscInt));CHKERRQ(ierr);
1330899cda47SBarry Smith   ierr = PetscMemcpy(mat->cmap.range,A->cmap.range,(a->size+1)*sizeof(PetscInt));CHKERRQ(ierr);
13318798bf22SSatish Balay   ierr = MatStashCreate_Private(A->comm,1,&mat->stash);CHKERRQ(ierr);
13328965ea79SLois Curfman McInnes 
1333329f5518SBarry Smith   ierr = MatSetUpMultiply_MPIDense(mat);CHKERRQ(ierr);
13345609ef8eSBarry Smith   ierr = MatDuplicate(oldmat->A,cpvalues,&a->A);CHKERRQ(ierr);
133552e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,a->A);CHKERRQ(ierr);
13368965ea79SLois Curfman McInnes   *newmat = mat;
13373a40ed3dSBarry Smith   PetscFunctionReturn(0);
13388965ea79SLois Curfman McInnes }
13398965ea79SLois Curfman McInnes 
1340e090d566SSatish Balay #include "petscsys.h"
13418965ea79SLois Curfman McInnes 
13424a2ae208SSatish Balay #undef __FUNCT__
13434a2ae208SSatish Balay #define __FUNCT__ "MatLoad_MPIDense_DenseInFile"
1344f69a0ea3SMatthew Knepley PetscErrorCode MatLoad_MPIDense_DenseInFile(MPI_Comm comm,PetscInt fd,PetscInt M,PetscInt N, MatType type,Mat *newmat)
134590ace30eSBarry Smith {
13466849ba73SBarry Smith   PetscErrorCode ierr;
134732dcc486SBarry Smith   PetscMPIInt    rank,size;
134813f74950SBarry Smith   PetscInt       *rowners,i,m,nz,j;
134987828ca2SBarry Smith   PetscScalar    *array,*vals,*vals_ptr;
135090ace30eSBarry Smith   MPI_Status     status;
135190ace30eSBarry Smith 
13523a40ed3dSBarry Smith   PetscFunctionBegin;
1353d132466eSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1354d132466eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
135590ace30eSBarry Smith 
135690ace30eSBarry Smith   /* determine ownership of all rows */
135790ace30eSBarry Smith   m          = M/size + ((M % size) > rank);
135813f74950SBarry Smith   ierr       = PetscMalloc((size+2)*sizeof(PetscInt),&rowners);CHKERRQ(ierr);
135913f74950SBarry Smith   ierr       = MPI_Allgather(&m,1,MPIU_INT,rowners+1,1,MPIU_INT,comm);CHKERRQ(ierr);
136090ace30eSBarry Smith   rowners[0] = 0;
136190ace30eSBarry Smith   for (i=2; i<=size; i++) {
136290ace30eSBarry Smith     rowners[i] += rowners[i-1];
136390ace30eSBarry Smith   }
136490ace30eSBarry Smith 
1365f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1366f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*newmat,m,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1367be5d1d56SKris Buschelman   ierr = MatSetType(*newmat,type);CHKERRQ(ierr);
1368878740d9SKris Buschelman   ierr = MatMPIDenseSetPreallocation(*newmat,PETSC_NULL);CHKERRQ(ierr);
136990ace30eSBarry Smith   ierr = MatGetArray(*newmat,&array);CHKERRQ(ierr);
137090ace30eSBarry Smith 
137190ace30eSBarry Smith   if (!rank) {
137287828ca2SBarry Smith     ierr = PetscMalloc(m*N*sizeof(PetscScalar),&vals);CHKERRQ(ierr);
137390ace30eSBarry Smith 
137490ace30eSBarry Smith     /* read in my part of the matrix numerical values  */
13750752156aSBarry Smith     ierr = PetscBinaryRead(fd,vals,m*N,PETSC_SCALAR);CHKERRQ(ierr);
137690ace30eSBarry Smith 
137790ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
137890ace30eSBarry Smith     vals_ptr = vals;
137990ace30eSBarry Smith     for (i=0; i<m; i++) {
138090ace30eSBarry Smith       for (j=0; j<N; j++) {
138190ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
138290ace30eSBarry Smith       }
138390ace30eSBarry Smith     }
138490ace30eSBarry Smith 
138590ace30eSBarry Smith     /* read in other processors and ship out */
138690ace30eSBarry Smith     for (i=1; i<size; i++) {
138790ace30eSBarry Smith       nz   = (rowners[i+1] - rowners[i])*N;
13880752156aSBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr);
1389ca161407SBarry Smith       ierr = MPI_Send(vals,nz,MPIU_SCALAR,i,(*newmat)->tag,comm);CHKERRQ(ierr);
139090ace30eSBarry Smith     }
13913a40ed3dSBarry Smith   } else {
139290ace30eSBarry Smith     /* receive numeric values */
139387828ca2SBarry Smith     ierr = PetscMalloc(m*N*sizeof(PetscScalar),&vals);CHKERRQ(ierr);
139490ace30eSBarry Smith 
139590ace30eSBarry Smith     /* receive message of values*/
1396ca161407SBarry Smith     ierr = MPI_Recv(vals,m*N,MPIU_SCALAR,0,(*newmat)->tag,comm,&status);CHKERRQ(ierr);
139790ace30eSBarry Smith 
139890ace30eSBarry Smith     /* insert into matrix-by row (this is why cannot directly read into array */
139990ace30eSBarry Smith     vals_ptr = vals;
140090ace30eSBarry Smith     for (i=0; i<m; i++) {
140190ace30eSBarry Smith       for (j=0; j<N; j++) {
140290ace30eSBarry Smith         array[i + j*m] = *vals_ptr++;
140390ace30eSBarry Smith       }
140490ace30eSBarry Smith     }
140590ace30eSBarry Smith   }
1406606d414cSSatish Balay   ierr = PetscFree(rowners);CHKERRQ(ierr);
1407606d414cSSatish Balay   ierr = PetscFree(vals);CHKERRQ(ierr);
14086d4a8577SBarry Smith   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14096d4a8577SBarry Smith   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14103a40ed3dSBarry Smith   PetscFunctionReturn(0);
141190ace30eSBarry Smith }
141290ace30eSBarry Smith 
14134a2ae208SSatish Balay #undef __FUNCT__
14144a2ae208SSatish Balay #define __FUNCT__ "MatLoad_MPIDense"
1415f69a0ea3SMatthew Knepley PetscErrorCode MatLoad_MPIDense(PetscViewer viewer, MatType type,Mat *newmat)
14168965ea79SLois Curfman McInnes {
14178965ea79SLois Curfman McInnes   Mat            A;
141887828ca2SBarry Smith   PetscScalar    *vals,*svals;
141919bcc07fSBarry Smith   MPI_Comm       comm = ((PetscObject)viewer)->comm;
14208965ea79SLois Curfman McInnes   MPI_Status     status;
142113f74950SBarry Smith   PetscMPIInt    rank,size,tag = ((PetscObject)viewer)->tag,*rowners,*sndcounts,m,maxnz;
142213f74950SBarry Smith   PetscInt       header[4],*rowlengths = 0,M,N,*cols;
142313f74950SBarry Smith   PetscInt       *ourlens,*procsnz = 0,*offlens,jj,*mycols,*smycols;
142413f74950SBarry Smith   PetscInt       i,nz,j,rstart,rend;
142513f74950SBarry Smith   int            fd;
14266849ba73SBarry Smith   PetscErrorCode ierr;
14278965ea79SLois Curfman McInnes 
14283a40ed3dSBarry Smith   PetscFunctionBegin;
1429d132466eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1430d132466eSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
14318965ea79SLois Curfman McInnes   if (!rank) {
1432b0a32e0cSBarry Smith     ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
14330752156aSBarry Smith     ierr = PetscBinaryRead(fd,(char *)header,4,PETSC_INT);CHKERRQ(ierr);
1434552e946dSBarry Smith     if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"not matrix object");
14358965ea79SLois Curfman McInnes   }
14368965ea79SLois Curfman McInnes 
143713f74950SBarry Smith   ierr = MPI_Bcast(header+1,3,MPIU_INT,0,comm);CHKERRQ(ierr);
143890ace30eSBarry Smith   M = header[1]; N = header[2]; nz = header[3];
143990ace30eSBarry Smith 
144090ace30eSBarry Smith   /*
144190ace30eSBarry Smith        Handle case where matrix is stored on disk as a dense matrix
144290ace30eSBarry Smith   */
144390ace30eSBarry Smith   if (nz == MATRIX_BINARY_FORMAT_DENSE) {
1444be5d1d56SKris Buschelman     ierr = MatLoad_MPIDense_DenseInFile(comm,fd,M,N,type,newmat);CHKERRQ(ierr);
14453a40ed3dSBarry Smith     PetscFunctionReturn(0);
144690ace30eSBarry Smith   }
144790ace30eSBarry Smith 
14488965ea79SLois Curfman McInnes   /* determine ownership of all rows */
14498965ea79SLois Curfman McInnes   m          = M/size + ((M % size) > rank);
145013f74950SBarry Smith   ierr       = PetscMalloc((size+2)*sizeof(PetscInt),&rowners);CHKERRQ(ierr);
1451ca161407SBarry Smith   ierr       = MPI_Allgather(&m,1,MPI_INT,rowners+1,1,MPI_INT,comm);CHKERRQ(ierr);
14528965ea79SLois Curfman McInnes   rowners[0] = 0;
14538965ea79SLois Curfman McInnes   for (i=2; i<=size; i++) {
14548965ea79SLois Curfman McInnes     rowners[i] += rowners[i-1];
14558965ea79SLois Curfman McInnes   }
14568965ea79SLois Curfman McInnes   rstart = rowners[rank];
14578965ea79SLois Curfman McInnes   rend   = rowners[rank+1];
14588965ea79SLois Curfman McInnes 
14598965ea79SLois Curfman McInnes   /* distribute row lengths to all processors */
146013f74950SBarry Smith   ierr    = PetscMalloc(2*(rend-rstart+1)*sizeof(PetscInt),&ourlens);CHKERRQ(ierr);
14618965ea79SLois Curfman McInnes   offlens = ourlens + (rend-rstart);
14628965ea79SLois Curfman McInnes   if (!rank) {
146313f74950SBarry Smith     ierr = PetscMalloc(M*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
14640752156aSBarry Smith     ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
146513f74950SBarry Smith     ierr = PetscMalloc(size*sizeof(PetscMPIInt),&sndcounts);CHKERRQ(ierr);
14668965ea79SLois Curfman McInnes     for (i=0; i<size; i++) sndcounts[i] = rowners[i+1] - rowners[i];
14671466f1e1SBarry Smith     ierr = MPI_Scatterv(rowlengths,sndcounts,rowners,MPIU_INT,ourlens,rend-rstart,MPIU_INT,0,comm);CHKERRQ(ierr);
1468606d414cSSatish Balay     ierr = PetscFree(sndcounts);CHKERRQ(ierr);
1469ca161407SBarry Smith   } else {
14701466f1e1SBarry Smith     ierr = MPI_Scatterv(0,0,0,MPIU_INT,ourlens,rend-rstart,MPIU_INT,0,comm);CHKERRQ(ierr);
14718965ea79SLois Curfman McInnes   }
14728965ea79SLois Curfman McInnes 
14738965ea79SLois Curfman McInnes   if (!rank) {
14748965ea79SLois Curfman McInnes     /* calculate the number of nonzeros on each processor */
147513f74950SBarry Smith     ierr = PetscMalloc(size*sizeof(PetscInt),&procsnz);CHKERRQ(ierr);
147613f74950SBarry Smith     ierr = PetscMemzero(procsnz,size*sizeof(PetscInt));CHKERRQ(ierr);
14778965ea79SLois Curfman McInnes     for (i=0; i<size; i++) {
14788965ea79SLois Curfman McInnes       for (j=rowners[i]; j< rowners[i+1]; j++) {
14798965ea79SLois Curfman McInnes         procsnz[i] += rowlengths[j];
14808965ea79SLois Curfman McInnes       }
14818965ea79SLois Curfman McInnes     }
1482606d414cSSatish Balay     ierr = PetscFree(rowlengths);CHKERRQ(ierr);
14838965ea79SLois Curfman McInnes 
14848965ea79SLois Curfman McInnes     /* determine max buffer needed and allocate it */
14858965ea79SLois Curfman McInnes     maxnz = 0;
14868965ea79SLois Curfman McInnes     for (i=0; i<size; i++) {
14870452661fSBarry Smith       maxnz = PetscMax(maxnz,procsnz[i]);
14888965ea79SLois Curfman McInnes     }
148913f74950SBarry Smith     ierr = PetscMalloc(maxnz*sizeof(PetscInt),&cols);CHKERRQ(ierr);
14908965ea79SLois Curfman McInnes 
14918965ea79SLois Curfman McInnes     /* read in my part of the matrix column indices  */
14928965ea79SLois Curfman McInnes     nz = procsnz[0];
149313f74950SBarry Smith     ierr = PetscMalloc(nz*sizeof(PetscInt),&mycols);CHKERRQ(ierr);
14940752156aSBarry Smith     ierr = PetscBinaryRead(fd,mycols,nz,PETSC_INT);CHKERRQ(ierr);
14958965ea79SLois Curfman McInnes 
14968965ea79SLois Curfman McInnes     /* read in every one elses and ship off */
14978965ea79SLois Curfman McInnes     for (i=1; i<size; i++) {
14988965ea79SLois Curfman McInnes       nz   = procsnz[i];
14990752156aSBarry Smith       ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT);CHKERRQ(ierr);
150013f74950SBarry Smith       ierr = MPI_Send(cols,nz,MPIU_INT,i,tag,comm);CHKERRQ(ierr);
15018965ea79SLois Curfman McInnes     }
1502606d414cSSatish Balay     ierr = PetscFree(cols);CHKERRQ(ierr);
15033a40ed3dSBarry Smith   } else {
15048965ea79SLois Curfman McInnes     /* determine buffer space needed for message */
15058965ea79SLois Curfman McInnes     nz = 0;
15068965ea79SLois Curfman McInnes     for (i=0; i<m; i++) {
15078965ea79SLois Curfman McInnes       nz += ourlens[i];
15088965ea79SLois Curfman McInnes     }
150913f74950SBarry Smith     ierr = PetscMalloc((nz+1)*sizeof(PetscInt),&mycols);CHKERRQ(ierr);
15108965ea79SLois Curfman McInnes 
15118965ea79SLois Curfman McInnes     /* receive message of column indices*/
151213f74950SBarry Smith     ierr = MPI_Recv(mycols,nz,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr);
151313f74950SBarry Smith     ierr = MPI_Get_count(&status,MPIU_INT,&maxnz);CHKERRQ(ierr);
151429bbc08cSBarry Smith     if (maxnz != nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"something is wrong with file");
15158965ea79SLois Curfman McInnes   }
15168965ea79SLois Curfman McInnes 
15178965ea79SLois Curfman McInnes   /* loop over local rows, determining number of off diagonal entries */
151813f74950SBarry Smith   ierr = PetscMemzero(offlens,m*sizeof(PetscInt));CHKERRQ(ierr);
15198965ea79SLois Curfman McInnes   jj = 0;
15208965ea79SLois Curfman McInnes   for (i=0; i<m; i++) {
15218965ea79SLois Curfman McInnes     for (j=0; j<ourlens[i]; j++) {
15228965ea79SLois Curfman McInnes       if (mycols[jj] < rstart || mycols[jj] >= rend) offlens[i]++;
15238965ea79SLois Curfman McInnes       jj++;
15248965ea79SLois Curfman McInnes     }
15258965ea79SLois Curfman McInnes   }
15268965ea79SLois Curfman McInnes 
15278965ea79SLois Curfman McInnes   /* create our matrix */
15288965ea79SLois Curfman McInnes   for (i=0; i<m; i++) {
15298965ea79SLois Curfman McInnes     ourlens[i] -= offlens[i];
15308965ea79SLois Curfman McInnes   }
1531f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1532f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*newmat,m,PETSC_DECIDE,M,N);CHKERRQ(ierr);
1533be5d1d56SKris Buschelman   ierr = MatSetType(*newmat,type);CHKERRQ(ierr);
1534878740d9SKris Buschelman   ierr = MatMPIDenseSetPreallocation(*newmat,PETSC_NULL);CHKERRQ(ierr);
15358965ea79SLois Curfman McInnes   A = *newmat;
15368965ea79SLois Curfman McInnes   for (i=0; i<m; i++) {
15378965ea79SLois Curfman McInnes     ourlens[i] += offlens[i];
15388965ea79SLois Curfman McInnes   }
15398965ea79SLois Curfman McInnes 
15408965ea79SLois Curfman McInnes   if (!rank) {
154187828ca2SBarry Smith     ierr = PetscMalloc(maxnz*sizeof(PetscScalar),&vals);CHKERRQ(ierr);
15428965ea79SLois Curfman McInnes 
15438965ea79SLois Curfman McInnes     /* read in my part of the matrix numerical values  */
15448965ea79SLois Curfman McInnes     nz = procsnz[0];
15450752156aSBarry Smith     ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr);
15468965ea79SLois Curfman McInnes 
15478965ea79SLois Curfman McInnes     /* insert into matrix */
15488965ea79SLois Curfman McInnes     jj      = rstart;
15498965ea79SLois Curfman McInnes     smycols = mycols;
15508965ea79SLois Curfman McInnes     svals   = vals;
15518965ea79SLois Curfman McInnes     for (i=0; i<m; i++) {
15528965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
15538965ea79SLois Curfman McInnes       smycols += ourlens[i];
15548965ea79SLois Curfman McInnes       svals   += ourlens[i];
15558965ea79SLois Curfman McInnes       jj++;
15568965ea79SLois Curfman McInnes     }
15578965ea79SLois Curfman McInnes 
15588965ea79SLois Curfman McInnes     /* read in other processors and ship out */
15598965ea79SLois Curfman McInnes     for (i=1; i<size; i++) {
15608965ea79SLois Curfman McInnes       nz   = procsnz[i];
15610752156aSBarry Smith       ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr);
1562ca161407SBarry Smith       ierr = MPI_Send(vals,nz,MPIU_SCALAR,i,A->tag,comm);CHKERRQ(ierr);
15638965ea79SLois Curfman McInnes     }
1564606d414cSSatish Balay     ierr = PetscFree(procsnz);CHKERRQ(ierr);
15653a40ed3dSBarry Smith   } else {
15668965ea79SLois Curfman McInnes     /* receive numeric values */
156784d528b1SBarry Smith     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&vals);CHKERRQ(ierr);
15688965ea79SLois Curfman McInnes 
15698965ea79SLois Curfman McInnes     /* receive message of values*/
1570ca161407SBarry Smith     ierr = MPI_Recv(vals,nz,MPIU_SCALAR,0,A->tag,comm,&status);CHKERRQ(ierr);
1571ca161407SBarry Smith     ierr = MPI_Get_count(&status,MPIU_SCALAR,&maxnz);CHKERRQ(ierr);
157229bbc08cSBarry Smith     if (maxnz != nz) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"something is wrong with file");
15738965ea79SLois Curfman McInnes 
15748965ea79SLois Curfman McInnes     /* insert into matrix */
15758965ea79SLois Curfman McInnes     jj      = rstart;
15768965ea79SLois Curfman McInnes     smycols = mycols;
15778965ea79SLois Curfman McInnes     svals   = vals;
15788965ea79SLois Curfman McInnes     for (i=0; i<m; i++) {
15798965ea79SLois Curfman McInnes       ierr = MatSetValues(A,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr);
15808965ea79SLois Curfman McInnes       smycols += ourlens[i];
15818965ea79SLois Curfman McInnes       svals   += ourlens[i];
15828965ea79SLois Curfman McInnes       jj++;
15838965ea79SLois Curfman McInnes     }
15848965ea79SLois Curfman McInnes   }
1585606d414cSSatish Balay   ierr = PetscFree(ourlens);CHKERRQ(ierr);
1586606d414cSSatish Balay   ierr = PetscFree(vals);CHKERRQ(ierr);
1587606d414cSSatish Balay   ierr = PetscFree(mycols);CHKERRQ(ierr);
1588606d414cSSatish Balay   ierr = PetscFree(rowners);CHKERRQ(ierr);
15898965ea79SLois Curfman McInnes 
15906d4a8577SBarry Smith   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15916d4a8577SBarry Smith   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15923a40ed3dSBarry Smith   PetscFunctionReturn(0);
15938965ea79SLois Curfman McInnes }
159490ace30eSBarry Smith 
15956e4ee0c6SHong Zhang #undef __FUNCT__
15966e4ee0c6SHong Zhang #define __FUNCT__ "MatEqual_MPIDense"
15976e4ee0c6SHong Zhang PetscErrorCode MatEqual_MPIDense(Mat A,Mat B,PetscTruth *flag)
15986e4ee0c6SHong Zhang {
15996e4ee0c6SHong Zhang   Mat_MPIDense   *matB = (Mat_MPIDense*)B->data,*matA = (Mat_MPIDense*)A->data;
16006e4ee0c6SHong Zhang   Mat            a,b;
16016e4ee0c6SHong Zhang   PetscTruth     flg;
16026e4ee0c6SHong Zhang   PetscErrorCode ierr;
160390ace30eSBarry Smith 
16046e4ee0c6SHong Zhang   PetscFunctionBegin;
16056e4ee0c6SHong Zhang   a = matA->A;
16066e4ee0c6SHong Zhang   b = matB->A;
16076e4ee0c6SHong Zhang   ierr = MatEqual(a,b,&flg);CHKERRQ(ierr);
1608*14459f09SHong Zhang   ierr = MPI_Allreduce(&flg,flag,1,MPI_INT,MPI_LAND,A->comm);CHKERRQ(ierr);
16096e4ee0c6SHong Zhang   PetscFunctionReturn(0);
16106e4ee0c6SHong Zhang }
161190ace30eSBarry Smith 
161290ace30eSBarry Smith 
161390ace30eSBarry Smith 
1614