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