11673f470SJose E. Roman #include <petsc/private/petscelemental.h> 2db31f6deSJed Brown 327e75052SPierre Jolivet const char ElementalCitation[] = "@Article{Elemental2012,\n" 427e75052SPierre Jolivet " author = {Jack Poulson and Bryan Marker and Jeff R. Hammond and Nichols A. Romero and Robert {v}an~{d}e~{G}eijn},\n" 527e75052SPierre Jolivet " title = {Elemental: A New Framework for Distributed Memory Dense Matrix Computations},\n" 627e75052SPierre Jolivet " journal = {{ACM} Transactions on Mathematical Software},\n" 727e75052SPierre Jolivet " volume = {39},\n" 827e75052SPierre Jolivet " number = {2},\n" 927e75052SPierre Jolivet " year = {2013}\n" 1027e75052SPierre Jolivet "}\n"; 1127e75052SPierre Jolivet static PetscBool ElementalCite = PETSC_FALSE; 1227e75052SPierre Jolivet 135e9f5b67SHong Zhang /* 145e9f5b67SHong Zhang The variable Petsc_Elemental_keyval is used to indicate an MPI attribute that 155e9f5b67SHong Zhang is attached to a communicator, in this case the attribute is a Mat_Elemental_Grid 165e9f5b67SHong Zhang */ 175e9f5b67SHong Zhang static PetscMPIInt Petsc_Elemental_keyval = MPI_KEYVAL_INVALID; 185e9f5b67SHong Zhang 19db31f6deSJed Brown static PetscErrorCode MatView_Elemental(Mat A,PetscViewer viewer) 20db31f6deSJed Brown { 21db31f6deSJed Brown PetscErrorCode ierr; 22db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 23db31f6deSJed Brown PetscBool iascii; 24db31f6deSJed Brown 25db31f6deSJed Brown PetscFunctionBegin; 26db31f6deSJed Brown ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 27db31f6deSJed Brown if (iascii) { 28db31f6deSJed Brown PetscViewerFormat format; 29db31f6deSJed Brown ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 30db31f6deSJed Brown if (format == PETSC_VIEWER_ASCII_INFO) { 3179673f7bSHong Zhang /* call elemental viewing function */ 322d8adcc7SHong Zhang ierr = PetscViewerASCIIPrintf(viewer,"Elemental run parameters:\n");CHKERRQ(ierr); 33ed667823SXuan Zhou ierr = PetscViewerASCIIPrintf(viewer," allocated entries=%d\n",(*a->emat).AllocatedMemory());CHKERRQ(ierr); 34ed667823SXuan Zhou ierr = PetscViewerASCIIPrintf(viewer," grid height=%d, grid width=%d\n",(*a->emat).Grid().Height(),(*a->emat).Grid().Width());CHKERRQ(ierr); 354fe7bbcaSHong Zhang if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 3679673f7bSHong Zhang /* call elemental viewing function */ 37ce94432eSBarry Smith ierr = PetscPrintf(PetscObjectComm((PetscObject)viewer),"test matview_elemental 2\n");CHKERRQ(ierr); 384fe7bbcaSHong Zhang } 3979673f7bSHong Zhang 40db31f6deSJed Brown } else if (format == PETSC_VIEWER_DEFAULT) { 41db31f6deSJed Brown ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr); 42e8146892SSatish Balay El::Print( *a->emat, "Elemental matrix (cyclic ordering)"); 43db31f6deSJed Brown ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr); 44834d3fecSHong Zhang if (A->factortype == MAT_FACTOR_NONE) { 4561119200SXuan Zhou Mat Adense; 4661119200SXuan Zhou ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense);CHKERRQ(ierr); 4761119200SXuan Zhou ierr = MatView(Adense,viewer);CHKERRQ(ierr); 4861119200SXuan Zhou ierr = MatDestroy(&Adense);CHKERRQ(ierr); 49834d3fecSHong Zhang } 50ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Format"); 51d2daa67eSHong Zhang } else { 525cb544a0SHong Zhang /* convert to dense format and call MatView() */ 5361119200SXuan Zhou Mat Adense; 5461119200SXuan Zhou ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense);CHKERRQ(ierr); 5561119200SXuan Zhou ierr = MatView(Adense,viewer);CHKERRQ(ierr); 5661119200SXuan Zhou ierr = MatDestroy(&Adense);CHKERRQ(ierr); 57d2daa67eSHong Zhang } 58db31f6deSJed Brown PetscFunctionReturn(0); 59db31f6deSJed Brown } 60db31f6deSJed Brown 6115767789SHong Zhang static PetscErrorCode MatGetInfo_Elemental(Mat A,MatInfoType flag,MatInfo *info) 62180a43e4SHong Zhang { 6315767789SHong Zhang Mat_Elemental *a = (Mat_Elemental*)A->data; 6415767789SHong Zhang 65180a43e4SHong Zhang PetscFunctionBegin; 665cb544a0SHong Zhang info->block_size = 1.0; 6715767789SHong Zhang 6815767789SHong Zhang if (flag == MAT_LOCAL) { 693966268fSBarry Smith info->nz_allocated = (*a->emat).AllocatedMemory(); /* locally allocated */ 7015767789SHong Zhang info->nz_used = info->nz_allocated; 7115767789SHong Zhang } else if (flag == MAT_GLOBAL_MAX) { 72820f2d46SBarry Smith //ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)matin));CHKERRMPI(ierr); 7315767789SHong Zhang /* see MatGetInfo_MPIAIJ() for getting global info->nz_allocated! */ 7415767789SHong Zhang //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_MAX not written yet"); 7515767789SHong Zhang } else if (flag == MAT_GLOBAL_SUM) { 7615767789SHong Zhang //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_SUM not written yet"); 773966268fSBarry Smith info->nz_allocated = (*a->emat).AllocatedMemory(); /* locally allocated */ 7815767789SHong Zhang info->nz_used = info->nz_allocated; /* assume Elemental does accurate allocation */ 79820f2d46SBarry Smith //ierr = MPIU_Allreduce(isend,irecv,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr); 8015767789SHong Zhang //PetscPrintf(PETSC_COMM_SELF," ... [%d] locally allocated %g\n",rank,info->nz_allocated); 8115767789SHong Zhang } 8215767789SHong Zhang 8315767789SHong Zhang info->nz_unneeded = 0.0; 843966268fSBarry Smith info->assemblies = A->num_ass; 8515767789SHong Zhang info->mallocs = 0; 8615767789SHong Zhang info->memory = ((PetscObject)A)->mem; 8715767789SHong Zhang info->fill_ratio_given = 0; /* determined by Elemental */ 8815767789SHong Zhang info->fill_ratio_needed = 0; 8915767789SHong Zhang info->factor_mallocs = 0; 90180a43e4SHong Zhang PetscFunctionReturn(0); 91180a43e4SHong Zhang } 92180a43e4SHong Zhang 9332d7a744SHong Zhang PetscErrorCode MatSetOption_Elemental(Mat A,MatOption op,PetscBool flg) 9432d7a744SHong Zhang { 9532d7a744SHong Zhang Mat_Elemental *a = (Mat_Elemental*)A->data; 9632d7a744SHong Zhang 9732d7a744SHong Zhang PetscFunctionBegin; 9832d7a744SHong Zhang switch (op) { 9932d7a744SHong Zhang case MAT_NEW_NONZERO_LOCATIONS: 10032d7a744SHong Zhang case MAT_NEW_NONZERO_LOCATION_ERR: 10132d7a744SHong Zhang case MAT_NEW_NONZERO_ALLOCATION_ERR: 102891a0571SHong Zhang case MAT_SYMMETRIC: 103071fcb05SBarry Smith case MAT_SORTED_FULL: 104eb1ec7c1SStefano Zampini case MAT_HERMITIAN: 105891a0571SHong Zhang break; 10632d7a744SHong Zhang case MAT_ROW_ORIENTED: 10732d7a744SHong Zhang a->roworiented = flg; 10832d7a744SHong Zhang break; 10932d7a744SHong Zhang default: 11032d7a744SHong Zhang SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %s",MatOptions[op]); 11132d7a744SHong Zhang } 11232d7a744SHong Zhang PetscFunctionReturn(0); 11332d7a744SHong Zhang } 11432d7a744SHong Zhang 115e6dea9dbSXuan Zhou static PetscErrorCode MatSetValues_Elemental(Mat A,PetscInt nr,const PetscInt *rows,PetscInt nc,const PetscInt *cols,const PetscScalar *vals,InsertMode imode) 116db31f6deSJed Brown { 117db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 118fbbcb730SJack Poulson PetscInt i,j,rrank,ridx,crank,cidx,erow,ecol,numQueues=0; 119db31f6deSJed Brown 120db31f6deSJed Brown PetscFunctionBegin; 121fbbcb730SJack Poulson // TODO: Initialize matrix to all zeros? 122fbbcb730SJack Poulson 123fbbcb730SJack Poulson // Count the number of queues from this process 12432d7a744SHong Zhang if (a->roworiented) { 125db31f6deSJed Brown for (i=0; i<nr; i++) { 126db31f6deSJed Brown if (rows[i] < 0) continue; 127db31f6deSJed Brown P2RO(A,0,rows[i],&rrank,&ridx); 128db31f6deSJed Brown RO2E(A,0,rrank,ridx,&erow); 129ce94432eSBarry Smith if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect row translation"); 130db31f6deSJed Brown for (j=0; j<nc; j++) { 131db31f6deSJed Brown if (cols[j] < 0) continue; 132db31f6deSJed Brown P2RO(A,1,cols[j],&crank,&cidx); 133db31f6deSJed Brown RO2E(A,1,crank,cidx,&ecol); 134ce94432eSBarry Smith if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect col translation"); 135fbbcb730SJack Poulson if (!a->emat->IsLocal(erow,ecol)) { /* off-proc entry */ 136fbbcb730SJack Poulson /* printf("Will later remotely update (%d,%d)\n",erow,ecol); */ 137aae2c449SHong Zhang if (imode != ADD_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported"); 138fbbcb730SJack Poulson ++numQueues; 139aae2c449SHong Zhang continue; 140ed36708cSHong Zhang } 141fbbcb730SJack Poulson /* printf("Locally updating (%d,%d)\n",erow,ecol); */ 142db31f6deSJed Brown switch (imode) { 143fbbcb730SJack Poulson case INSERT_VALUES: a->emat->Set(erow,ecol,(PetscElemScalar)vals[i*nc+j]); break; 144fbbcb730SJack Poulson case ADD_VALUES: a->emat->Update(erow,ecol,(PetscElemScalar)vals[i*nc+j]); break; 145ce94432eSBarry Smith default: SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode); 146db31f6deSJed Brown } 147db31f6deSJed Brown } 148db31f6deSJed Brown } 149fbbcb730SJack Poulson 150fbbcb730SJack Poulson /* printf("numQueues=%d\n",numQueues); */ 151fbbcb730SJack Poulson a->emat->Reserve( numQueues); 152fbbcb730SJack Poulson for (i=0; i<nr; i++) { 153fbbcb730SJack Poulson if (rows[i] < 0) continue; 154fbbcb730SJack Poulson P2RO(A,0,rows[i],&rrank,&ridx); 155fbbcb730SJack Poulson RO2E(A,0,rrank,ridx,&erow); 156fbbcb730SJack Poulson for (j=0; j<nc; j++) { 157fbbcb730SJack Poulson if (cols[j] < 0) continue; 158fbbcb730SJack Poulson P2RO(A,1,cols[j],&crank,&cidx); 159fbbcb730SJack Poulson RO2E(A,1,crank,cidx,&ecol); 160fbbcb730SJack Poulson if (!a->emat->IsLocal(erow,ecol)) { /*off-proc entry*/ 161fbbcb730SJack Poulson /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */ 162fbbcb730SJack Poulson a->emat->QueueUpdate( erow, ecol, vals[i*nc+j]); 163fbbcb730SJack Poulson } 164fbbcb730SJack Poulson } 165fbbcb730SJack Poulson } 16632d7a744SHong Zhang } else { /* columnoriented */ 16732d7a744SHong Zhang for (j=0; j<nc; j++) { 16832d7a744SHong Zhang if (cols[j] < 0) continue; 16932d7a744SHong Zhang P2RO(A,1,cols[j],&crank,&cidx); 17032d7a744SHong Zhang RO2E(A,1,crank,cidx,&ecol); 17132d7a744SHong Zhang if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect col translation"); 17232d7a744SHong Zhang for (i=0; i<nr; i++) { 17332d7a744SHong Zhang if (rows[i] < 0) continue; 17432d7a744SHong Zhang P2RO(A,0,rows[i],&rrank,&ridx); 17532d7a744SHong Zhang RO2E(A,0,rrank,ridx,&erow); 17632d7a744SHong Zhang if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect row translation"); 17732d7a744SHong Zhang if (!a->emat->IsLocal(erow,ecol)) { /* off-proc entry */ 17832d7a744SHong Zhang /* printf("Will later remotely update (%d,%d)\n",erow,ecol); */ 17932d7a744SHong Zhang if (imode != ADD_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported"); 18032d7a744SHong Zhang ++numQueues; 18132d7a744SHong Zhang continue; 18232d7a744SHong Zhang } 18332d7a744SHong Zhang /* printf("Locally updating (%d,%d)\n",erow,ecol); */ 18432d7a744SHong Zhang switch (imode) { 18532d7a744SHong Zhang case INSERT_VALUES: a->emat->Set(erow,ecol,(PetscElemScalar)vals[i+j*nr]); break; 18632d7a744SHong Zhang case ADD_VALUES: a->emat->Update(erow,ecol,(PetscElemScalar)vals[i+j*nr]); break; 18732d7a744SHong Zhang default: SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode); 18832d7a744SHong Zhang } 18932d7a744SHong Zhang } 19032d7a744SHong Zhang } 19132d7a744SHong Zhang 19232d7a744SHong Zhang /* printf("numQueues=%d\n",numQueues); */ 19332d7a744SHong Zhang a->emat->Reserve( numQueues); 19432d7a744SHong Zhang for (j=0; j<nc; j++) { 19532d7a744SHong Zhang if (cols[j] < 0) continue; 19632d7a744SHong Zhang P2RO(A,1,cols[j],&crank,&cidx); 19732d7a744SHong Zhang RO2E(A,1,crank,cidx,&ecol); 19832d7a744SHong Zhang 19932d7a744SHong Zhang for (i=0; i<nr; i++) { 20032d7a744SHong Zhang if (rows[i] < 0) continue; 20132d7a744SHong Zhang P2RO(A,0,rows[i],&rrank,&ridx); 20232d7a744SHong Zhang RO2E(A,0,rrank,ridx,&erow); 20332d7a744SHong Zhang if (!a->emat->IsLocal(erow,ecol)) { /*off-proc entry*/ 20432d7a744SHong Zhang /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */ 20532d7a744SHong Zhang a->emat->QueueUpdate( erow, ecol, vals[i+j*nr]); 20632d7a744SHong Zhang } 20732d7a744SHong Zhang } 20832d7a744SHong Zhang } 20932d7a744SHong Zhang } 210db31f6deSJed Brown PetscFunctionReturn(0); 211db31f6deSJed Brown } 212db31f6deSJed Brown 213db31f6deSJed Brown static PetscErrorCode MatMult_Elemental(Mat A,Vec X,Vec Y) 214db31f6deSJed Brown { 215db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 216db31f6deSJed Brown PetscErrorCode ierr; 217e6dea9dbSXuan Zhou const PetscElemScalar *x; 218e6dea9dbSXuan Zhou PetscElemScalar *y; 219df311e6cSXuan Zhou PetscElemScalar one = 1,zero = 0; 220db31f6deSJed Brown 221db31f6deSJed Brown PetscFunctionBegin; 222e6dea9dbSXuan Zhou ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 223e6dea9dbSXuan Zhou ierr = VecGetArray(Y,(PetscScalar **)&y);CHKERRQ(ierr); 224db31f6deSJed Brown { /* Scoping so that constructor is called before pointer is returned */ 225e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ye; 2260c18141cSBarry Smith xe.LockedAttach(A->cmap->N,1,*a->grid,0,0,x,A->cmap->n); 2270c18141cSBarry Smith ye.Attach(A->rmap->N,1,*a->grid,0,0,y,A->rmap->n); 228e8146892SSatish Balay El::Gemv(El::NORMAL,one,*a->emat,xe,zero,ye); 229db31f6deSJed Brown } 230e6dea9dbSXuan Zhou ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 231e6dea9dbSXuan Zhou ierr = VecRestoreArray(Y,(PetscScalar **)&y);CHKERRQ(ierr); 232db31f6deSJed Brown PetscFunctionReturn(0); 233db31f6deSJed Brown } 234db31f6deSJed Brown 2359426833fSXuan Zhou static PetscErrorCode MatMultTranspose_Elemental(Mat A,Vec X,Vec Y) 2369426833fSXuan Zhou { 2379426833fSXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 2389426833fSXuan Zhou PetscErrorCode ierr; 239df311e6cSXuan Zhou const PetscElemScalar *x; 240df311e6cSXuan Zhou PetscElemScalar *y; 241e6dea9dbSXuan Zhou PetscElemScalar one = 1,zero = 0; 2429426833fSXuan Zhou 2439426833fSXuan Zhou PetscFunctionBegin; 244e6dea9dbSXuan Zhou ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 245e6dea9dbSXuan Zhou ierr = VecGetArray(Y,(PetscScalar **)&y);CHKERRQ(ierr); 2469426833fSXuan Zhou { /* Scoping so that constructor is called before pointer is returned */ 247e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ye; 2480c18141cSBarry Smith xe.LockedAttach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n); 2490c18141cSBarry Smith ye.Attach(A->cmap->N,1,*a->grid,0,0,y,A->cmap->n); 250e8146892SSatish Balay El::Gemv(El::TRANSPOSE,one,*a->emat,xe,zero,ye); 2519426833fSXuan Zhou } 252e6dea9dbSXuan Zhou ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 253e6dea9dbSXuan Zhou ierr = VecRestoreArray(Y,(PetscScalar **)&y);CHKERRQ(ierr); 2549426833fSXuan Zhou PetscFunctionReturn(0); 2559426833fSXuan Zhou } 2569426833fSXuan Zhou 257db31f6deSJed Brown static PetscErrorCode MatMultAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z) 258db31f6deSJed Brown { 259db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 260db31f6deSJed Brown PetscErrorCode ierr; 261df311e6cSXuan Zhou const PetscElemScalar *x; 262df311e6cSXuan Zhou PetscElemScalar *z; 263e6dea9dbSXuan Zhou PetscElemScalar one = 1; 264db31f6deSJed Brown 265db31f6deSJed Brown PetscFunctionBegin; 266db31f6deSJed Brown if (Y != Z) {ierr = VecCopy(Y,Z);CHKERRQ(ierr);} 267e6dea9dbSXuan Zhou ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 268e6dea9dbSXuan Zhou ierr = VecGetArray(Z,(PetscScalar **)&z);CHKERRQ(ierr); 269db31f6deSJed Brown { /* Scoping so that constructor is called before pointer is returned */ 270e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ze; 2710c18141cSBarry Smith xe.LockedAttach(A->cmap->N,1,*a->grid,0,0,x,A->cmap->n); 2720c18141cSBarry Smith ze.Attach(A->rmap->N,1,*a->grid,0,0,z,A->rmap->n); 273e8146892SSatish Balay El::Gemv(El::NORMAL,one,*a->emat,xe,one,ze); 274db31f6deSJed Brown } 275e6dea9dbSXuan Zhou ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 276e6dea9dbSXuan Zhou ierr = VecRestoreArray(Z,(PetscScalar **)&z);CHKERRQ(ierr); 277db31f6deSJed Brown PetscFunctionReturn(0); 278db31f6deSJed Brown } 279db31f6deSJed Brown 280e883f9d5SXuan Zhou static PetscErrorCode MatMultTransposeAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z) 281e883f9d5SXuan Zhou { 282e883f9d5SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 283e883f9d5SXuan Zhou PetscErrorCode ierr; 284df311e6cSXuan Zhou const PetscElemScalar *x; 285df311e6cSXuan Zhou PetscElemScalar *z; 286e6dea9dbSXuan Zhou PetscElemScalar one = 1; 287e883f9d5SXuan Zhou 288e883f9d5SXuan Zhou PetscFunctionBegin; 289e883f9d5SXuan Zhou if (Y != Z) {ierr = VecCopy(Y,Z);CHKERRQ(ierr);} 290e6dea9dbSXuan Zhou ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 291e6dea9dbSXuan Zhou ierr = VecGetArray(Z,(PetscScalar **)&z);CHKERRQ(ierr); 292e883f9d5SXuan Zhou { /* Scoping so that constructor is called before pointer is returned */ 293e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ze; 2940c18141cSBarry Smith xe.LockedAttach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n); 2950c18141cSBarry Smith ze.Attach(A->cmap->N,1,*a->grid,0,0,z,A->cmap->n); 296e8146892SSatish Balay El::Gemv(El::TRANSPOSE,one,*a->emat,xe,one,ze); 297e883f9d5SXuan Zhou } 298e6dea9dbSXuan Zhou ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr); 299e6dea9dbSXuan Zhou ierr = VecRestoreArray(Z,(PetscScalar **)&z);CHKERRQ(ierr); 300e883f9d5SXuan Zhou PetscFunctionReturn(0); 301e883f9d5SXuan Zhou } 302e883f9d5SXuan Zhou 3034222ddf1SHong Zhang PetscErrorCode MatMatMultNumeric_Elemental(Mat A,Mat B,Mat C) 304c1d1b975SXuan Zhou { 305c1d1b975SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 306c1d1b975SXuan Zhou Mat_Elemental *b = (Mat_Elemental*)B->data; 3079a9e8502SHong Zhang Mat_Elemental *c = (Mat_Elemental*)C->data; 308e6dea9dbSXuan Zhou PetscElemScalar one = 1,zero = 0; 309c1d1b975SXuan Zhou 310c1d1b975SXuan Zhou PetscFunctionBegin; 311aae2c449SHong Zhang { /* Scoping so that constructor is called before pointer is returned */ 312e8146892SSatish Balay El::Gemm(El::NORMAL,El::NORMAL,one,*a->emat,*b->emat,zero,*c->emat); 313aae2c449SHong Zhang } 3149a9e8502SHong Zhang C->assembled = PETSC_TRUE; 3159a9e8502SHong Zhang PetscFunctionReturn(0); 3169a9e8502SHong Zhang } 3179a9e8502SHong Zhang 3184222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat Ce) 3199a9e8502SHong Zhang { 3209a9e8502SHong Zhang PetscErrorCode ierr; 3219a9e8502SHong Zhang 3229a9e8502SHong Zhang PetscFunctionBegin; 3239a9e8502SHong Zhang ierr = MatSetSizes(Ce,A->rmap->n,B->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 3249a9e8502SHong Zhang ierr = MatSetType(Ce,MATELEMENTAL);CHKERRQ(ierr); 3259a9e8502SHong Zhang ierr = MatSetUp(Ce);CHKERRQ(ierr); 3264222ddf1SHong Zhang Ce->ops->matmultnumeric = MatMatMultNumeric_Elemental; 327c1d1b975SXuan Zhou PetscFunctionReturn(0); 328c1d1b975SXuan Zhou } 329c1d1b975SXuan Zhou 330df311e6cSXuan Zhou static PetscErrorCode MatMatTransposeMultNumeric_Elemental(Mat A,Mat B,Mat C) 331df311e6cSXuan Zhou { 332df311e6cSXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 333df311e6cSXuan Zhou Mat_Elemental *b = (Mat_Elemental*)B->data; 334df311e6cSXuan Zhou Mat_Elemental *c = (Mat_Elemental*)C->data; 335e6dea9dbSXuan Zhou PetscElemScalar one = 1,zero = 0; 336df311e6cSXuan Zhou 337df311e6cSXuan Zhou PetscFunctionBegin; 338df311e6cSXuan Zhou { /* Scoping so that constructor is called before pointer is returned */ 339e8146892SSatish Balay El::Gemm(El::NORMAL,El::TRANSPOSE,one,*a->emat,*b->emat,zero,*c->emat); 340df311e6cSXuan Zhou } 341df311e6cSXuan Zhou C->assembled = PETSC_TRUE; 342df311e6cSXuan Zhou PetscFunctionReturn(0); 343df311e6cSXuan Zhou } 344df311e6cSXuan Zhou 3454222ddf1SHong Zhang static PetscErrorCode MatMatTransposeMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat C) 346df311e6cSXuan Zhou { 347df311e6cSXuan Zhou PetscErrorCode ierr; 348df311e6cSXuan Zhou 349df311e6cSXuan Zhou PetscFunctionBegin; 3504222ddf1SHong Zhang ierr = MatSetSizes(C,A->rmap->n,B->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 3514222ddf1SHong Zhang ierr = MatSetType(C,MATELEMENTAL);CHKERRQ(ierr); 3524222ddf1SHong Zhang ierr = MatSetUp(C);CHKERRQ(ierr); 353df311e6cSXuan Zhou PetscFunctionReturn(0); 354df311e6cSXuan Zhou } 355df311e6cSXuan Zhou 3564222ddf1SHong Zhang /* --------------------------------------- */ 3574222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_Elemental_AB(Mat C) 3584222ddf1SHong Zhang { 3594222ddf1SHong Zhang PetscFunctionBegin; 3604222ddf1SHong Zhang C->ops->matmultsymbolic = MatMatMultSymbolic_Elemental; 3614222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_AB; 3624222ddf1SHong Zhang PetscFunctionReturn(0); 3634222ddf1SHong Zhang } 3644222ddf1SHong Zhang 3654222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_Elemental_ABt(Mat C) 3664222ddf1SHong Zhang { 3674222ddf1SHong Zhang PetscFunctionBegin; 3684222ddf1SHong Zhang C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_Elemental; 3694222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_ABt; 3704222ddf1SHong Zhang PetscFunctionReturn(0); 3714222ddf1SHong Zhang } 3724222ddf1SHong Zhang 3734222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Elemental(Mat C) 3744222ddf1SHong Zhang { 3754222ddf1SHong Zhang PetscErrorCode ierr; 3764222ddf1SHong Zhang Mat_Product *product = C->product; 3774222ddf1SHong Zhang 3784222ddf1SHong Zhang PetscFunctionBegin; 3794222ddf1SHong Zhang switch (product->type) { 3804222ddf1SHong Zhang case MATPRODUCT_AB: 3814222ddf1SHong Zhang ierr = MatProductSetFromOptions_Elemental_AB(C);CHKERRQ(ierr); 3824222ddf1SHong Zhang break; 3834222ddf1SHong Zhang case MATPRODUCT_ABt: 3844222ddf1SHong Zhang ierr = MatProductSetFromOptions_Elemental_ABt(C);CHKERRQ(ierr); 3854222ddf1SHong Zhang break; 3866718818eSStefano Zampini default: 3876718818eSStefano Zampini break; 3884222ddf1SHong Zhang } 3894222ddf1SHong Zhang PetscFunctionReturn(0); 3904222ddf1SHong Zhang } 391f6e5db1bSPierre Jolivet 392f6e5db1bSPierre Jolivet PetscErrorCode MatMatMultNumeric_Elemental_MPIDense(Mat A,Mat B,Mat C) 393f6e5db1bSPierre Jolivet { 394f6e5db1bSPierre Jolivet Mat Be,Ce; 395f6e5db1bSPierre Jolivet PetscErrorCode ierr; 396f6e5db1bSPierre Jolivet 397f6e5db1bSPierre Jolivet PetscFunctionBegin; 398f6e5db1bSPierre Jolivet ierr = MatConvert(B,MATELEMENTAL,MAT_INITIAL_MATRIX,&Be);CHKERRQ(ierr); 399f6e5db1bSPierre Jolivet ierr = MatMatMult(A,Be,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&Ce);CHKERRQ(ierr); 400f6e5db1bSPierre Jolivet ierr = MatConvert(Ce,MATMPIDENSE,MAT_REUSE_MATRIX,&C);CHKERRQ(ierr); 401f6e5db1bSPierre Jolivet ierr = MatDestroy(&Be);CHKERRQ(ierr); 402f6e5db1bSPierre Jolivet ierr = MatDestroy(&Ce);CHKERRQ(ierr); 403f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 404f6e5db1bSPierre Jolivet } 405f6e5db1bSPierre Jolivet 406f6e5db1bSPierre Jolivet PetscErrorCode MatMatMultSymbolic_Elemental_MPIDense(Mat A,Mat B,PetscReal fill,Mat C) 407f6e5db1bSPierre Jolivet { 408f6e5db1bSPierre Jolivet PetscErrorCode ierr; 409f6e5db1bSPierre Jolivet 410f6e5db1bSPierre Jolivet PetscFunctionBegin; 411f6e5db1bSPierre Jolivet ierr = MatSetSizes(C,A->rmap->n,B->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 412f6e5db1bSPierre Jolivet ierr = MatSetType(C,MATMPIDENSE);CHKERRQ(ierr); 413f6e5db1bSPierre Jolivet ierr = MatSetUp(C);CHKERRQ(ierr); 414f6e5db1bSPierre Jolivet C->ops->matmultnumeric = MatMatMultNumeric_Elemental_MPIDense; 415f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 416f6e5db1bSPierre Jolivet } 417f6e5db1bSPierre Jolivet 418f6e5db1bSPierre Jolivet PetscErrorCode MatProductSetFromOptions_Elemental_MPIDense_AB(Mat C) 419f6e5db1bSPierre Jolivet { 420f6e5db1bSPierre Jolivet PetscFunctionBegin; 421f6e5db1bSPierre Jolivet C->ops->matmultsymbolic = MatMatMultSymbolic_Elemental_MPIDense; 422f6e5db1bSPierre Jolivet C->ops->productsymbolic = MatProductSymbolic_AB; 423f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 424f6e5db1bSPierre Jolivet } 425f6e5db1bSPierre Jolivet 426f6e5db1bSPierre Jolivet PetscErrorCode MatProductSetFromOptions_Elemental_MPIDense(Mat C) 427f6e5db1bSPierre Jolivet { 428f6e5db1bSPierre Jolivet PetscErrorCode ierr; 429f6e5db1bSPierre Jolivet Mat_Product *product = C->product; 430f6e5db1bSPierre Jolivet 431f6e5db1bSPierre Jolivet PetscFunctionBegin; 432f6e5db1bSPierre Jolivet if (product->type == MATPRODUCT_AB) { 433f6e5db1bSPierre Jolivet ierr = MatProductSetFromOptions_Elemental_MPIDense_AB(C);CHKERRQ(ierr); 434f6e5db1bSPierre Jolivet } 435f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 436f6e5db1bSPierre Jolivet } 4374222ddf1SHong Zhang /* --------------------------------------- */ 4384222ddf1SHong Zhang 439a9d89745SXuan Zhou static PetscErrorCode MatGetDiagonal_Elemental(Mat A,Vec D) 44061119200SXuan Zhou { 441a9d89745SXuan Zhou PetscInt i,nrows,ncols,nD,rrank,ridx,crank,cidx; 442a9d89745SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 44361119200SXuan Zhou PetscErrorCode ierr; 444a9d89745SXuan Zhou PetscElemScalar v; 445ce94432eSBarry Smith MPI_Comm comm; 44661119200SXuan Zhou 44761119200SXuan Zhou PetscFunctionBegin; 448ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 449a9d89745SXuan Zhou ierr = MatGetSize(A,&nrows,&ncols);CHKERRQ(ierr); 450a9d89745SXuan Zhou nD = nrows>ncols ? ncols : nrows; 451a9d89745SXuan Zhou for (i=0; i<nD; i++) { 452a9d89745SXuan Zhou PetscInt erow,ecol; 453a9d89745SXuan Zhou P2RO(A,0,i,&rrank,&ridx); 454a9d89745SXuan Zhou RO2E(A,0,rrank,ridx,&erow); 455a9d89745SXuan Zhou if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation"); 456a9d89745SXuan Zhou P2RO(A,1,i,&crank,&cidx); 457a9d89745SXuan Zhou RO2E(A,1,crank,cidx,&ecol); 458a9d89745SXuan Zhou if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation"); 459a9d89745SXuan Zhou v = a->emat->Get(erow,ecol); 4607c8b904fSSatish Balay ierr = VecSetValues(D,1,&i,(PetscScalar*)&v,INSERT_VALUES);CHKERRQ(ierr); 461ade3cc5eSXuan Zhou } 462a9d89745SXuan Zhou ierr = VecAssemblyBegin(D);CHKERRQ(ierr); 463a9d89745SXuan Zhou ierr = VecAssemblyEnd(D);CHKERRQ(ierr); 46461119200SXuan Zhou PetscFunctionReturn(0); 46561119200SXuan Zhou } 46661119200SXuan Zhou 467ade3cc5eSXuan Zhou static PetscErrorCode MatDiagonalScale_Elemental(Mat X,Vec L,Vec R) 468ade3cc5eSXuan Zhou { 469ade3cc5eSXuan Zhou Mat_Elemental *x = (Mat_Elemental*)X->data; 470ade3cc5eSXuan Zhou const PetscElemScalar *d; 471ade3cc5eSXuan Zhou PetscErrorCode ierr; 472ade3cc5eSXuan Zhou 473ade3cc5eSXuan Zhou PetscFunctionBegin; 4749065cd98SJed Brown if (R) { 475ade3cc5eSXuan Zhou ierr = VecGetArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr); 476e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de; 4770c18141cSBarry Smith de.LockedAttach(X->cmap->N,1,*x->grid,0,0,d,X->cmap->n); 478e8146892SSatish Balay El::DiagonalScale(El::RIGHT,El::NORMAL,de,*x->emat); 479ade3cc5eSXuan Zhou ierr = VecRestoreArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr); 4809065cd98SJed Brown } 4819065cd98SJed Brown if (L) { 482ade3cc5eSXuan Zhou ierr = VecGetArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr); 483e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de; 4840c18141cSBarry Smith de.LockedAttach(X->rmap->N,1,*x->grid,0,0,d,X->rmap->n); 485e8146892SSatish Balay El::DiagonalScale(El::LEFT,El::NORMAL,de,*x->emat); 486ade3cc5eSXuan Zhou ierr = VecRestoreArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr); 487ade3cc5eSXuan Zhou } 488ade3cc5eSXuan Zhou PetscFunctionReturn(0); 489ade3cc5eSXuan Zhou } 490ade3cc5eSXuan Zhou 49134fa46e1SFrancesco Ballarin static PetscErrorCode MatMissingDiagonal_Elemental(Mat A,PetscBool *missing,PetscInt *d) 49234fa46e1SFrancesco Ballarin { 49334fa46e1SFrancesco Ballarin PetscFunctionBegin; 49434fa46e1SFrancesco Ballarin *missing = PETSC_FALSE; 49534fa46e1SFrancesco Ballarin PetscFunctionReturn(0); 49634fa46e1SFrancesco Ballarin } 49734fa46e1SFrancesco Ballarin 498e6dea9dbSXuan Zhou static PetscErrorCode MatScale_Elemental(Mat X,PetscScalar a) 49965b78793SXuan Zhou { 50065b78793SXuan Zhou Mat_Elemental *x = (Mat_Elemental*)X->data; 50165b78793SXuan Zhou 50265b78793SXuan Zhou PetscFunctionBegin; 503e8146892SSatish Balay El::Scale((PetscElemScalar)a,*x->emat); 50465b78793SXuan Zhou PetscFunctionReturn(0); 50565b78793SXuan Zhou } 50665b78793SXuan Zhou 507f82baa17SHong Zhang /* 508f82baa17SHong Zhang MatAXPY - Computes Y = a*X + Y. 509f82baa17SHong Zhang */ 510e6dea9dbSXuan Zhou static PetscErrorCode MatAXPY_Elemental(Mat Y,PetscScalar a,Mat X,MatStructure str) 511e09a3074SHong Zhang { 512e09a3074SHong Zhang Mat_Elemental *x = (Mat_Elemental*)X->data; 513e09a3074SHong Zhang Mat_Elemental *y = (Mat_Elemental*)Y->data; 51468446cf8SJed Brown PetscErrorCode ierr; 515e09a3074SHong Zhang 516e09a3074SHong Zhang PetscFunctionBegin; 517e8146892SSatish Balay El::Axpy((PetscElemScalar)a,*x->emat,*y->emat); 51821f6c9c4SJed Brown ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr); 519e09a3074SHong Zhang PetscFunctionReturn(0); 520e09a3074SHong Zhang } 521e09a3074SHong Zhang 522d6223691SXuan Zhou static PetscErrorCode MatCopy_Elemental(Mat A,Mat B,MatStructure str) 523d6223691SXuan Zhou { 524d6223691SXuan Zhou Mat_Elemental *a=(Mat_Elemental*)A->data; 525d6223691SXuan Zhou Mat_Elemental *b=(Mat_Elemental*)B->data; 526a4ee3bb6SSatish Balay PetscErrorCode ierr; 527d6223691SXuan Zhou 528d6223691SXuan Zhou PetscFunctionBegin; 529e8146892SSatish Balay El::Copy(*a->emat,*b->emat); 530cdc753b6SBarry Smith ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr); 531d6223691SXuan Zhou PetscFunctionReturn(0); 532d6223691SXuan Zhou } 533d6223691SXuan Zhou 534df311e6cSXuan Zhou static PetscErrorCode MatDuplicate_Elemental(Mat A,MatDuplicateOption op,Mat *B) 535df311e6cSXuan Zhou { 536df311e6cSXuan Zhou Mat Be; 537ce94432eSBarry Smith MPI_Comm comm; 538df311e6cSXuan Zhou Mat_Elemental *a=(Mat_Elemental*)A->data; 539df311e6cSXuan Zhou PetscErrorCode ierr; 540df311e6cSXuan Zhou 541df311e6cSXuan Zhou PetscFunctionBegin; 542ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 543df311e6cSXuan Zhou ierr = MatCreate(comm,&Be);CHKERRQ(ierr); 544df311e6cSXuan Zhou ierr = MatSetSizes(Be,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 545df311e6cSXuan Zhou ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr); 546df311e6cSXuan Zhou ierr = MatSetUp(Be);CHKERRQ(ierr); 547df311e6cSXuan Zhou *B = Be; 548df311e6cSXuan Zhou if (op == MAT_COPY_VALUES) { 549df311e6cSXuan Zhou Mat_Elemental *b=(Mat_Elemental*)Be->data; 550e8146892SSatish Balay El::Copy(*a->emat,*b->emat); 551df311e6cSXuan Zhou } 552df311e6cSXuan Zhou Be->assembled = PETSC_TRUE; 553df311e6cSXuan Zhou PetscFunctionReturn(0); 554df311e6cSXuan Zhou } 555df311e6cSXuan Zhou 556d6223691SXuan Zhou static PetscErrorCode MatTranspose_Elemental(Mat A,MatReuse reuse,Mat *B) 557d6223691SXuan Zhou { 558ec8cb81fSBarry Smith Mat Be = *B; 5595262d616SXuan Zhou PetscErrorCode ierr; 560ce94432eSBarry Smith MPI_Comm comm; 5614fe7bbcaSHong Zhang Mat_Elemental *a = (Mat_Elemental*)A->data, *b; 562d6223691SXuan Zhou 563d6223691SXuan Zhou PetscFunctionBegin; 564ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 5655cb544a0SHong Zhang /* Only out-of-place supported */ 5662847e3fdSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) SETERRQ(comm,PETSC_ERR_SUP,"Only out-of-place supported"); 5675262d616SXuan Zhou if (reuse == MAT_INITIAL_MATRIX) { 5685262d616SXuan Zhou ierr = MatCreate(comm,&Be);CHKERRQ(ierr); 5695262d616SXuan Zhou ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 5705262d616SXuan Zhou ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr); 5715262d616SXuan Zhou ierr = MatSetUp(Be);CHKERRQ(ierr); 5725262d616SXuan Zhou *B = Be; 5735262d616SXuan Zhou } 5744fe7bbcaSHong Zhang b = (Mat_Elemental*)Be->data; 575e8146892SSatish Balay El::Transpose(*a->emat,*b->emat); 5765262d616SXuan Zhou Be->assembled = PETSC_TRUE; 577d6223691SXuan Zhou PetscFunctionReturn(0); 578d6223691SXuan Zhou } 579d6223691SXuan Zhou 580dfcb0403SXuan Zhou static PetscErrorCode MatConjugate_Elemental(Mat A) 581dfcb0403SXuan Zhou { 582dfcb0403SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 583dfcb0403SXuan Zhou 584dfcb0403SXuan Zhou PetscFunctionBegin; 585e8146892SSatish Balay El::Conjugate(*a->emat); 586dfcb0403SXuan Zhou PetscFunctionReturn(0); 587dfcb0403SXuan Zhou } 588dfcb0403SXuan Zhou 5894a29722dSXuan Zhou static PetscErrorCode MatHermitianTranspose_Elemental(Mat A,MatReuse reuse,Mat *B) 5904a29722dSXuan Zhou { 591ec8cb81fSBarry Smith Mat Be = *B; 5924a29722dSXuan Zhou PetscErrorCode ierr; 593ce94432eSBarry Smith MPI_Comm comm; 5944a29722dSXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data, *b; 5954a29722dSXuan Zhou 5964a29722dSXuan Zhou PetscFunctionBegin; 597ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 5985cb544a0SHong Zhang /* Only out-of-place supported */ 5994a29722dSXuan Zhou if (reuse == MAT_INITIAL_MATRIX) { 6004a29722dSXuan Zhou ierr = MatCreate(comm,&Be);CHKERRQ(ierr); 6014a29722dSXuan Zhou ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 6024a29722dSXuan Zhou ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr); 6034a29722dSXuan Zhou ierr = MatSetUp(Be);CHKERRQ(ierr); 6044a29722dSXuan Zhou *B = Be; 6054a29722dSXuan Zhou } 6064a29722dSXuan Zhou b = (Mat_Elemental*)Be->data; 607e8146892SSatish Balay El::Adjoint(*a->emat,*b->emat); 6084a29722dSXuan Zhou Be->assembled = PETSC_TRUE; 6094a29722dSXuan Zhou PetscFunctionReturn(0); 6104a29722dSXuan Zhou } 6114a29722dSXuan Zhou 6121f881ff8SXuan Zhou static PetscErrorCode MatSolve_Elemental(Mat A,Vec B,Vec X) 6131f881ff8SXuan Zhou { 6141f881ff8SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 6151f881ff8SXuan Zhou PetscErrorCode ierr; 616df311e6cSXuan Zhou PetscElemScalar *x; 617ea394475SSatish Balay PetscInt pivoting = a->pivoting; 6181f881ff8SXuan Zhou 6191f881ff8SXuan Zhou PetscFunctionBegin; 62045cf121fSXuan Zhou ierr = VecCopy(B,X);CHKERRQ(ierr); 621e6dea9dbSXuan Zhou ierr = VecGetArray(X,(PetscScalar **)&x);CHKERRQ(ierr); 622ea394475SSatish Balay 623e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe; 6240c18141cSBarry Smith xe.Attach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n); 625e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::MC,El::MR> xer(xe); 626fc54b460SXuan Zhou switch (A->factortype) { 627fc54b460SXuan Zhou case MAT_FACTOR_LU: 628ea394475SSatish Balay if (pivoting == 0) { 629e8146892SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,xer); 630ea394475SSatish Balay } else if (pivoting == 1) { 631ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,xer); 632ea394475SSatish Balay } else { /* pivoting == 2 */ 633ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,xer); 6341f881ff8SXuan Zhou } 635fc54b460SXuan Zhou break; 636fc54b460SXuan Zhou case MAT_FACTOR_CHOLESKY: 637e8146892SSatish Balay El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,xer); 638fc54b460SXuan Zhou break; 639fc54b460SXuan Zhou default: 6404fe7bbcaSHong Zhang SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType"); 641fc54b460SXuan Zhou break; 6421f881ff8SXuan Zhou } 643ea394475SSatish Balay El::Copy(xer,xe); 644ea394475SSatish Balay 645e6dea9dbSXuan Zhou ierr = VecRestoreArray(X,(PetscScalar **)&x);CHKERRQ(ierr); 6461f881ff8SXuan Zhou PetscFunctionReturn(0); 6471f881ff8SXuan Zhou } 6481f881ff8SXuan Zhou 649df311e6cSXuan Zhou static PetscErrorCode MatSolveAdd_Elemental(Mat A,Vec B,Vec Y,Vec X) 650df311e6cSXuan Zhou { 651df311e6cSXuan Zhou PetscErrorCode ierr; 652df311e6cSXuan Zhou 653df311e6cSXuan Zhou PetscFunctionBegin; 654df311e6cSXuan Zhou ierr = MatSolve_Elemental(A,B,X);CHKERRQ(ierr); 6553d7f40dbSXuan Zhou ierr = VecAXPY(X,1,Y);CHKERRQ(ierr); 656df311e6cSXuan Zhou PetscFunctionReturn(0); 657df311e6cSXuan Zhou } 658df311e6cSXuan Zhou 659ae844d54SHong Zhang static PetscErrorCode MatMatSolve_Elemental(Mat A,Mat B,Mat X) 660ae844d54SHong Zhang { 6611f0e42cfSHong Zhang Mat_Elemental *a = (Mat_Elemental*)A->data; 66242ba530cSPierre Jolivet Mat_Elemental *x; 66342ba530cSPierre Jolivet Mat C; 664ea394475SSatish Balay PetscInt pivoting = a->pivoting; 66542ba530cSPierre Jolivet PetscBool flg; 66642ba530cSPierre Jolivet MatType type; 66742ba530cSPierre Jolivet PetscErrorCode ierr; 6681f0e42cfSHong Zhang 669ae844d54SHong Zhang PetscFunctionBegin; 67042ba530cSPierre Jolivet ierr = MatGetType(X,&type);CHKERRQ(ierr); 67142ba530cSPierre Jolivet ierr = PetscStrcmp(type,MATELEMENTAL,&flg);CHKERRQ(ierr); 67242ba530cSPierre Jolivet if (!flg) { 67342ba530cSPierre Jolivet ierr = MatConvert(B,MATELEMENTAL,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr); 67442ba530cSPierre Jolivet x = (Mat_Elemental*)C->data; 67542ba530cSPierre Jolivet } else { 67642ba530cSPierre Jolivet x = (Mat_Elemental*)X->data; 67742ba530cSPierre Jolivet El::Copy(*((Mat_Elemental*)B->data)->emat,*x->emat); 67842ba530cSPierre Jolivet } 679fc54b460SXuan Zhou switch (A->factortype) { 680fc54b460SXuan Zhou case MAT_FACTOR_LU: 681ea394475SSatish Balay if (pivoting == 0) { 682e8146892SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,*x->emat); 683ea394475SSatish Balay } else if (pivoting == 1) { 684ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*x->emat); 685ea394475SSatish Balay } else { 686ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,*x->emat); 687d6223691SXuan Zhou } 688fc54b460SXuan Zhou break; 689fc54b460SXuan Zhou case MAT_FACTOR_CHOLESKY: 690e8146892SSatish Balay El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,*x->emat); 691fc54b460SXuan Zhou break; 692fc54b460SXuan Zhou default: 6934fe7bbcaSHong Zhang SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType"); 694fc54b460SXuan Zhou break; 695fc54b460SXuan Zhou } 69642ba530cSPierre Jolivet if (!flg) { 69742ba530cSPierre Jolivet ierr = MatConvert(C,type,MAT_REUSE_MATRIX,&X);CHKERRQ(ierr); 69842ba530cSPierre Jolivet ierr = MatDestroy(&C);CHKERRQ(ierr); 69942ba530cSPierre Jolivet } 700ae844d54SHong Zhang PetscFunctionReturn(0); 701ae844d54SHong Zhang } 702ae844d54SHong Zhang 703ae844d54SHong Zhang static PetscErrorCode MatLUFactor_Elemental(Mat A,IS row,IS col,const MatFactorInfo *info) 704ae844d54SHong Zhang { 7057c920d81SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 706124af5d2SSatish Balay PetscErrorCode ierr; 707ea394475SSatish Balay PetscInt pivoting = a->pivoting; 7087c920d81SXuan Zhou 709ae844d54SHong Zhang PetscFunctionBegin; 710ea394475SSatish Balay if (pivoting == 0) { 711e8146892SSatish Balay El::LU(*a->emat); 712ea394475SSatish Balay } else if (pivoting == 1) { 713ea394475SSatish Balay El::LU(*a->emat,*a->P); 714ea394475SSatish Balay } else { 715ea394475SSatish Balay El::LU(*a->emat,*a->P,*a->Q); 716d6223691SXuan Zhou } 7171293973dSHong Zhang A->factortype = MAT_FACTOR_LU; 718834d3fecSHong Zhang A->assembled = PETSC_TRUE; 719f6224b95SHong Zhang 720f6224b95SHong Zhang ierr = PetscFree(A->solvertype);CHKERRQ(ierr); 721f6224b95SHong Zhang ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype);CHKERRQ(ierr); 722ae844d54SHong Zhang PetscFunctionReturn(0); 723ae844d54SHong Zhang } 724ae844d54SHong Zhang 725d7c3f9d8SHong Zhang static PetscErrorCode MatLUFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info) 726d7c3f9d8SHong Zhang { 727d7c3f9d8SHong Zhang PetscErrorCode ierr; 728d7c3f9d8SHong Zhang 729d7c3f9d8SHong Zhang PetscFunctionBegin; 730d7c3f9d8SHong Zhang ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 731d7c3f9d8SHong Zhang ierr = MatLUFactor_Elemental(F,0,0,info);CHKERRQ(ierr); 732d7c3f9d8SHong Zhang PetscFunctionReturn(0); 733d7c3f9d8SHong Zhang } 734d7c3f9d8SHong Zhang 735d7c3f9d8SHong Zhang static PetscErrorCode MatLUFactorSymbolic_Elemental(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info) 736d7c3f9d8SHong Zhang { 737d7c3f9d8SHong Zhang PetscFunctionBegin; 738d8304050SJose E. Roman /* F is created and allocated by MatGetFactor_elemental_petsc(), skip this routine. */ 739d7c3f9d8SHong Zhang PetscFunctionReturn(0); 740d7c3f9d8SHong Zhang } 741d7c3f9d8SHong Zhang 74245cf121fSXuan Zhou static PetscErrorCode MatCholeskyFactor_Elemental(Mat A,IS perm,const MatFactorInfo *info) 74345cf121fSXuan Zhou { 74445cf121fSXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 745e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::MC,El::STAR> d; 746124af5d2SSatish Balay PetscErrorCode ierr; 74745cf121fSXuan Zhou 74845cf121fSXuan Zhou PetscFunctionBegin; 749e8146892SSatish Balay El::Cholesky(El::UPPER,*a->emat); 750fc54b460SXuan Zhou A->factortype = MAT_FACTOR_CHOLESKY; 751834d3fecSHong Zhang A->assembled = PETSC_TRUE; 752f6224b95SHong Zhang 753f6224b95SHong Zhang ierr = PetscFree(A->solvertype);CHKERRQ(ierr); 754f6224b95SHong Zhang ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype);CHKERRQ(ierr); 75545cf121fSXuan Zhou PetscFunctionReturn(0); 75645cf121fSXuan Zhou } 75745cf121fSXuan Zhou 75879673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info) 75979673f7bSHong Zhang { 760cb76c1d8SXuan Zhou PetscErrorCode ierr; 761cb76c1d8SXuan Zhou 762cb76c1d8SXuan Zhou PetscFunctionBegin; 763cb76c1d8SXuan Zhou ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 764cb76c1d8SXuan Zhou ierr = MatCholeskyFactor_Elemental(F,0,info);CHKERRQ(ierr); 765cb76c1d8SXuan Zhou PetscFunctionReturn(0); 76679673f7bSHong Zhang } 767cb76c1d8SXuan Zhou 76879673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorSymbolic_Elemental(Mat F,Mat A,IS perm,const MatFactorInfo *info) 76979673f7bSHong Zhang { 77079673f7bSHong Zhang PetscFunctionBegin; 771d8304050SJose E. Roman /* F is created and allocated by MatGetFactor_elemental_petsc(), skip this routine. */ 77279673f7bSHong Zhang PetscFunctionReturn(0); 77379673f7bSHong Zhang } 77479673f7bSHong Zhang 775ea799195SBarry Smith PetscErrorCode MatFactorGetSolverType_elemental_elemental(Mat A,MatSolverType *type) 77615767789SHong Zhang { 77715767789SHong Zhang PetscFunctionBegin; 77815767789SHong Zhang *type = MATSOLVERELEMENTAL; 77915767789SHong Zhang PetscFunctionReturn(0); 78015767789SHong Zhang } 78115767789SHong Zhang 78215767789SHong Zhang static PetscErrorCode MatGetFactor_elemental_elemental(Mat A,MatFactorType ftype,Mat *F) 7831293973dSHong Zhang { 7841293973dSHong Zhang Mat B; 7851293973dSHong Zhang PetscErrorCode ierr; 7861293973dSHong Zhang 7871293973dSHong Zhang PetscFunctionBegin; 7881293973dSHong Zhang /* Create the factorization matrix */ 789ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 7901293973dSHong Zhang ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 7911293973dSHong Zhang ierr = MatSetType(B,MATELEMENTAL);CHKERRQ(ierr); 7921293973dSHong Zhang ierr = MatSetUp(B);CHKERRQ(ierr); 7931293973dSHong Zhang B->factortype = ftype; 79466e17bc3SBarry Smith B->trivialsymbolic = PETSC_TRUE; 79500c67f3bSHong Zhang ierr = PetscFree(B->solvertype);CHKERRQ(ierr); 79600c67f3bSHong Zhang ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&B->solvertype);CHKERRQ(ierr); 79700c67f3bSHong Zhang 7983ca39a21SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_elemental_elemental);CHKERRQ(ierr); 7991293973dSHong Zhang *F = B; 8001293973dSHong Zhang PetscFunctionReturn(0); 8011293973dSHong Zhang } 8021293973dSHong Zhang 8033ca39a21SBarry Smith PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Elemental(void) 80442c9c57cSBarry Smith { 80518713533SBarry Smith PetscErrorCode ierr; 80618713533SBarry Smith 80742c9c57cSBarry Smith PetscFunctionBegin; 8083ca39a21SBarry Smith ierr = MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL, MAT_FACTOR_LU,MatGetFactor_elemental_elemental);CHKERRQ(ierr); 8093ca39a21SBarry Smith ierr = MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL, MAT_FACTOR_CHOLESKY,MatGetFactor_elemental_elemental);CHKERRQ(ierr); 81042c9c57cSBarry Smith PetscFunctionReturn(0); 81142c9c57cSBarry Smith } 81242c9c57cSBarry Smith 8131f881ff8SXuan Zhou static PetscErrorCode MatNorm_Elemental(Mat A,NormType type,PetscReal *nrm) 8141f881ff8SXuan Zhou { 8151f881ff8SXuan Zhou Mat_Elemental *a=(Mat_Elemental*)A->data; 8161f881ff8SXuan Zhou 8171f881ff8SXuan Zhou PetscFunctionBegin; 8181f881ff8SXuan Zhou switch (type) { 8191f881ff8SXuan Zhou case NORM_1: 820e8146892SSatish Balay *nrm = El::OneNorm(*a->emat); 8211f881ff8SXuan Zhou break; 8221f881ff8SXuan Zhou case NORM_FROBENIUS: 823e8146892SSatish Balay *nrm = El::FrobeniusNorm(*a->emat); 8241f881ff8SXuan Zhou break; 8251f881ff8SXuan Zhou case NORM_INFINITY: 826e8146892SSatish Balay *nrm = El::InfinityNorm(*a->emat); 8271f881ff8SXuan Zhou break; 8281f881ff8SXuan Zhou default: 829d8304050SJose E. Roman SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unsupported norm type"); 8301f881ff8SXuan Zhou } 8311f881ff8SXuan Zhou PetscFunctionReturn(0); 8321f881ff8SXuan Zhou } 8331f881ff8SXuan Zhou 8345262d616SXuan Zhou static PetscErrorCode MatZeroEntries_Elemental(Mat A) 8355262d616SXuan Zhou { 8365262d616SXuan Zhou Mat_Elemental *a=(Mat_Elemental*)A->data; 8375262d616SXuan Zhou 8385262d616SXuan Zhou PetscFunctionBegin; 839e8146892SSatish Balay El::Zero(*a->emat); 8405262d616SXuan Zhou PetscFunctionReturn(0); 8415262d616SXuan Zhou } 8425262d616SXuan Zhou 843db31f6deSJed Brown static PetscErrorCode MatGetOwnershipIS_Elemental(Mat A,IS *rows,IS *cols) 844db31f6deSJed Brown { 845db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 846db31f6deSJed Brown PetscErrorCode ierr; 847db31f6deSJed Brown PetscInt i,m,shift,stride,*idx; 848db31f6deSJed Brown 849db31f6deSJed Brown PetscFunctionBegin; 850db31f6deSJed Brown if (rows) { 851db31f6deSJed Brown m = a->emat->LocalHeight(); 852db31f6deSJed Brown shift = a->emat->ColShift(); 853db31f6deSJed Brown stride = a->emat->ColStride(); 854785e854fSJed Brown ierr = PetscMalloc1(m,&idx);CHKERRQ(ierr); 855db31f6deSJed Brown for (i=0; i<m; i++) { 856db31f6deSJed Brown PetscInt rank,offset; 857db31f6deSJed Brown E2RO(A,0,shift+i*stride,&rank,&offset); 858db31f6deSJed Brown RO2P(A,0,rank,offset,&idx[i]); 859db31f6deSJed Brown } 860db31f6deSJed Brown ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,rows);CHKERRQ(ierr); 861db31f6deSJed Brown } 862db31f6deSJed Brown if (cols) { 863db31f6deSJed Brown m = a->emat->LocalWidth(); 864db31f6deSJed Brown shift = a->emat->RowShift(); 865db31f6deSJed Brown stride = a->emat->RowStride(); 866785e854fSJed Brown ierr = PetscMalloc1(m,&idx);CHKERRQ(ierr); 867db31f6deSJed Brown for (i=0; i<m; i++) { 868db31f6deSJed Brown PetscInt rank,offset; 869db31f6deSJed Brown E2RO(A,1,shift+i*stride,&rank,&offset); 870db31f6deSJed Brown RO2P(A,1,rank,offset,&idx[i]); 871db31f6deSJed Brown } 872db31f6deSJed Brown ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,cols);CHKERRQ(ierr); 873db31f6deSJed Brown } 874db31f6deSJed Brown PetscFunctionReturn(0); 875db31f6deSJed Brown } 876db31f6deSJed Brown 87719fd82e9SBarry Smith static PetscErrorCode MatConvert_Elemental_Dense(Mat A,MatType newtype,MatReuse reuse,Mat *B) 878af295397SXuan Zhou { 8792ef0cf24SXuan Zhou Mat Bmpi; 880af295397SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 881ce94432eSBarry Smith MPI_Comm comm; 8822ef0cf24SXuan Zhou PetscErrorCode ierr; 883fa9e26c8SHong Zhang IS isrows,iscols; 884fa9e26c8SHong Zhang PetscInt rrank,ridx,crank,cidx,nrows,ncols,i,j,erow,ecol,elrow,elcol; 885fa9e26c8SHong Zhang const PetscInt *rows,*cols; 886df311e6cSXuan Zhou PetscElemScalar v; 887fa9e26c8SHong Zhang const El::Grid &grid = a->emat->Grid(); 888af295397SXuan Zhou 889af295397SXuan Zhou PetscFunctionBegin; 890ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 891a000e53bSHong Zhang 892de0a22f0SHong Zhang if (reuse == MAT_REUSE_MATRIX) { 893de0a22f0SHong Zhang Bmpi = *B; 894de0a22f0SHong Zhang } else { 895af295397SXuan Zhou ierr = MatCreate(comm,&Bmpi);CHKERRQ(ierr); 896af295397SXuan Zhou ierr = MatSetSizes(Bmpi,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 8972ef0cf24SXuan Zhou ierr = MatSetType(Bmpi,MATDENSE);CHKERRQ(ierr); 898af295397SXuan Zhou ierr = MatSetUp(Bmpi);CHKERRQ(ierr); 899de0a22f0SHong Zhang } 900fa9e26c8SHong Zhang 901fa9e26c8SHong Zhang /* Get local entries of A */ 902fa9e26c8SHong Zhang ierr = MatGetOwnershipIS(A,&isrows,&iscols);CHKERRQ(ierr); 903fa9e26c8SHong Zhang ierr = ISGetLocalSize(isrows,&nrows);CHKERRQ(ierr); 904fa9e26c8SHong Zhang ierr = ISGetIndices(isrows,&rows);CHKERRQ(ierr); 905fa9e26c8SHong Zhang ierr = ISGetLocalSize(iscols,&ncols);CHKERRQ(ierr); 906fa9e26c8SHong Zhang ierr = ISGetIndices(iscols,&cols);CHKERRQ(ierr); 907fa9e26c8SHong Zhang 90857299f2fSHong Zhang if (a->roworiented) { 9092ef0cf24SXuan Zhou for (i=0; i<nrows; i++) { 910fa9e26c8SHong Zhang P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */ 9112ef0cf24SXuan Zhou RO2E(A,0,rrank,ridx,&erow); 9122ef0cf24SXuan Zhou if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation"); 9132ef0cf24SXuan Zhou for (j=0; j<ncols; j++) { 914fa9e26c8SHong Zhang P2RO(A,1,cols[j],&crank,&cidx); 9152ef0cf24SXuan Zhou RO2E(A,1,crank,cidx,&ecol); 9162ef0cf24SXuan Zhou if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation"); 917fa9e26c8SHong Zhang 918fa9e26c8SHong Zhang elrow = erow / grid.MCSize(); /* Elemental local row index */ 919fa9e26c8SHong Zhang elcol = ecol / grid.MRSize(); /* Elemental local column index */ 920fa9e26c8SHong Zhang v = a->emat->GetLocal(elrow,elcol); 921fa9e26c8SHong Zhang ierr = MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr); 9222ef0cf24SXuan Zhou } 9232ef0cf24SXuan Zhou } 92457299f2fSHong Zhang } else { /* column-oriented */ 92557299f2fSHong Zhang for (j=0; j<ncols; j++) { 92657299f2fSHong Zhang P2RO(A,1,cols[j],&crank,&cidx); 92757299f2fSHong Zhang RO2E(A,1,crank,cidx,&ecol); 92857299f2fSHong Zhang if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation"); 92957299f2fSHong Zhang for (i=0; i<nrows; i++) { 93057299f2fSHong Zhang P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */ 93157299f2fSHong Zhang RO2E(A,0,rrank,ridx,&erow); 93257299f2fSHong Zhang if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation"); 93357299f2fSHong Zhang 93457299f2fSHong Zhang elrow = erow / grid.MCSize(); /* Elemental local row index */ 93557299f2fSHong Zhang elcol = ecol / grid.MRSize(); /* Elemental local column index */ 93657299f2fSHong Zhang v = a->emat->GetLocal(elrow,elcol); 93757299f2fSHong Zhang ierr = MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr); 93857299f2fSHong Zhang } 93957299f2fSHong Zhang } 94057299f2fSHong Zhang } 941af295397SXuan Zhou ierr = MatAssemblyBegin(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 942af295397SXuan Zhou ierr = MatAssemblyEnd(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 943511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 94428be2f97SBarry Smith ierr = MatHeaderReplace(A,&Bmpi);CHKERRQ(ierr); 945c4ad791aSXuan Zhou } else { 946c4ad791aSXuan Zhou *B = Bmpi; 947c4ad791aSXuan Zhou } 948fa9e26c8SHong Zhang ierr = ISDestroy(&isrows);CHKERRQ(ierr); 949fa9e26c8SHong Zhang ierr = ISDestroy(&iscols);CHKERRQ(ierr); 950af295397SXuan Zhou PetscFunctionReturn(0); 951af295397SXuan Zhou } 952af295397SXuan Zhou 953cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat) 954af8000cdSHong Zhang { 955af8000cdSHong Zhang Mat mat_elemental; 956af8000cdSHong Zhang PetscErrorCode ierr; 957af8000cdSHong Zhang PetscInt M=A->rmap->N,N=A->cmap->N,row,ncols; 958af8000cdSHong Zhang const PetscInt *cols; 959af8000cdSHong Zhang const PetscScalar *vals; 960af8000cdSHong Zhang 961af8000cdSHong Zhang PetscFunctionBegin; 962bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 963bdeae278SStefano Zampini mat_elemental = *newmat; 964bdeae278SStefano Zampini ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr); 965bdeae278SStefano Zampini } else { 966af8000cdSHong Zhang ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr); 967af8000cdSHong Zhang ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 968af8000cdSHong Zhang ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr); 969af8000cdSHong Zhang ierr = MatSetUp(mat_elemental);CHKERRQ(ierr); 970bdeae278SStefano Zampini } 971af8000cdSHong Zhang for (row=0; row<M; row++) { 972af8000cdSHong Zhang ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr); 973bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 974af8000cdSHong Zhang ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr); 975af8000cdSHong Zhang ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr); 976af8000cdSHong Zhang } 977af8000cdSHong Zhang ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 978af8000cdSHong Zhang ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 979af8000cdSHong Zhang 980511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 98128be2f97SBarry Smith ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr); 982af8000cdSHong Zhang } else { 983af8000cdSHong Zhang *newmat = mat_elemental; 984af8000cdSHong Zhang } 985af8000cdSHong Zhang PetscFunctionReturn(0); 986af8000cdSHong Zhang } 987af8000cdSHong Zhang 988cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat) 9895d7652ecSHong Zhang { 9905d7652ecSHong Zhang Mat mat_elemental; 9915d7652ecSHong Zhang PetscErrorCode ierr; 9925d7652ecSHong Zhang PetscInt row,ncols,rstart=A->rmap->rstart,rend=A->rmap->rend,j; 9935d7652ecSHong Zhang const PetscInt *cols; 9945d7652ecSHong Zhang const PetscScalar *vals; 9955d7652ecSHong Zhang 9965d7652ecSHong Zhang PetscFunctionBegin; 997bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 998bdeae278SStefano Zampini mat_elemental = *newmat; 999bdeae278SStefano Zampini ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr); 1000bdeae278SStefano Zampini } else { 10015d7652ecSHong Zhang ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr); 10025d7652ecSHong Zhang ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,A->rmap->N,A->cmap->N);CHKERRQ(ierr); 10035d7652ecSHong Zhang ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr); 10045d7652ecSHong Zhang ierr = MatSetUp(mat_elemental);CHKERRQ(ierr); 1005bdeae278SStefano Zampini } 10065d7652ecSHong Zhang for (row=rstart; row<rend; row++) { 10075d7652ecSHong Zhang ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr); 10085d7652ecSHong Zhang for (j=0; j<ncols; j++) { 1009bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 10105d7652ecSHong Zhang ierr = MatSetValues(mat_elemental,1,&row,1,&cols[j],&vals[j],ADD_VALUES);CHKERRQ(ierr); 10115d7652ecSHong Zhang } 10125d7652ecSHong Zhang ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr); 10135d7652ecSHong Zhang } 10145d7652ecSHong Zhang ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10155d7652ecSHong Zhang ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10165d7652ecSHong Zhang 1017511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 101828be2f97SBarry Smith ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr); 10195d7652ecSHong Zhang } else { 10205d7652ecSHong Zhang *newmat = mat_elemental; 10215d7652ecSHong Zhang } 10225d7652ecSHong Zhang PetscFunctionReturn(0); 10235d7652ecSHong Zhang } 10245d7652ecSHong Zhang 1025cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat) 10266214f412SHong Zhang { 10276214f412SHong Zhang Mat mat_elemental; 10286214f412SHong Zhang PetscErrorCode ierr; 10296214f412SHong Zhang PetscInt M=A->rmap->N,N=A->cmap->N,row,ncols,j; 10306214f412SHong Zhang const PetscInt *cols; 10316214f412SHong Zhang const PetscScalar *vals; 10326214f412SHong Zhang 10336214f412SHong Zhang PetscFunctionBegin; 1034bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 1035bdeae278SStefano Zampini mat_elemental = *newmat; 1036bdeae278SStefano Zampini ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr); 1037bdeae278SStefano Zampini } else { 10386214f412SHong Zhang ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr); 10396214f412SHong Zhang ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 10406214f412SHong Zhang ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr); 10416214f412SHong Zhang ierr = MatSetUp(mat_elemental);CHKERRQ(ierr); 1042bdeae278SStefano Zampini } 10436214f412SHong Zhang ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr); 10446214f412SHong Zhang for (row=0; row<M; row++) { 10456214f412SHong Zhang ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr); 1046bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 10476214f412SHong Zhang ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr); 10486214f412SHong Zhang for (j=0; j<ncols; j++) { /* lower triangular part */ 1049eb1ec7c1SStefano Zampini PetscScalar v; 10506214f412SHong Zhang if (cols[j] == row) continue; 1051eb1ec7c1SStefano Zampini v = A->hermitian ? PetscConj(vals[j]) : vals[j]; 1052eb1ec7c1SStefano Zampini ierr = MatSetValues(mat_elemental,1,&cols[j],1,&row,&v,ADD_VALUES);CHKERRQ(ierr); 10536214f412SHong Zhang } 10546214f412SHong Zhang ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr); 10556214f412SHong Zhang } 10566214f412SHong Zhang ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr); 10576214f412SHong Zhang ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10586214f412SHong Zhang ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 10596214f412SHong Zhang 1060511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 106128be2f97SBarry Smith ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr); 10626214f412SHong Zhang } else { 10636214f412SHong Zhang *newmat = mat_elemental; 10646214f412SHong Zhang } 10656214f412SHong Zhang PetscFunctionReturn(0); 10666214f412SHong Zhang } 10676214f412SHong Zhang 1068cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat) 10696214f412SHong Zhang { 10706214f412SHong Zhang Mat mat_elemental; 10716214f412SHong Zhang PetscErrorCode ierr; 10726214f412SHong Zhang PetscInt M=A->rmap->N,N=A->cmap->N,row,ncols,j,rstart=A->rmap->rstart,rend=A->rmap->rend; 10736214f412SHong Zhang const PetscInt *cols; 10746214f412SHong Zhang const PetscScalar *vals; 10756214f412SHong Zhang 10766214f412SHong Zhang PetscFunctionBegin; 1077bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 1078bdeae278SStefano Zampini mat_elemental = *newmat; 1079bdeae278SStefano Zampini ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr); 1080bdeae278SStefano Zampini } else { 10816214f412SHong Zhang ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr); 10826214f412SHong Zhang ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr); 10836214f412SHong Zhang ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr); 10846214f412SHong Zhang ierr = MatSetUp(mat_elemental);CHKERRQ(ierr); 1085bdeae278SStefano Zampini } 10866214f412SHong Zhang ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr); 10876214f412SHong Zhang for (row=rstart; row<rend; row++) { 10886214f412SHong Zhang ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr); 1089bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 10906214f412SHong Zhang ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr); 10916214f412SHong Zhang for (j=0; j<ncols; j++) { /* lower triangular part */ 1092eb1ec7c1SStefano Zampini PetscScalar v; 10936214f412SHong Zhang if (cols[j] == row) continue; 1094eb1ec7c1SStefano Zampini v = A->hermitian ? PetscConj(vals[j]) : vals[j]; 1095eb1ec7c1SStefano Zampini ierr = MatSetValues(mat_elemental,1,&cols[j],1,&row,&v,ADD_VALUES);CHKERRQ(ierr); 10966214f412SHong Zhang } 10976214f412SHong Zhang ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr); 10986214f412SHong Zhang } 10996214f412SHong Zhang ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr); 11006214f412SHong Zhang ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11016214f412SHong Zhang ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 11026214f412SHong Zhang 1103511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 110428be2f97SBarry Smith ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr); 11056214f412SHong Zhang } else { 11066214f412SHong Zhang *newmat = mat_elemental; 11076214f412SHong Zhang } 11086214f412SHong Zhang PetscFunctionReturn(0); 11096214f412SHong Zhang } 11106214f412SHong Zhang 1111db31f6deSJed Brown static PetscErrorCode MatDestroy_Elemental(Mat A) 1112db31f6deSJed Brown { 1113db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 1114db31f6deSJed Brown PetscErrorCode ierr; 11155e9f5b67SHong Zhang Mat_Elemental_Grid *commgrid; 11165e9f5b67SHong Zhang PetscBool flg; 11175e9f5b67SHong Zhang MPI_Comm icomm; 1118db31f6deSJed Brown 1119db31f6deSJed Brown PetscFunctionBegin; 1120db31f6deSJed Brown delete a->emat; 1121ea394475SSatish Balay delete a->P; 1122ea394475SSatish Balay delete a->Q; 11235e9f5b67SHong Zhang 1124e8146892SSatish Balay El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A)); 11250c18141cSBarry Smith ierr = PetscCommDuplicate(cxxcomm.comm,&icomm,NULL);CHKERRQ(ierr); 1126ffc4695bSBarry Smith ierr = MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRMPI(ierr); 11275e9f5b67SHong Zhang if (--commgrid->grid_refct == 0) { 11285e9f5b67SHong Zhang delete commgrid->grid; 11295e9f5b67SHong Zhang ierr = PetscFree(commgrid);CHKERRQ(ierr); 1130ffc4695bSBarry Smith ierr = MPI_Comm_free_keyval(&Petsc_Elemental_keyval);CHKERRMPI(ierr); 11315e9f5b67SHong Zhang } 11325e9f5b67SHong Zhang ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr); 1133bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",NULL);CHKERRQ(ierr); 11343ca39a21SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverType_C",NULL);CHKERRQ(ierr); 1135f6e5db1bSPierre Jolivet ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_elemental_mpidense_C",NULL);CHKERRQ(ierr); 1136db31f6deSJed Brown ierr = PetscFree(A->data);CHKERRQ(ierr); 1137db31f6deSJed Brown PetscFunctionReturn(0); 1138db31f6deSJed Brown } 1139db31f6deSJed Brown 1140db31f6deSJed Brown PetscErrorCode MatSetUp_Elemental(Mat A) 1141db31f6deSJed Brown { 1142db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 1143db31f6deSJed Brown PetscErrorCode ierr; 1144f19600a0SHong Zhang MPI_Comm comm; 1145db31f6deSJed Brown PetscMPIInt rsize,csize; 1146f19600a0SHong Zhang PetscInt n; 1147db31f6deSJed Brown 1148db31f6deSJed Brown PetscFunctionBegin; 1149db31f6deSJed Brown ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 1150db31f6deSJed Brown ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 1151db31f6deSJed Brown 1152d8304050SJose E. Roman /* Check if local row and column sizes are equally distributed. 1153f19600a0SHong Zhang Jed: Elemental uses "element" cyclic ordering so the sizes need to match that 1154f19600a0SHong Zhang exactly. The strategy in MatElemental is for PETSc to implicitly permute to block ordering (like would be returned by 1155d8304050SJose E. Roman PetscSplitOwnership(comm,&n,&N), at which point Elemental matrices can act on PETSc vectors without redistributing the vectors. */ 1156f19600a0SHong Zhang ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 1157f19600a0SHong Zhang n = PETSC_DECIDE; 1158f19600a0SHong Zhang ierr = PetscSplitOwnership(comm,&n,&A->rmap->N);CHKERRQ(ierr); 1159f19600a0SHong Zhang if (n != A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local row size %D of ELEMENTAL matrix must be equally distributed",A->rmap->n); 1160f19600a0SHong Zhang 1161f19600a0SHong Zhang n = PETSC_DECIDE; 1162f19600a0SHong Zhang ierr = PetscSplitOwnership(comm,&n,&A->cmap->N);CHKERRQ(ierr); 1163f19600a0SHong Zhang if (n != A->cmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local column size %D of ELEMENTAL matrix must be equally distributed",A->cmap->n); 1164f19600a0SHong Zhang 1165*2f613bf5SBarry Smith a->emat->Resize(A->rmap->N,A->cmap->N); 1166e8146892SSatish Balay El::Zero(*a->emat); 1167db31f6deSJed Brown 1168ffc4695bSBarry Smith ierr = MPI_Comm_size(A->rmap->comm,&rsize);CHKERRMPI(ierr); 1169ffc4695bSBarry Smith ierr = MPI_Comm_size(A->cmap->comm,&csize);CHKERRMPI(ierr); 1170ce94432eSBarry Smith if (csize != rsize) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Cannot use row and column communicators of different sizes"); 1171db31f6deSJed Brown a->commsize = rsize; 1172db31f6deSJed Brown a->mr[0] = A->rmap->N % rsize; if (!a->mr[0]) a->mr[0] = rsize; 1173db31f6deSJed Brown a->mr[1] = A->cmap->N % csize; if (!a->mr[1]) a->mr[1] = csize; 1174db31f6deSJed Brown a->m[0] = A->rmap->N / rsize + (a->mr[0] != rsize); 1175db31f6deSJed Brown a->m[1] = A->cmap->N / csize + (a->mr[1] != csize); 1176db31f6deSJed Brown PetscFunctionReturn(0); 1177db31f6deSJed Brown } 1178db31f6deSJed Brown 1179aae2c449SHong Zhang PetscErrorCode MatAssemblyBegin_Elemental(Mat A, MatAssemblyType type) 1180aae2c449SHong Zhang { 1181aae2c449SHong Zhang Mat_Elemental *a = (Mat_Elemental*)A->data; 1182aae2c449SHong Zhang 1183aae2c449SHong Zhang PetscFunctionBegin; 1184fbbcb730SJack Poulson /* printf("Calling ProcessQueues\n"); */ 1185fbbcb730SJack Poulson a->emat->ProcessQueues(); 1186fbbcb730SJack Poulson /* printf("Finished ProcessQueues\n"); */ 1187aae2c449SHong Zhang PetscFunctionReturn(0); 1188aae2c449SHong Zhang } 1189aae2c449SHong Zhang 1190aae2c449SHong Zhang PetscErrorCode MatAssemblyEnd_Elemental(Mat A, MatAssemblyType type) 1191aae2c449SHong Zhang { 1192aae2c449SHong Zhang PetscFunctionBegin; 1193aae2c449SHong Zhang /* Currently does nothing */ 1194aae2c449SHong Zhang PetscFunctionReturn(0); 1195aae2c449SHong Zhang } 1196aae2c449SHong Zhang 11977b30e0f1SHong Zhang PetscErrorCode MatLoad_Elemental(Mat newMat, PetscViewer viewer) 11987b30e0f1SHong Zhang { 11997b30e0f1SHong Zhang PetscErrorCode ierr; 12007b30e0f1SHong Zhang Mat Adense,Ae; 12017b30e0f1SHong Zhang MPI_Comm comm; 12027b30e0f1SHong Zhang 12037b30e0f1SHong Zhang PetscFunctionBegin; 12047b30e0f1SHong Zhang ierr = PetscObjectGetComm((PetscObject)newMat,&comm);CHKERRQ(ierr); 12057b30e0f1SHong Zhang ierr = MatCreate(comm,&Adense);CHKERRQ(ierr); 12067b30e0f1SHong Zhang ierr = MatSetType(Adense,MATDENSE);CHKERRQ(ierr); 12077b30e0f1SHong Zhang ierr = MatLoad(Adense,viewer);CHKERRQ(ierr); 12087b30e0f1SHong Zhang ierr = MatConvert(Adense, MATELEMENTAL, MAT_INITIAL_MATRIX,&Ae);CHKERRQ(ierr); 12097b30e0f1SHong Zhang ierr = MatDestroy(&Adense);CHKERRQ(ierr); 121028be2f97SBarry Smith ierr = MatHeaderReplace(newMat,&Ae);CHKERRQ(ierr); 12117b30e0f1SHong Zhang PetscFunctionReturn(0); 12127b30e0f1SHong Zhang } 12137b30e0f1SHong Zhang 121440d92e34SHong Zhang /* -------------------------------------------------------------------*/ 121540d92e34SHong Zhang static struct _MatOps MatOps_Values = { 121640d92e34SHong Zhang MatSetValues_Elemental, 121740d92e34SHong Zhang 0, 121840d92e34SHong Zhang 0, 121940d92e34SHong Zhang MatMult_Elemental, 122040d92e34SHong Zhang /* 4*/ MatMultAdd_Elemental, 12219426833fSXuan Zhou MatMultTranspose_Elemental, 1222e883f9d5SXuan Zhou MatMultTransposeAdd_Elemental, 122340d92e34SHong Zhang MatSolve_Elemental, 1224df311e6cSXuan Zhou MatSolveAdd_Elemental, 12252ef15aa2SHong Zhang 0, 12262ef15aa2SHong Zhang /*10*/ 0, 122740d92e34SHong Zhang MatLUFactor_Elemental, 122840d92e34SHong Zhang MatCholeskyFactor_Elemental, 122940d92e34SHong Zhang 0, 123040d92e34SHong Zhang MatTranspose_Elemental, 123140d92e34SHong Zhang /*15*/ MatGetInfo_Elemental, 123240d92e34SHong Zhang 0, 123361119200SXuan Zhou MatGetDiagonal_Elemental, 1234ade3cc5eSXuan Zhou MatDiagonalScale_Elemental, 123540d92e34SHong Zhang MatNorm_Elemental, 123640d92e34SHong Zhang /*20*/ MatAssemblyBegin_Elemental, 123740d92e34SHong Zhang MatAssemblyEnd_Elemental, 123832d7a744SHong Zhang MatSetOption_Elemental, 123940d92e34SHong Zhang MatZeroEntries_Elemental, 124040d92e34SHong Zhang /*24*/ 0, 124140d92e34SHong Zhang MatLUFactorSymbolic_Elemental, 124240d92e34SHong Zhang MatLUFactorNumeric_Elemental, 124340d92e34SHong Zhang MatCholeskyFactorSymbolic_Elemental, 124440d92e34SHong Zhang MatCholeskyFactorNumeric_Elemental, 124540d92e34SHong Zhang /*29*/ MatSetUp_Elemental, 124640d92e34SHong Zhang 0, 124740d92e34SHong Zhang 0, 124840d92e34SHong Zhang 0, 124940d92e34SHong Zhang 0, 1250df311e6cSXuan Zhou /*34*/ MatDuplicate_Elemental, 125140d92e34SHong Zhang 0, 125240d92e34SHong Zhang 0, 125340d92e34SHong Zhang 0, 125440d92e34SHong Zhang 0, 125540d92e34SHong Zhang /*39*/ MatAXPY_Elemental, 125640d92e34SHong Zhang 0, 125740d92e34SHong Zhang 0, 125840d92e34SHong Zhang 0, 125940d92e34SHong Zhang MatCopy_Elemental, 126040d92e34SHong Zhang /*44*/ 0, 126140d92e34SHong Zhang MatScale_Elemental, 12627d68702bSBarry Smith MatShift_Basic, 126340d92e34SHong Zhang 0, 126440d92e34SHong Zhang 0, 126540d92e34SHong Zhang /*49*/ 0, 126640d92e34SHong Zhang 0, 126740d92e34SHong Zhang 0, 126840d92e34SHong Zhang 0, 126940d92e34SHong Zhang 0, 127040d92e34SHong Zhang /*54*/ 0, 127140d92e34SHong Zhang 0, 127240d92e34SHong Zhang 0, 127340d92e34SHong Zhang 0, 127440d92e34SHong Zhang 0, 127540d92e34SHong Zhang /*59*/ 0, 127640d92e34SHong Zhang MatDestroy_Elemental, 127740d92e34SHong Zhang MatView_Elemental, 127840d92e34SHong Zhang 0, 127940d92e34SHong Zhang 0, 128040d92e34SHong Zhang /*64*/ 0, 128140d92e34SHong Zhang 0, 128240d92e34SHong Zhang 0, 128340d92e34SHong Zhang 0, 128440d92e34SHong Zhang 0, 128540d92e34SHong Zhang /*69*/ 0, 128640d92e34SHong Zhang 0, 12872ef0cf24SXuan Zhou MatConvert_Elemental_Dense, 128840d92e34SHong Zhang 0, 128940d92e34SHong Zhang 0, 129040d92e34SHong Zhang /*74*/ 0, 129140d92e34SHong Zhang 0, 129240d92e34SHong Zhang 0, 129340d92e34SHong Zhang 0, 129440d92e34SHong Zhang 0, 129540d92e34SHong Zhang /*79*/ 0, 129640d92e34SHong Zhang 0, 129740d92e34SHong Zhang 0, 129840d92e34SHong Zhang 0, 12997b30e0f1SHong Zhang MatLoad_Elemental, 130040d92e34SHong Zhang /*84*/ 0, 130140d92e34SHong Zhang 0, 130240d92e34SHong Zhang 0, 130340d92e34SHong Zhang 0, 130440d92e34SHong Zhang 0, 13054222ddf1SHong Zhang /*89*/ 0, 13064222ddf1SHong Zhang 0, 130740d92e34SHong Zhang MatMatMultNumeric_Elemental, 130840d92e34SHong Zhang 0, 130940d92e34SHong Zhang 0, 131040d92e34SHong Zhang /*94*/ 0, 13114222ddf1SHong Zhang 0, 13124222ddf1SHong Zhang 0, 1313df311e6cSXuan Zhou MatMatTransposeMultNumeric_Elemental, 131440d92e34SHong Zhang 0, 13154222ddf1SHong Zhang /*99*/ MatProductSetFromOptions_Elemental, 131640d92e34SHong Zhang 0, 131740d92e34SHong Zhang 0, 1318dfcb0403SXuan Zhou MatConjugate_Elemental, 131940d92e34SHong Zhang 0, 132040d92e34SHong Zhang /*104*/0, 132140d92e34SHong Zhang 0, 132240d92e34SHong Zhang 0, 132340d92e34SHong Zhang 0, 132440d92e34SHong Zhang 0, 132540d92e34SHong Zhang /*109*/MatMatSolve_Elemental, 132640d92e34SHong Zhang 0, 132740d92e34SHong Zhang 0, 132840d92e34SHong Zhang 0, 132934fa46e1SFrancesco Ballarin MatMissingDiagonal_Elemental, 133040d92e34SHong Zhang /*114*/0, 133140d92e34SHong Zhang 0, 133240d92e34SHong Zhang 0, 133340d92e34SHong Zhang 0, 133440d92e34SHong Zhang 0, 133540d92e34SHong Zhang /*119*/0, 13364a29722dSXuan Zhou MatHermitianTranspose_Elemental, 133740d92e34SHong Zhang 0, 133840d92e34SHong Zhang 0, 133940d92e34SHong Zhang 0, 134040d92e34SHong Zhang /*124*/0, 134140d92e34SHong Zhang 0, 134240d92e34SHong Zhang 0, 134340d92e34SHong Zhang 0, 134440d92e34SHong Zhang 0, 134540d92e34SHong Zhang /*129*/0, 134640d92e34SHong Zhang 0, 134740d92e34SHong Zhang 0, 134840d92e34SHong Zhang 0, 134940d92e34SHong Zhang 0, 135040d92e34SHong Zhang /*134*/0, 135140d92e34SHong Zhang 0, 135240d92e34SHong Zhang 0, 135340d92e34SHong Zhang 0, 13544222ddf1SHong Zhang 0, 13554222ddf1SHong Zhang 0, 13564222ddf1SHong Zhang /*140*/0, 13574222ddf1SHong Zhang 0, 13584222ddf1SHong Zhang 0, 13594222ddf1SHong Zhang 0, 13604222ddf1SHong Zhang 0, 13614222ddf1SHong Zhang /*145*/0, 13624222ddf1SHong Zhang 0, 136340d92e34SHong Zhang 0 136440d92e34SHong Zhang }; 136540d92e34SHong Zhang 1366ed36708cSHong Zhang /*MC 1367ed36708cSHong Zhang MATELEMENTAL = "elemental" - A matrix type for dense matrices using the Elemental package 1368ed36708cSHong Zhang 1369c2b89b5dSBarry Smith Use ./configure --download-elemental to install PETSc to use Elemental 1370c2b89b5dSBarry Smith 13713ca39a21SBarry Smith Use -pc_type lu -pc_factor_mat_solver_type elemental to use this direct solver 1372c2b89b5dSBarry Smith 1373ed36708cSHong Zhang Options Database Keys: 13745cc86fc1SJed Brown + -mat_type elemental - sets the matrix type to "elemental" during a call to MatSetFromOptions() 13755cc86fc1SJed Brown - -mat_elemental_grid_height - sets Grid Height for 2D cyclic ordering of internal matrix 1376ed36708cSHong Zhang 1377ed36708cSHong Zhang Level: beginner 1378ed36708cSHong Zhang 13795cb544a0SHong Zhang .seealso: MATDENSE 1380ed36708cSHong Zhang M*/ 13814a29722dSXuan Zhou 13828cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Elemental(Mat A) 1383db31f6deSJed Brown { 1384db31f6deSJed Brown Mat_Elemental *a; 1385db31f6deSJed Brown PetscErrorCode ierr; 13865682a260SJack Poulson PetscBool flg,flg1; 13875e9f5b67SHong Zhang Mat_Elemental_Grid *commgrid; 13885e9f5b67SHong Zhang MPI_Comm icomm; 13895682a260SJack Poulson PetscInt optv1; 1390db31f6deSJed Brown 1391db31f6deSJed Brown PetscFunctionBegin; 139240d92e34SHong Zhang ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 139340d92e34SHong Zhang A->insertmode = NOT_SET_VALUES; 1394db31f6deSJed Brown 1395b00a9115SJed Brown ierr = PetscNewLog(A,&a);CHKERRQ(ierr); 1396db31f6deSJed Brown A->data = (void*)a; 1397db31f6deSJed Brown 1398db31f6deSJed Brown /* Set up the elemental matrix */ 1399e8146892SSatish Balay El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A)); 14005e9f5b67SHong Zhang 14015e9f5b67SHong Zhang /* Grid needs to be shared between multiple Mats on the same communicator, implement by attribute caching on the MPI_Comm */ 14025e9f5b67SHong Zhang if (Petsc_Elemental_keyval == MPI_KEYVAL_INVALID) { 1403ffc4695bSBarry Smith ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Elemental_keyval,(void*)0);CHKERRMPI(ierr); 140427e75052SPierre Jolivet ierr = PetscCitationsRegister(ElementalCitation,&ElementalCite);CHKERRQ(ierr); 14055e9f5b67SHong Zhang } 14060c18141cSBarry Smith ierr = PetscCommDuplicate(cxxcomm.comm,&icomm,NULL);CHKERRQ(ierr); 1407ffc4695bSBarry Smith ierr = MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRMPI(ierr); 14085e9f5b67SHong Zhang if (!flg) { 1409b00a9115SJed Brown ierr = PetscNewLog(A,&commgrid);CHKERRQ(ierr); 14105cb544a0SHong Zhang 1411ce94432eSBarry Smith ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"Elemental Options","Mat");CHKERRQ(ierr); 1412e8146892SSatish Balay /* displayed default grid sizes (CommSize,1) are set by us arbitrarily until El::Grid() is called */ 1413e8146892SSatish Balay ierr = PetscOptionsInt("-mat_elemental_grid_height","Grid Height","None",El::mpi::Size(cxxcomm),&optv1,&flg1);CHKERRQ(ierr); 14145682a260SJack Poulson if (flg1) { 1415d8304050SJose E. Roman if (El::mpi::Size(cxxcomm) % optv1) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Grid Height %D must evenly divide CommSize %D",optv1,(PetscInt)El::mpi::Size(cxxcomm)); 1416e8146892SSatish Balay commgrid->grid = new El::Grid(cxxcomm,optv1); /* use user-provided grid height */ 14172ef0cf24SXuan Zhou } else { 1418e8146892SSatish Balay commgrid->grid = new El::Grid(cxxcomm); /* use Elemental default grid sizes */ 1419da0640a4SHong Zhang /* printf("new commgrid->grid = %p\n",commgrid->grid); -- memory leak revealed by valgrind? */ 1420ed667823SXuan Zhou } 14215e9f5b67SHong Zhang commgrid->grid_refct = 1; 1422ffc4695bSBarry Smith ierr = MPI_Comm_set_attr(icomm,Petsc_Elemental_keyval,(void*)commgrid);CHKERRMPI(ierr); 1423ea394475SSatish Balay 1424ea394475SSatish Balay a->pivoting = 1; 1425ea394475SSatish Balay ierr = PetscOptionsInt("-mat_elemental_pivoting","Pivoting","None",a->pivoting,&a->pivoting,NULL);CHKERRQ(ierr); 1426ea394475SSatish Balay 14272a808120SBarry Smith ierr = PetscOptionsEnd();CHKERRQ(ierr); 14285e9f5b67SHong Zhang } else { 14295e9f5b67SHong Zhang commgrid->grid_refct++; 14305e9f5b67SHong Zhang } 14315e9f5b67SHong Zhang ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr); 14325e9f5b67SHong Zhang a->grid = commgrid->grid; 1433e8146892SSatish Balay a->emat = new El::DistMatrix<PetscElemScalar>(*a->grid); 143432d7a744SHong Zhang a->roworiented = PETSC_TRUE; 1435db31f6deSJed Brown 1436bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",MatGetOwnershipIS_Elemental);CHKERRQ(ierr); 1437f6e5db1bSPierre Jolivet ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_elemental_mpidense_C",MatProductSetFromOptions_Elemental_MPIDense);CHKERRQ(ierr); 1438db31f6deSJed Brown ierr = PetscObjectChangeTypeName((PetscObject)A,MATELEMENTAL);CHKERRQ(ierr); 1439db31f6deSJed Brown PetscFunctionReturn(0); 1440db31f6deSJed Brown } 1441