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 Mat_Elemental *a = (Mat_Elemental*)A->data; 22db31f6deSJed Brown PetscBool iascii; 23db31f6deSJed Brown 24db31f6deSJed Brown PetscFunctionBegin; 259566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 26db31f6deSJed Brown if (iascii) { 27db31f6deSJed Brown PetscViewerFormat format; 289566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer,&format)); 29db31f6deSJed Brown if (format == PETSC_VIEWER_ASCII_INFO) { 3079673f7bSHong Zhang /* call elemental viewing function */ 319566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer,"Elemental run parameters:\n")); 3263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," allocated entries=%zu\n",(*a->emat).AllocatedMemory())); 339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," grid height=%d, grid width=%d\n",(*a->emat).Grid().Height(),(*a->emat).Grid().Width())); 344fe7bbcaSHong Zhang if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 3579673f7bSHong Zhang /* call elemental viewing function */ 369566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PetscObjectComm((PetscObject)viewer),"test matview_elemental 2\n")); 374fe7bbcaSHong Zhang } 3879673f7bSHong Zhang 39db31f6deSJed Brown } else if (format == PETSC_VIEWER_DEFAULT) { 409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE)); 41e8146892SSatish Balay El::Print( *a->emat, "Elemental matrix (cyclic ordering)"); 429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE)); 43834d3fecSHong Zhang if (A->factortype == MAT_FACTOR_NONE) { 4461119200SXuan Zhou Mat Adense; 459566063dSJacob Faibussowitsch PetscCall(MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense)); 469566063dSJacob Faibussowitsch PetscCall(MatView(Adense,viewer)); 479566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Adense)); 48834d3fecSHong Zhang } 49ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Format"); 50d2daa67eSHong Zhang } else { 515cb544a0SHong Zhang /* convert to dense format and call MatView() */ 5261119200SXuan Zhou Mat Adense; 539566063dSJacob Faibussowitsch PetscCall(MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense)); 549566063dSJacob Faibussowitsch PetscCall(MatView(Adense,viewer)); 559566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Adense)); 56d2daa67eSHong Zhang } 57db31f6deSJed Brown PetscFunctionReturn(0); 58db31f6deSJed Brown } 59db31f6deSJed Brown 6015767789SHong Zhang static PetscErrorCode MatGetInfo_Elemental(Mat A,MatInfoType flag,MatInfo *info) 61180a43e4SHong Zhang { 6215767789SHong Zhang Mat_Elemental *a = (Mat_Elemental*)A->data; 6315767789SHong Zhang 64180a43e4SHong Zhang PetscFunctionBegin; 655cb544a0SHong Zhang info->block_size = 1.0; 6615767789SHong Zhang 6715767789SHong Zhang if (flag == MAT_LOCAL) { 683966268fSBarry Smith info->nz_allocated = (*a->emat).AllocatedMemory(); /* locally allocated */ 6915767789SHong Zhang info->nz_used = info->nz_allocated; 7015767789SHong Zhang } else if (flag == MAT_GLOBAL_MAX) { 711c2dc1cbSBarry Smith //PetscCall(MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)matin))); 7215767789SHong Zhang /* see MatGetInfo_MPIAIJ() for getting global info->nz_allocated! */ 7315767789SHong Zhang //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_MAX not written yet"); 7415767789SHong Zhang } else if (flag == MAT_GLOBAL_SUM) { 7515767789SHong Zhang //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_SUM not written yet"); 763966268fSBarry Smith info->nz_allocated = (*a->emat).AllocatedMemory(); /* locally allocated */ 7715767789SHong Zhang info->nz_used = info->nz_allocated; /* assume Elemental does accurate allocation */ 781c2dc1cbSBarry Smith //PetscCall(MPIU_Allreduce(isend,irecv,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A))); 7915767789SHong Zhang //PetscPrintf(PETSC_COMM_SELF," ... [%d] locally allocated %g\n",rank,info->nz_allocated); 8015767789SHong Zhang } 8115767789SHong Zhang 8215767789SHong Zhang info->nz_unneeded = 0.0; 833966268fSBarry Smith info->assemblies = A->num_ass; 8415767789SHong Zhang info->mallocs = 0; 8515767789SHong Zhang info->memory = ((PetscObject)A)->mem; 8615767789SHong Zhang info->fill_ratio_given = 0; /* determined by Elemental */ 8715767789SHong Zhang info->fill_ratio_needed = 0; 8815767789SHong Zhang info->factor_mallocs = 0; 89180a43e4SHong Zhang PetscFunctionReturn(0); 90180a43e4SHong Zhang } 91180a43e4SHong Zhang 9232d7a744SHong Zhang PetscErrorCode MatSetOption_Elemental(Mat A,MatOption op,PetscBool flg) 9332d7a744SHong Zhang { 9432d7a744SHong Zhang Mat_Elemental *a = (Mat_Elemental*)A->data; 9532d7a744SHong Zhang 9632d7a744SHong Zhang PetscFunctionBegin; 9732d7a744SHong Zhang switch (op) { 9832d7a744SHong Zhang case MAT_NEW_NONZERO_LOCATIONS: 9932d7a744SHong Zhang case MAT_NEW_NONZERO_LOCATION_ERR: 10032d7a744SHong Zhang case MAT_NEW_NONZERO_ALLOCATION_ERR: 101891a0571SHong Zhang case MAT_SYMMETRIC: 102071fcb05SBarry Smith case MAT_SORTED_FULL: 103eb1ec7c1SStefano Zampini case MAT_HERMITIAN: 104891a0571SHong Zhang break; 10532d7a744SHong Zhang case MAT_ROW_ORIENTED: 10632d7a744SHong Zhang a->roworiented = flg; 10732d7a744SHong Zhang break; 10832d7a744SHong Zhang default: 10998921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %s",MatOptions[op]); 11032d7a744SHong Zhang } 11132d7a744SHong Zhang PetscFunctionReturn(0); 11232d7a744SHong Zhang } 11332d7a744SHong Zhang 114e6dea9dbSXuan Zhou static PetscErrorCode MatSetValues_Elemental(Mat A,PetscInt nr,const PetscInt *rows,PetscInt nc,const PetscInt *cols,const PetscScalar *vals,InsertMode imode) 115db31f6deSJed Brown { 116db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 117fbbcb730SJack Poulson PetscInt i,j,rrank,ridx,crank,cidx,erow,ecol,numQueues=0; 118db31f6deSJed Brown 119db31f6deSJed Brown PetscFunctionBegin; 120fbbcb730SJack Poulson // TODO: Initialize matrix to all zeros? 121fbbcb730SJack Poulson 122fbbcb730SJack Poulson // Count the number of queues from this process 12332d7a744SHong Zhang if (a->roworiented) { 124db31f6deSJed Brown for (i=0; i<nr; i++) { 125db31f6deSJed Brown if (rows[i] < 0) continue; 126db31f6deSJed Brown P2RO(A,0,rows[i],&rrank,&ridx); 127db31f6deSJed Brown RO2E(A,0,rrank,ridx,&erow); 128aed4548fSBarry Smith PetscCheck(rrank >= 0 && ridx >= 0 && erow >= 0,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect row translation"); 129db31f6deSJed Brown for (j=0; j<nc; j++) { 130db31f6deSJed Brown if (cols[j] < 0) continue; 131db31f6deSJed Brown P2RO(A,1,cols[j],&crank,&cidx); 132db31f6deSJed Brown RO2E(A,1,crank,cidx,&ecol); 133aed4548fSBarry Smith PetscCheck(crank >= 0 && cidx >= 0 && ecol >= 0,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect col translation"); 134fbbcb730SJack Poulson if (!a->emat->IsLocal(erow,ecol)) { /* off-proc entry */ 135fbbcb730SJack Poulson /* printf("Will later remotely update (%d,%d)\n",erow,ecol); */ 13608401ef6SPierre Jolivet PetscCheck(imode == ADD_VALUES,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported"); 137fbbcb730SJack Poulson ++numQueues; 138aae2c449SHong Zhang continue; 139ed36708cSHong Zhang } 140fbbcb730SJack Poulson /* printf("Locally updating (%d,%d)\n",erow,ecol); */ 141db31f6deSJed Brown switch (imode) { 142fbbcb730SJack Poulson case INSERT_VALUES: a->emat->Set(erow,ecol,(PetscElemScalar)vals[i*nc+j]); break; 143fbbcb730SJack Poulson case ADD_VALUES: a->emat->Update(erow,ecol,(PetscElemScalar)vals[i*nc+j]); break; 14498921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode); 145db31f6deSJed Brown } 146db31f6deSJed Brown } 147db31f6deSJed Brown } 148fbbcb730SJack Poulson 149fbbcb730SJack Poulson /* printf("numQueues=%d\n",numQueues); */ 150fbbcb730SJack Poulson a->emat->Reserve( numQueues); 151fbbcb730SJack Poulson for (i=0; i<nr; i++) { 152fbbcb730SJack Poulson if (rows[i] < 0) continue; 153fbbcb730SJack Poulson P2RO(A,0,rows[i],&rrank,&ridx); 154fbbcb730SJack Poulson RO2E(A,0,rrank,ridx,&erow); 155fbbcb730SJack Poulson for (j=0; j<nc; j++) { 156fbbcb730SJack Poulson if (cols[j] < 0) continue; 157fbbcb730SJack Poulson P2RO(A,1,cols[j],&crank,&cidx); 158fbbcb730SJack Poulson RO2E(A,1,crank,cidx,&ecol); 159fbbcb730SJack Poulson if (!a->emat->IsLocal(erow,ecol)) { /*off-proc entry*/ 160fbbcb730SJack Poulson /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */ 161fbbcb730SJack Poulson a->emat->QueueUpdate( erow, ecol, vals[i*nc+j]); 162fbbcb730SJack Poulson } 163fbbcb730SJack Poulson } 164fbbcb730SJack Poulson } 16532d7a744SHong Zhang } else { /* columnoriented */ 16632d7a744SHong Zhang for (j=0; j<nc; j++) { 16732d7a744SHong Zhang if (cols[j] < 0) continue; 16832d7a744SHong Zhang P2RO(A,1,cols[j],&crank,&cidx); 16932d7a744SHong Zhang RO2E(A,1,crank,cidx,&ecol); 170aed4548fSBarry Smith PetscCheck(crank >= 0 && cidx >= 0 && ecol >= 0,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect col translation"); 17132d7a744SHong Zhang for (i=0; i<nr; i++) { 17232d7a744SHong Zhang if (rows[i] < 0) continue; 17332d7a744SHong Zhang P2RO(A,0,rows[i],&rrank,&ridx); 17432d7a744SHong Zhang RO2E(A,0,rrank,ridx,&erow); 175aed4548fSBarry Smith PetscCheck(rrank >= 0 && ridx >= 0 && erow >= 0,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect row translation"); 17632d7a744SHong Zhang if (!a->emat->IsLocal(erow,ecol)) { /* off-proc entry */ 17732d7a744SHong Zhang /* printf("Will later remotely update (%d,%d)\n",erow,ecol); */ 17808401ef6SPierre Jolivet PetscCheck(imode == ADD_VALUES,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported"); 17932d7a744SHong Zhang ++numQueues; 18032d7a744SHong Zhang continue; 18132d7a744SHong Zhang } 18232d7a744SHong Zhang /* printf("Locally updating (%d,%d)\n",erow,ecol); */ 18332d7a744SHong Zhang switch (imode) { 18432d7a744SHong Zhang case INSERT_VALUES: a->emat->Set(erow,ecol,(PetscElemScalar)vals[i+j*nr]); break; 18532d7a744SHong Zhang case ADD_VALUES: a->emat->Update(erow,ecol,(PetscElemScalar)vals[i+j*nr]); break; 18698921bdaSJacob Faibussowitsch default: SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode); 18732d7a744SHong Zhang } 18832d7a744SHong Zhang } 18932d7a744SHong Zhang } 19032d7a744SHong Zhang 19132d7a744SHong Zhang /* printf("numQueues=%d\n",numQueues); */ 19232d7a744SHong Zhang a->emat->Reserve( numQueues); 19332d7a744SHong Zhang for (j=0; j<nc; j++) { 19432d7a744SHong Zhang if (cols[j] < 0) continue; 19532d7a744SHong Zhang P2RO(A,1,cols[j],&crank,&cidx); 19632d7a744SHong Zhang RO2E(A,1,crank,cidx,&ecol); 19732d7a744SHong Zhang 19832d7a744SHong Zhang for (i=0; i<nr; i++) { 19932d7a744SHong Zhang if (rows[i] < 0) continue; 20032d7a744SHong Zhang P2RO(A,0,rows[i],&rrank,&ridx); 20132d7a744SHong Zhang RO2E(A,0,rrank,ridx,&erow); 20232d7a744SHong Zhang if (!a->emat->IsLocal(erow,ecol)) { /*off-proc entry*/ 20332d7a744SHong Zhang /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */ 20432d7a744SHong Zhang a->emat->QueueUpdate( erow, ecol, vals[i+j*nr]); 20532d7a744SHong Zhang } 20632d7a744SHong Zhang } 20732d7a744SHong Zhang } 20832d7a744SHong Zhang } 209db31f6deSJed Brown PetscFunctionReturn(0); 210db31f6deSJed Brown } 211db31f6deSJed Brown 212db31f6deSJed Brown static PetscErrorCode MatMult_Elemental(Mat A,Vec X,Vec Y) 213db31f6deSJed Brown { 214db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 215e6dea9dbSXuan Zhou const PetscElemScalar *x; 216e6dea9dbSXuan Zhou PetscElemScalar *y; 217df311e6cSXuan Zhou PetscElemScalar one = 1,zero = 0; 218db31f6deSJed Brown 219db31f6deSJed Brown PetscFunctionBegin; 2209566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X,(const PetscScalar **)&x)); 2219566063dSJacob Faibussowitsch PetscCall(VecGetArray(Y,(PetscScalar **)&y)); 222db31f6deSJed Brown { /* Scoping so that constructor is called before pointer is returned */ 223e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ye; 2240c18141cSBarry Smith xe.LockedAttach(A->cmap->N,1,*a->grid,0,0,x,A->cmap->n); 2250c18141cSBarry Smith ye.Attach(A->rmap->N,1,*a->grid,0,0,y,A->rmap->n); 226e8146892SSatish Balay El::Gemv(El::NORMAL,one,*a->emat,xe,zero,ye); 227db31f6deSJed Brown } 2289566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X,(const PetscScalar **)&x)); 2299566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(Y,(PetscScalar **)&y)); 230db31f6deSJed Brown PetscFunctionReturn(0); 231db31f6deSJed Brown } 232db31f6deSJed Brown 2339426833fSXuan Zhou static PetscErrorCode MatMultTranspose_Elemental(Mat A,Vec X,Vec Y) 2349426833fSXuan Zhou { 2359426833fSXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 236df311e6cSXuan Zhou const PetscElemScalar *x; 237df311e6cSXuan Zhou PetscElemScalar *y; 238e6dea9dbSXuan Zhou PetscElemScalar one = 1,zero = 0; 2399426833fSXuan Zhou 2409426833fSXuan Zhou PetscFunctionBegin; 2419566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X,(const PetscScalar **)&x)); 2429566063dSJacob Faibussowitsch PetscCall(VecGetArray(Y,(PetscScalar **)&y)); 2439426833fSXuan Zhou { /* Scoping so that constructor is called before pointer is returned */ 244e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ye; 2450c18141cSBarry Smith xe.LockedAttach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n); 2460c18141cSBarry Smith ye.Attach(A->cmap->N,1,*a->grid,0,0,y,A->cmap->n); 247e8146892SSatish Balay El::Gemv(El::TRANSPOSE,one,*a->emat,xe,zero,ye); 2489426833fSXuan Zhou } 2499566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X,(const PetscScalar **)&x)); 2509566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(Y,(PetscScalar **)&y)); 2519426833fSXuan Zhou PetscFunctionReturn(0); 2529426833fSXuan Zhou } 2539426833fSXuan Zhou 254db31f6deSJed Brown static PetscErrorCode MatMultAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z) 255db31f6deSJed Brown { 256db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 257df311e6cSXuan Zhou const PetscElemScalar *x; 258df311e6cSXuan Zhou PetscElemScalar *z; 259e6dea9dbSXuan Zhou PetscElemScalar one = 1; 260db31f6deSJed Brown 261db31f6deSJed Brown PetscFunctionBegin; 2629566063dSJacob Faibussowitsch if (Y != Z) PetscCall(VecCopy(Y,Z)); 2639566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X,(const PetscScalar **)&x)); 2649566063dSJacob Faibussowitsch PetscCall(VecGetArray(Z,(PetscScalar **)&z)); 265db31f6deSJed Brown { /* Scoping so that constructor is called before pointer is returned */ 266e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ze; 2670c18141cSBarry Smith xe.LockedAttach(A->cmap->N,1,*a->grid,0,0,x,A->cmap->n); 2680c18141cSBarry Smith ze.Attach(A->rmap->N,1,*a->grid,0,0,z,A->rmap->n); 269e8146892SSatish Balay El::Gemv(El::NORMAL,one,*a->emat,xe,one,ze); 270db31f6deSJed Brown } 2719566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X,(const PetscScalar **)&x)); 2729566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(Z,(PetscScalar **)&z)); 273db31f6deSJed Brown PetscFunctionReturn(0); 274db31f6deSJed Brown } 275db31f6deSJed Brown 276e883f9d5SXuan Zhou static PetscErrorCode MatMultTransposeAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z) 277e883f9d5SXuan Zhou { 278e883f9d5SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 279df311e6cSXuan Zhou const PetscElemScalar *x; 280df311e6cSXuan Zhou PetscElemScalar *z; 281e6dea9dbSXuan Zhou PetscElemScalar one = 1; 282e883f9d5SXuan Zhou 283e883f9d5SXuan Zhou PetscFunctionBegin; 2849566063dSJacob Faibussowitsch if (Y != Z) PetscCall(VecCopy(Y,Z)); 2859566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X,(const PetscScalar **)&x)); 2869566063dSJacob Faibussowitsch PetscCall(VecGetArray(Z,(PetscScalar **)&z)); 287e883f9d5SXuan Zhou { /* Scoping so that constructor is called before pointer is returned */ 288e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ze; 2890c18141cSBarry Smith xe.LockedAttach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n); 2900c18141cSBarry Smith ze.Attach(A->cmap->N,1,*a->grid,0,0,z,A->cmap->n); 291e8146892SSatish Balay El::Gemv(El::TRANSPOSE,one,*a->emat,xe,one,ze); 292e883f9d5SXuan Zhou } 2939566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X,(const PetscScalar **)&x)); 2949566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(Z,(PetscScalar **)&z)); 295e883f9d5SXuan Zhou PetscFunctionReturn(0); 296e883f9d5SXuan Zhou } 297e883f9d5SXuan Zhou 2984222ddf1SHong Zhang PetscErrorCode MatMatMultNumeric_Elemental(Mat A,Mat B,Mat C) 299c1d1b975SXuan Zhou { 300c1d1b975SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 301c1d1b975SXuan Zhou Mat_Elemental *b = (Mat_Elemental*)B->data; 3029a9e8502SHong Zhang Mat_Elemental *c = (Mat_Elemental*)C->data; 303e6dea9dbSXuan Zhou PetscElemScalar one = 1,zero = 0; 304c1d1b975SXuan Zhou 305c1d1b975SXuan Zhou PetscFunctionBegin; 306aae2c449SHong Zhang { /* Scoping so that constructor is called before pointer is returned */ 307e8146892SSatish Balay El::Gemm(El::NORMAL,El::NORMAL,one,*a->emat,*b->emat,zero,*c->emat); 308aae2c449SHong Zhang } 3099a9e8502SHong Zhang C->assembled = PETSC_TRUE; 3109a9e8502SHong Zhang PetscFunctionReturn(0); 3119a9e8502SHong Zhang } 3129a9e8502SHong Zhang 3134222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat Ce) 3149a9e8502SHong Zhang { 3159a9e8502SHong Zhang PetscFunctionBegin; 3169566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Ce,A->rmap->n,B->cmap->n,PETSC_DECIDE,PETSC_DECIDE)); 3179566063dSJacob Faibussowitsch PetscCall(MatSetType(Ce,MATELEMENTAL)); 3189566063dSJacob Faibussowitsch PetscCall(MatSetUp(Ce)); 3194222ddf1SHong Zhang Ce->ops->matmultnumeric = MatMatMultNumeric_Elemental; 320c1d1b975SXuan Zhou PetscFunctionReturn(0); 321c1d1b975SXuan Zhou } 322c1d1b975SXuan Zhou 323df311e6cSXuan Zhou static PetscErrorCode MatMatTransposeMultNumeric_Elemental(Mat A,Mat B,Mat C) 324df311e6cSXuan Zhou { 325df311e6cSXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 326df311e6cSXuan Zhou Mat_Elemental *b = (Mat_Elemental*)B->data; 327df311e6cSXuan Zhou Mat_Elemental *c = (Mat_Elemental*)C->data; 328e6dea9dbSXuan Zhou PetscElemScalar one = 1,zero = 0; 329df311e6cSXuan Zhou 330df311e6cSXuan Zhou PetscFunctionBegin; 331df311e6cSXuan Zhou { /* Scoping so that constructor is called before pointer is returned */ 332e8146892SSatish Balay El::Gemm(El::NORMAL,El::TRANSPOSE,one,*a->emat,*b->emat,zero,*c->emat); 333df311e6cSXuan Zhou } 334df311e6cSXuan Zhou C->assembled = PETSC_TRUE; 335df311e6cSXuan Zhou PetscFunctionReturn(0); 336df311e6cSXuan Zhou } 337df311e6cSXuan Zhou 3384222ddf1SHong Zhang static PetscErrorCode MatMatTransposeMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat C) 339df311e6cSXuan Zhou { 340df311e6cSXuan Zhou PetscFunctionBegin; 3419566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,A->rmap->n,B->rmap->n,PETSC_DECIDE,PETSC_DECIDE)); 3429566063dSJacob Faibussowitsch PetscCall(MatSetType(C,MATELEMENTAL)); 3439566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 344df311e6cSXuan Zhou PetscFunctionReturn(0); 345df311e6cSXuan Zhou } 346df311e6cSXuan Zhou 3474222ddf1SHong Zhang /* --------------------------------------- */ 3484222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_Elemental_AB(Mat C) 3494222ddf1SHong Zhang { 3504222ddf1SHong Zhang PetscFunctionBegin; 3514222ddf1SHong Zhang C->ops->matmultsymbolic = MatMatMultSymbolic_Elemental; 3524222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_AB; 3534222ddf1SHong Zhang PetscFunctionReturn(0); 3544222ddf1SHong Zhang } 3554222ddf1SHong Zhang 3564222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_Elemental_ABt(Mat C) 3574222ddf1SHong Zhang { 3584222ddf1SHong Zhang PetscFunctionBegin; 3594222ddf1SHong Zhang C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_Elemental; 3604222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_ABt; 3614222ddf1SHong Zhang PetscFunctionReturn(0); 3624222ddf1SHong Zhang } 3634222ddf1SHong Zhang 3644222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Elemental(Mat C) 3654222ddf1SHong Zhang { 3664222ddf1SHong Zhang Mat_Product *product = C->product; 3674222ddf1SHong Zhang 3684222ddf1SHong Zhang PetscFunctionBegin; 3694222ddf1SHong Zhang switch (product->type) { 3704222ddf1SHong Zhang case MATPRODUCT_AB: 3719566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Elemental_AB(C)); 3724222ddf1SHong Zhang break; 3734222ddf1SHong Zhang case MATPRODUCT_ABt: 3749566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Elemental_ABt(C)); 3754222ddf1SHong Zhang break; 3766718818eSStefano Zampini default: 3776718818eSStefano Zampini break; 3784222ddf1SHong Zhang } 3794222ddf1SHong Zhang PetscFunctionReturn(0); 3804222ddf1SHong Zhang } 381f6e5db1bSPierre Jolivet 382f6e5db1bSPierre Jolivet PetscErrorCode MatMatMultNumeric_Elemental_MPIDense(Mat A,Mat B,Mat C) 383f6e5db1bSPierre Jolivet { 384f6e5db1bSPierre Jolivet Mat Be,Ce; 385f6e5db1bSPierre Jolivet 386f6e5db1bSPierre Jolivet PetscFunctionBegin; 3879566063dSJacob Faibussowitsch PetscCall(MatConvert(B,MATELEMENTAL,MAT_INITIAL_MATRIX,&Be)); 3889566063dSJacob Faibussowitsch PetscCall(MatMatMult(A,Be,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&Ce)); 3899566063dSJacob Faibussowitsch PetscCall(MatConvert(Ce,MATMPIDENSE,MAT_REUSE_MATRIX,&C)); 3909566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Be)); 3919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ce)); 392f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 393f6e5db1bSPierre Jolivet } 394f6e5db1bSPierre Jolivet 395f6e5db1bSPierre Jolivet PetscErrorCode MatMatMultSymbolic_Elemental_MPIDense(Mat A,Mat B,PetscReal fill,Mat C) 396f6e5db1bSPierre Jolivet { 397f6e5db1bSPierre Jolivet PetscFunctionBegin; 3989566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C,A->rmap->n,B->cmap->n,PETSC_DECIDE,PETSC_DECIDE)); 3999566063dSJacob Faibussowitsch PetscCall(MatSetType(C,MATMPIDENSE)); 4009566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 401f6e5db1bSPierre Jolivet C->ops->matmultnumeric = MatMatMultNumeric_Elemental_MPIDense; 402f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 403f6e5db1bSPierre Jolivet } 404f6e5db1bSPierre Jolivet 405f6e5db1bSPierre Jolivet PetscErrorCode MatProductSetFromOptions_Elemental_MPIDense_AB(Mat C) 406f6e5db1bSPierre Jolivet { 407f6e5db1bSPierre Jolivet PetscFunctionBegin; 408f6e5db1bSPierre Jolivet C->ops->matmultsymbolic = MatMatMultSymbolic_Elemental_MPIDense; 409f6e5db1bSPierre Jolivet C->ops->productsymbolic = MatProductSymbolic_AB; 410f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 411f6e5db1bSPierre Jolivet } 412f6e5db1bSPierre Jolivet 413f6e5db1bSPierre Jolivet PetscErrorCode MatProductSetFromOptions_Elemental_MPIDense(Mat C) 414f6e5db1bSPierre Jolivet { 415f6e5db1bSPierre Jolivet Mat_Product *product = C->product; 416f6e5db1bSPierre Jolivet 417f6e5db1bSPierre Jolivet PetscFunctionBegin; 418f6e5db1bSPierre Jolivet if (product->type == MATPRODUCT_AB) { 4199566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Elemental_MPIDense_AB(C)); 420f6e5db1bSPierre Jolivet } 421f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 422f6e5db1bSPierre Jolivet } 4234222ddf1SHong Zhang /* --------------------------------------- */ 4244222ddf1SHong Zhang 425a9d89745SXuan Zhou static PetscErrorCode MatGetDiagonal_Elemental(Mat A,Vec D) 42661119200SXuan Zhou { 427a9d89745SXuan Zhou PetscInt i,nrows,ncols,nD,rrank,ridx,crank,cidx; 428a9d89745SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 429a9d89745SXuan Zhou PetscElemScalar v; 430ce94432eSBarry Smith MPI_Comm comm; 43161119200SXuan Zhou 43261119200SXuan Zhou PetscFunctionBegin; 4339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 4349566063dSJacob Faibussowitsch PetscCall(MatGetSize(A,&nrows,&ncols)); 435a9d89745SXuan Zhou nD = nrows>ncols ? ncols : nrows; 436a9d89745SXuan Zhou for (i=0; i<nD; i++) { 437a9d89745SXuan Zhou PetscInt erow,ecol; 438a9d89745SXuan Zhou P2RO(A,0,i,&rrank,&ridx); 439a9d89745SXuan Zhou RO2E(A,0,rrank,ridx,&erow); 440aed4548fSBarry Smith PetscCheck(rrank >= 0 && ridx >= 0 && erow >= 0,comm,PETSC_ERR_PLIB,"Incorrect row translation"); 441a9d89745SXuan Zhou P2RO(A,1,i,&crank,&cidx); 442a9d89745SXuan Zhou RO2E(A,1,crank,cidx,&ecol); 443aed4548fSBarry Smith PetscCheck(crank >= 0 && cidx >= 0 && ecol >= 0,comm,PETSC_ERR_PLIB,"Incorrect col translation"); 444a9d89745SXuan Zhou v = a->emat->Get(erow,ecol); 4459566063dSJacob Faibussowitsch PetscCall(VecSetValues(D,1,&i,(PetscScalar*)&v,INSERT_VALUES)); 446ade3cc5eSXuan Zhou } 4479566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(D)); 4489566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(D)); 44961119200SXuan Zhou PetscFunctionReturn(0); 45061119200SXuan Zhou } 45161119200SXuan Zhou 452ade3cc5eSXuan Zhou static PetscErrorCode MatDiagonalScale_Elemental(Mat X,Vec L,Vec R) 453ade3cc5eSXuan Zhou { 454ade3cc5eSXuan Zhou Mat_Elemental *x = (Mat_Elemental*)X->data; 455ade3cc5eSXuan Zhou const PetscElemScalar *d; 456ade3cc5eSXuan Zhou 457ade3cc5eSXuan Zhou PetscFunctionBegin; 4589065cd98SJed Brown if (R) { 4599566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(R,(const PetscScalar **)&d)); 460e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de; 4610c18141cSBarry Smith de.LockedAttach(X->cmap->N,1,*x->grid,0,0,d,X->cmap->n); 462e8146892SSatish Balay El::DiagonalScale(El::RIGHT,El::NORMAL,de,*x->emat); 4639566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(R,(const PetscScalar **)&d)); 4649065cd98SJed Brown } 4659065cd98SJed Brown if (L) { 4669566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(L,(const PetscScalar **)&d)); 467e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de; 4680c18141cSBarry Smith de.LockedAttach(X->rmap->N,1,*x->grid,0,0,d,X->rmap->n); 469e8146892SSatish Balay El::DiagonalScale(El::LEFT,El::NORMAL,de,*x->emat); 4709566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(L,(const PetscScalar **)&d)); 471ade3cc5eSXuan Zhou } 472ade3cc5eSXuan Zhou PetscFunctionReturn(0); 473ade3cc5eSXuan Zhou } 474ade3cc5eSXuan Zhou 47534fa46e1SFrancesco Ballarin static PetscErrorCode MatMissingDiagonal_Elemental(Mat A,PetscBool *missing,PetscInt *d) 47634fa46e1SFrancesco Ballarin { 47734fa46e1SFrancesco Ballarin PetscFunctionBegin; 47834fa46e1SFrancesco Ballarin *missing = PETSC_FALSE; 47934fa46e1SFrancesco Ballarin PetscFunctionReturn(0); 48034fa46e1SFrancesco Ballarin } 48134fa46e1SFrancesco Ballarin 482e6dea9dbSXuan Zhou static PetscErrorCode MatScale_Elemental(Mat X,PetscScalar a) 48365b78793SXuan Zhou { 48465b78793SXuan Zhou Mat_Elemental *x = (Mat_Elemental*)X->data; 48565b78793SXuan Zhou 48665b78793SXuan Zhou PetscFunctionBegin; 487e8146892SSatish Balay El::Scale((PetscElemScalar)a,*x->emat); 48865b78793SXuan Zhou PetscFunctionReturn(0); 48965b78793SXuan Zhou } 49065b78793SXuan Zhou 491f82baa17SHong Zhang /* 492f82baa17SHong Zhang MatAXPY - Computes Y = a*X + Y. 493f82baa17SHong Zhang */ 494e6dea9dbSXuan Zhou static PetscErrorCode MatAXPY_Elemental(Mat Y,PetscScalar a,Mat X,MatStructure str) 495e09a3074SHong Zhang { 496e09a3074SHong Zhang Mat_Elemental *x = (Mat_Elemental*)X->data; 497e09a3074SHong Zhang Mat_Elemental *y = (Mat_Elemental*)Y->data; 498e09a3074SHong Zhang 499e09a3074SHong Zhang PetscFunctionBegin; 500e8146892SSatish Balay El::Axpy((PetscElemScalar)a,*x->emat,*y->emat); 5019566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 502e09a3074SHong Zhang PetscFunctionReturn(0); 503e09a3074SHong Zhang } 504e09a3074SHong Zhang 505d6223691SXuan Zhou static PetscErrorCode MatCopy_Elemental(Mat A,Mat B,MatStructure str) 506d6223691SXuan Zhou { 507d6223691SXuan Zhou Mat_Elemental *a=(Mat_Elemental*)A->data; 508d6223691SXuan Zhou Mat_Elemental *b=(Mat_Elemental*)B->data; 509d6223691SXuan Zhou 510d6223691SXuan Zhou PetscFunctionBegin; 511e8146892SSatish Balay El::Copy(*a->emat,*b->emat); 5129566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 513d6223691SXuan Zhou PetscFunctionReturn(0); 514d6223691SXuan Zhou } 515d6223691SXuan Zhou 516df311e6cSXuan Zhou static PetscErrorCode MatDuplicate_Elemental(Mat A,MatDuplicateOption op,Mat *B) 517df311e6cSXuan Zhou { 518df311e6cSXuan Zhou Mat Be; 519ce94432eSBarry Smith MPI_Comm comm; 520df311e6cSXuan Zhou Mat_Elemental *a=(Mat_Elemental*)A->data; 521df311e6cSXuan Zhou 522df311e6cSXuan Zhou PetscFunctionBegin; 5239566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 5249566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&Be)); 5259566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Be,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE)); 5269566063dSJacob Faibussowitsch PetscCall(MatSetType(Be,MATELEMENTAL)); 5279566063dSJacob Faibussowitsch PetscCall(MatSetUp(Be)); 528df311e6cSXuan Zhou *B = Be; 529df311e6cSXuan Zhou if (op == MAT_COPY_VALUES) { 530df311e6cSXuan Zhou Mat_Elemental *b=(Mat_Elemental*)Be->data; 531e8146892SSatish Balay El::Copy(*a->emat,*b->emat); 532df311e6cSXuan Zhou } 533df311e6cSXuan Zhou Be->assembled = PETSC_TRUE; 534df311e6cSXuan Zhou PetscFunctionReturn(0); 535df311e6cSXuan Zhou } 536df311e6cSXuan Zhou 537d6223691SXuan Zhou static PetscErrorCode MatTranspose_Elemental(Mat A,MatReuse reuse,Mat *B) 538d6223691SXuan Zhou { 539ec8cb81fSBarry Smith Mat Be = *B; 540ce94432eSBarry Smith MPI_Comm comm; 5414fe7bbcaSHong Zhang Mat_Elemental *a = (Mat_Elemental*)A->data, *b; 542d6223691SXuan Zhou 543d6223691SXuan Zhou PetscFunctionBegin; 5449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 5455cb544a0SHong Zhang /* Only out-of-place supported */ 5465f80ce2aSJacob Faibussowitsch PetscCheck(reuse != MAT_INPLACE_MATRIX,comm,PETSC_ERR_SUP,"Only out-of-place supported"); 5475262d616SXuan Zhou if (reuse == MAT_INITIAL_MATRIX) { 5489566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&Be)); 5499566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE)); 5509566063dSJacob Faibussowitsch PetscCall(MatSetType(Be,MATELEMENTAL)); 5519566063dSJacob Faibussowitsch PetscCall(MatSetUp(Be)); 5525262d616SXuan Zhou *B = Be; 5535262d616SXuan Zhou } 5544fe7bbcaSHong Zhang b = (Mat_Elemental*)Be->data; 555e8146892SSatish Balay El::Transpose(*a->emat,*b->emat); 5565262d616SXuan Zhou Be->assembled = PETSC_TRUE; 557d6223691SXuan Zhou PetscFunctionReturn(0); 558d6223691SXuan Zhou } 559d6223691SXuan Zhou 560dfcb0403SXuan Zhou static PetscErrorCode MatConjugate_Elemental(Mat A) 561dfcb0403SXuan Zhou { 562dfcb0403SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 563dfcb0403SXuan Zhou 564dfcb0403SXuan Zhou PetscFunctionBegin; 565e8146892SSatish Balay El::Conjugate(*a->emat); 566dfcb0403SXuan Zhou PetscFunctionReturn(0); 567dfcb0403SXuan Zhou } 568dfcb0403SXuan Zhou 5694a29722dSXuan Zhou static PetscErrorCode MatHermitianTranspose_Elemental(Mat A,MatReuse reuse,Mat *B) 5704a29722dSXuan Zhou { 571ec8cb81fSBarry Smith Mat Be = *B; 572ce94432eSBarry Smith MPI_Comm comm; 5734a29722dSXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data, *b; 5744a29722dSXuan Zhou 5754a29722dSXuan Zhou PetscFunctionBegin; 5769566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 5775cb544a0SHong Zhang /* Only out-of-place supported */ 5784a29722dSXuan Zhou if (reuse == MAT_INITIAL_MATRIX) { 5799566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&Be)); 5809566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE)); 5819566063dSJacob Faibussowitsch PetscCall(MatSetType(Be,MATELEMENTAL)); 5829566063dSJacob Faibussowitsch PetscCall(MatSetUp(Be)); 5834a29722dSXuan Zhou *B = Be; 5844a29722dSXuan Zhou } 5854a29722dSXuan Zhou b = (Mat_Elemental*)Be->data; 586e8146892SSatish Balay El::Adjoint(*a->emat,*b->emat); 5874a29722dSXuan Zhou Be->assembled = PETSC_TRUE; 5884a29722dSXuan Zhou PetscFunctionReturn(0); 5894a29722dSXuan Zhou } 5904a29722dSXuan Zhou 5911f881ff8SXuan Zhou static PetscErrorCode MatSolve_Elemental(Mat A,Vec B,Vec X) 5921f881ff8SXuan Zhou { 5931f881ff8SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 594df311e6cSXuan Zhou PetscElemScalar *x; 595ea394475SSatish Balay PetscInt pivoting = a->pivoting; 5961f881ff8SXuan Zhou 5971f881ff8SXuan Zhou PetscFunctionBegin; 5989566063dSJacob Faibussowitsch PetscCall(VecCopy(B,X)); 5999566063dSJacob Faibussowitsch PetscCall(VecGetArray(X,(PetscScalar **)&x)); 600ea394475SSatish Balay 601e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe; 6020c18141cSBarry Smith xe.Attach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n); 603e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::MC,El::MR> xer(xe); 604fc54b460SXuan Zhou switch (A->factortype) { 605fc54b460SXuan Zhou case MAT_FACTOR_LU: 606ea394475SSatish Balay if (pivoting == 0) { 607e8146892SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,xer); 608ea394475SSatish Balay } else if (pivoting == 1) { 609ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,xer); 610ea394475SSatish Balay } else { /* pivoting == 2 */ 611ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,xer); 6121f881ff8SXuan Zhou } 613fc54b460SXuan Zhou break; 614fc54b460SXuan Zhou case MAT_FACTOR_CHOLESKY: 615e8146892SSatish Balay El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,xer); 616fc54b460SXuan Zhou break; 617fc54b460SXuan Zhou default: 6184fe7bbcaSHong Zhang SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType"); 619fc54b460SXuan Zhou break; 6201f881ff8SXuan Zhou } 621ea394475SSatish Balay El::Copy(xer,xe); 622ea394475SSatish Balay 6239566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X,(PetscScalar **)&x)); 6241f881ff8SXuan Zhou PetscFunctionReturn(0); 6251f881ff8SXuan Zhou } 6261f881ff8SXuan Zhou 627df311e6cSXuan Zhou static PetscErrorCode MatSolveAdd_Elemental(Mat A,Vec B,Vec Y,Vec X) 628df311e6cSXuan Zhou { 629df311e6cSXuan Zhou PetscFunctionBegin; 6309566063dSJacob Faibussowitsch PetscCall(MatSolve_Elemental(A,B,X)); 6319566063dSJacob Faibussowitsch PetscCall(VecAXPY(X,1,Y)); 632df311e6cSXuan Zhou PetscFunctionReturn(0); 633df311e6cSXuan Zhou } 634df311e6cSXuan Zhou 635ae844d54SHong Zhang static PetscErrorCode MatMatSolve_Elemental(Mat A,Mat B,Mat X) 636ae844d54SHong Zhang { 6371f0e42cfSHong Zhang Mat_Elemental *a = (Mat_Elemental*)A->data; 63842ba530cSPierre Jolivet Mat_Elemental *x; 63942ba530cSPierre Jolivet Mat C; 640ea394475SSatish Balay PetscInt pivoting = a->pivoting; 64142ba530cSPierre Jolivet PetscBool flg; 64242ba530cSPierre Jolivet MatType type; 6431f0e42cfSHong Zhang 644ae844d54SHong Zhang PetscFunctionBegin; 6459566063dSJacob Faibussowitsch PetscCall(MatGetType(X,&type)); 6469566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(type,MATELEMENTAL,&flg)); 64742ba530cSPierre Jolivet if (!flg) { 6489566063dSJacob Faibussowitsch PetscCall(MatConvert(B,MATELEMENTAL,MAT_INITIAL_MATRIX,&C)); 64942ba530cSPierre Jolivet x = (Mat_Elemental*)C->data; 65042ba530cSPierre Jolivet } else { 65142ba530cSPierre Jolivet x = (Mat_Elemental*)X->data; 65242ba530cSPierre Jolivet El::Copy(*((Mat_Elemental*)B->data)->emat,*x->emat); 65342ba530cSPierre Jolivet } 654fc54b460SXuan Zhou switch (A->factortype) { 655fc54b460SXuan Zhou case MAT_FACTOR_LU: 656ea394475SSatish Balay if (pivoting == 0) { 657e8146892SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,*x->emat); 658ea394475SSatish Balay } else if (pivoting == 1) { 659ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*x->emat); 660ea394475SSatish Balay } else { 661ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,*x->emat); 662d6223691SXuan Zhou } 663fc54b460SXuan Zhou break; 664fc54b460SXuan Zhou case MAT_FACTOR_CHOLESKY: 665e8146892SSatish Balay El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,*x->emat); 666fc54b460SXuan Zhou break; 667fc54b460SXuan Zhou default: 6684fe7bbcaSHong Zhang SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType"); 669fc54b460SXuan Zhou break; 670fc54b460SXuan Zhou } 67142ba530cSPierre Jolivet if (!flg) { 6729566063dSJacob Faibussowitsch PetscCall(MatConvert(C,type,MAT_REUSE_MATRIX,&X)); 6739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 67442ba530cSPierre Jolivet } 675ae844d54SHong Zhang PetscFunctionReturn(0); 676ae844d54SHong Zhang } 677ae844d54SHong Zhang 678ae844d54SHong Zhang static PetscErrorCode MatLUFactor_Elemental(Mat A,IS row,IS col,const MatFactorInfo *info) 679ae844d54SHong Zhang { 6807c920d81SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 681ea394475SSatish Balay PetscInt pivoting = a->pivoting; 6827c920d81SXuan Zhou 683ae844d54SHong Zhang PetscFunctionBegin; 684ea394475SSatish Balay if (pivoting == 0) { 685e8146892SSatish Balay El::LU(*a->emat); 686ea394475SSatish Balay } else if (pivoting == 1) { 687ea394475SSatish Balay El::LU(*a->emat,*a->P); 688ea394475SSatish Balay } else { 689ea394475SSatish Balay El::LU(*a->emat,*a->P,*a->Q); 690d6223691SXuan Zhou } 6911293973dSHong Zhang A->factortype = MAT_FACTOR_LU; 692834d3fecSHong Zhang A->assembled = PETSC_TRUE; 693f6224b95SHong Zhang 6949566063dSJacob Faibussowitsch PetscCall(PetscFree(A->solvertype)); 6959566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype)); 696ae844d54SHong Zhang PetscFunctionReturn(0); 697ae844d54SHong Zhang } 698ae844d54SHong Zhang 699d7c3f9d8SHong Zhang static PetscErrorCode MatLUFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info) 700d7c3f9d8SHong Zhang { 701d7c3f9d8SHong Zhang PetscFunctionBegin; 7029566063dSJacob Faibussowitsch PetscCall(MatCopy(A,F,SAME_NONZERO_PATTERN)); 7039566063dSJacob Faibussowitsch PetscCall(MatLUFactor_Elemental(F,0,0,info)); 704d7c3f9d8SHong Zhang PetscFunctionReturn(0); 705d7c3f9d8SHong Zhang } 706d7c3f9d8SHong Zhang 707d7c3f9d8SHong Zhang static PetscErrorCode MatLUFactorSymbolic_Elemental(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info) 708d7c3f9d8SHong Zhang { 709d7c3f9d8SHong Zhang PetscFunctionBegin; 710d8304050SJose E. Roman /* F is created and allocated by MatGetFactor_elemental_petsc(), skip this routine. */ 711d7c3f9d8SHong Zhang PetscFunctionReturn(0); 712d7c3f9d8SHong Zhang } 713d7c3f9d8SHong Zhang 71445cf121fSXuan Zhou static PetscErrorCode MatCholeskyFactor_Elemental(Mat A,IS perm,const MatFactorInfo *info) 71545cf121fSXuan Zhou { 71645cf121fSXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 717e8146892SSatish Balay El::DistMatrix<PetscElemScalar,El::MC,El::STAR> d; 71845cf121fSXuan Zhou 71945cf121fSXuan Zhou PetscFunctionBegin; 720e8146892SSatish Balay El::Cholesky(El::UPPER,*a->emat); 721fc54b460SXuan Zhou A->factortype = MAT_FACTOR_CHOLESKY; 722834d3fecSHong Zhang A->assembled = PETSC_TRUE; 723f6224b95SHong Zhang 7249566063dSJacob Faibussowitsch PetscCall(PetscFree(A->solvertype)); 7259566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype)); 72645cf121fSXuan Zhou PetscFunctionReturn(0); 72745cf121fSXuan Zhou } 72845cf121fSXuan Zhou 72979673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info) 73079673f7bSHong Zhang { 731cb76c1d8SXuan Zhou PetscFunctionBegin; 7329566063dSJacob Faibussowitsch PetscCall(MatCopy(A,F,SAME_NONZERO_PATTERN)); 7339566063dSJacob Faibussowitsch PetscCall(MatCholeskyFactor_Elemental(F,0,info)); 734cb76c1d8SXuan Zhou PetscFunctionReturn(0); 73579673f7bSHong Zhang } 736cb76c1d8SXuan Zhou 73779673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorSymbolic_Elemental(Mat F,Mat A,IS perm,const MatFactorInfo *info) 73879673f7bSHong Zhang { 73979673f7bSHong Zhang PetscFunctionBegin; 740d8304050SJose E. Roman /* F is created and allocated by MatGetFactor_elemental_petsc(), skip this routine. */ 74179673f7bSHong Zhang PetscFunctionReturn(0); 74279673f7bSHong Zhang } 74379673f7bSHong Zhang 744ea799195SBarry Smith PetscErrorCode MatFactorGetSolverType_elemental_elemental(Mat A,MatSolverType *type) 74515767789SHong Zhang { 74615767789SHong Zhang PetscFunctionBegin; 74715767789SHong Zhang *type = MATSOLVERELEMENTAL; 74815767789SHong Zhang PetscFunctionReturn(0); 74915767789SHong Zhang } 75015767789SHong Zhang 75115767789SHong Zhang static PetscErrorCode MatGetFactor_elemental_elemental(Mat A,MatFactorType ftype,Mat *F) 7521293973dSHong Zhang { 7531293973dSHong Zhang Mat B; 7541293973dSHong Zhang 7551293973dSHong Zhang PetscFunctionBegin; 7561293973dSHong Zhang /* Create the factorization matrix */ 7579566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&B)); 7589566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE)); 7599566063dSJacob Faibussowitsch PetscCall(MatSetType(B,MATELEMENTAL)); 7609566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 7611293973dSHong Zhang B->factortype = ftype; 76266e17bc3SBarry Smith B->trivialsymbolic = PETSC_TRUE; 7639566063dSJacob Faibussowitsch PetscCall(PetscFree(B->solvertype)); 7649566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERELEMENTAL,&B->solvertype)); 76500c67f3bSHong Zhang 7669566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_elemental_elemental)); 7671293973dSHong Zhang *F = B; 7681293973dSHong Zhang PetscFunctionReturn(0); 7691293973dSHong Zhang } 7701293973dSHong Zhang 7713ca39a21SBarry Smith PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Elemental(void) 77242c9c57cSBarry Smith { 77342c9c57cSBarry Smith PetscFunctionBegin; 7749566063dSJacob Faibussowitsch PetscCall(MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL, MAT_FACTOR_LU,MatGetFactor_elemental_elemental)); 7759566063dSJacob Faibussowitsch PetscCall(MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL, MAT_FACTOR_CHOLESKY,MatGetFactor_elemental_elemental)); 77642c9c57cSBarry Smith PetscFunctionReturn(0); 77742c9c57cSBarry Smith } 77842c9c57cSBarry Smith 7791f881ff8SXuan Zhou static PetscErrorCode MatNorm_Elemental(Mat A,NormType type,PetscReal *nrm) 7801f881ff8SXuan Zhou { 7811f881ff8SXuan Zhou Mat_Elemental *a=(Mat_Elemental*)A->data; 7821f881ff8SXuan Zhou 7831f881ff8SXuan Zhou PetscFunctionBegin; 7841f881ff8SXuan Zhou switch (type) { 7851f881ff8SXuan Zhou case NORM_1: 786e8146892SSatish Balay *nrm = El::OneNorm(*a->emat); 7871f881ff8SXuan Zhou break; 7881f881ff8SXuan Zhou case NORM_FROBENIUS: 789e8146892SSatish Balay *nrm = El::FrobeniusNorm(*a->emat); 7901f881ff8SXuan Zhou break; 7911f881ff8SXuan Zhou case NORM_INFINITY: 792e8146892SSatish Balay *nrm = El::InfinityNorm(*a->emat); 7931f881ff8SXuan Zhou break; 7941f881ff8SXuan Zhou default: 795d8304050SJose E. Roman SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unsupported norm type"); 7961f881ff8SXuan Zhou } 7971f881ff8SXuan Zhou PetscFunctionReturn(0); 7981f881ff8SXuan Zhou } 7991f881ff8SXuan Zhou 8005262d616SXuan Zhou static PetscErrorCode MatZeroEntries_Elemental(Mat A) 8015262d616SXuan Zhou { 8025262d616SXuan Zhou Mat_Elemental *a=(Mat_Elemental*)A->data; 8035262d616SXuan Zhou 8045262d616SXuan Zhou PetscFunctionBegin; 805e8146892SSatish Balay El::Zero(*a->emat); 8065262d616SXuan Zhou PetscFunctionReturn(0); 8075262d616SXuan Zhou } 8085262d616SXuan Zhou 809db31f6deSJed Brown static PetscErrorCode MatGetOwnershipIS_Elemental(Mat A,IS *rows,IS *cols) 810db31f6deSJed Brown { 811db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 812db31f6deSJed Brown PetscInt i,m,shift,stride,*idx; 813db31f6deSJed Brown 814db31f6deSJed Brown PetscFunctionBegin; 815db31f6deSJed Brown if (rows) { 816db31f6deSJed Brown m = a->emat->LocalHeight(); 817db31f6deSJed Brown shift = a->emat->ColShift(); 818db31f6deSJed Brown stride = a->emat->ColStride(); 8199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&idx)); 820db31f6deSJed Brown for (i=0; i<m; i++) { 821db31f6deSJed Brown PetscInt rank,offset; 822db31f6deSJed Brown E2RO(A,0,shift+i*stride,&rank,&offset); 823db31f6deSJed Brown RO2P(A,0,rank,offset,&idx[i]); 824db31f6deSJed Brown } 8259566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,rows)); 826db31f6deSJed Brown } 827db31f6deSJed Brown if (cols) { 828db31f6deSJed Brown m = a->emat->LocalWidth(); 829db31f6deSJed Brown shift = a->emat->RowShift(); 830db31f6deSJed Brown stride = a->emat->RowStride(); 8319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m,&idx)); 832db31f6deSJed Brown for (i=0; i<m; i++) { 833db31f6deSJed Brown PetscInt rank,offset; 834db31f6deSJed Brown E2RO(A,1,shift+i*stride,&rank,&offset); 835db31f6deSJed Brown RO2P(A,1,rank,offset,&idx[i]); 836db31f6deSJed Brown } 8379566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,cols)); 838db31f6deSJed Brown } 839db31f6deSJed Brown PetscFunctionReturn(0); 840db31f6deSJed Brown } 841db31f6deSJed Brown 84219fd82e9SBarry Smith static PetscErrorCode MatConvert_Elemental_Dense(Mat A,MatType newtype,MatReuse reuse,Mat *B) 843af295397SXuan Zhou { 8442ef0cf24SXuan Zhou Mat Bmpi; 845af295397SXuan Zhou Mat_Elemental *a = (Mat_Elemental*)A->data; 846ce94432eSBarry Smith MPI_Comm comm; 847fa9e26c8SHong Zhang IS isrows,iscols; 848fa9e26c8SHong Zhang PetscInt rrank,ridx,crank,cidx,nrows,ncols,i,j,erow,ecol,elrow,elcol; 849fa9e26c8SHong Zhang const PetscInt *rows,*cols; 850df311e6cSXuan Zhou PetscElemScalar v; 851fa9e26c8SHong Zhang const El::Grid &grid = a->emat->Grid(); 852af295397SXuan Zhou 853af295397SXuan Zhou PetscFunctionBegin; 8549566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 855a000e53bSHong Zhang 856de0a22f0SHong Zhang if (reuse == MAT_REUSE_MATRIX) { 857de0a22f0SHong Zhang Bmpi = *B; 858de0a22f0SHong Zhang } else { 8599566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&Bmpi)); 8609566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Bmpi,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE)); 8619566063dSJacob Faibussowitsch PetscCall(MatSetType(Bmpi,MATDENSE)); 8629566063dSJacob Faibussowitsch PetscCall(MatSetUp(Bmpi)); 863de0a22f0SHong Zhang } 864fa9e26c8SHong Zhang 865fa9e26c8SHong Zhang /* Get local entries of A */ 8669566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipIS(A,&isrows,&iscols)); 8679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrows,&nrows)); 8689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrows,&rows)); 8699566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscols,&ncols)); 8709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscols,&cols)); 871fa9e26c8SHong Zhang 87257299f2fSHong Zhang if (a->roworiented) { 8732ef0cf24SXuan Zhou for (i=0; i<nrows; i++) { 874fa9e26c8SHong Zhang P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */ 8752ef0cf24SXuan Zhou RO2E(A,0,rrank,ridx,&erow); 876aed4548fSBarry Smith PetscCheck(rrank >= 0 && ridx >= 0 && erow >= 0,comm,PETSC_ERR_PLIB,"Incorrect row translation"); 8772ef0cf24SXuan Zhou for (j=0; j<ncols; j++) { 878fa9e26c8SHong Zhang P2RO(A,1,cols[j],&crank,&cidx); 8792ef0cf24SXuan Zhou RO2E(A,1,crank,cidx,&ecol); 880aed4548fSBarry Smith PetscCheck(crank >= 0 && cidx >= 0 && ecol >= 0,comm,PETSC_ERR_PLIB,"Incorrect col translation"); 881fa9e26c8SHong Zhang 882fa9e26c8SHong Zhang elrow = erow / grid.MCSize(); /* Elemental local row index */ 883fa9e26c8SHong Zhang elcol = ecol / grid.MRSize(); /* Elemental local column index */ 884fa9e26c8SHong Zhang v = a->emat->GetLocal(elrow,elcol); 8859566063dSJacob Faibussowitsch PetscCall(MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES)); 8862ef0cf24SXuan Zhou } 8872ef0cf24SXuan Zhou } 88857299f2fSHong Zhang } else { /* column-oriented */ 88957299f2fSHong Zhang for (j=0; j<ncols; j++) { 89057299f2fSHong Zhang P2RO(A,1,cols[j],&crank,&cidx); 89157299f2fSHong Zhang RO2E(A,1,crank,cidx,&ecol); 892aed4548fSBarry Smith PetscCheck(crank >= 0 && cidx >= 0 && ecol >= 0,comm,PETSC_ERR_PLIB,"Incorrect col translation"); 89357299f2fSHong Zhang for (i=0; i<nrows; i++) { 89457299f2fSHong Zhang P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */ 89557299f2fSHong Zhang RO2E(A,0,rrank,ridx,&erow); 896aed4548fSBarry Smith PetscCheck(rrank >= 0 && ridx >= 0 && erow >= 0,comm,PETSC_ERR_PLIB,"Incorrect row translation"); 89757299f2fSHong Zhang 89857299f2fSHong Zhang elrow = erow / grid.MCSize(); /* Elemental local row index */ 89957299f2fSHong Zhang elcol = ecol / grid.MRSize(); /* Elemental local column index */ 90057299f2fSHong Zhang v = a->emat->GetLocal(elrow,elcol); 9019566063dSJacob Faibussowitsch PetscCall(MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES)); 90257299f2fSHong Zhang } 90357299f2fSHong Zhang } 90457299f2fSHong Zhang } 9059566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Bmpi,MAT_FINAL_ASSEMBLY)); 9069566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Bmpi,MAT_FINAL_ASSEMBLY)); 907511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 9089566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&Bmpi)); 909c4ad791aSXuan Zhou } else { 910c4ad791aSXuan Zhou *B = Bmpi; 911c4ad791aSXuan Zhou } 9129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isrows)); 9139566063dSJacob Faibussowitsch PetscCall(ISDestroy(&iscols)); 914af295397SXuan Zhou PetscFunctionReturn(0); 915af295397SXuan Zhou } 916af295397SXuan Zhou 917cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat) 918af8000cdSHong Zhang { 919af8000cdSHong Zhang Mat mat_elemental; 920af8000cdSHong Zhang PetscInt M=A->rmap->N,N=A->cmap->N,row,ncols; 921af8000cdSHong Zhang const PetscInt *cols; 922af8000cdSHong Zhang const PetscScalar *vals; 923af8000cdSHong Zhang 924af8000cdSHong Zhang PetscFunctionBegin; 925bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 926bdeae278SStefano Zampini mat_elemental = *newmat; 9279566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(mat_elemental)); 928bdeae278SStefano Zampini } else { 9299566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental)); 9309566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N)); 9319566063dSJacob Faibussowitsch PetscCall(MatSetType(mat_elemental,MATELEMENTAL)); 9329566063dSJacob Faibussowitsch PetscCall(MatSetUp(mat_elemental)); 933bdeae278SStefano Zampini } 934af8000cdSHong Zhang for (row=0; row<M; row++) { 9359566063dSJacob Faibussowitsch PetscCall(MatGetRow(A,row,&ncols,&cols,&vals)); 936bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 9379566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES)); 9389566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A,row,&ncols,&cols,&vals)); 939af8000cdSHong Zhang } 9409566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY)); 9419566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY)); 942af8000cdSHong Zhang 943511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 9449566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&mat_elemental)); 945af8000cdSHong Zhang } else { 946af8000cdSHong Zhang *newmat = mat_elemental; 947af8000cdSHong Zhang } 948af8000cdSHong Zhang PetscFunctionReturn(0); 949af8000cdSHong Zhang } 950af8000cdSHong Zhang 951cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat) 9525d7652ecSHong Zhang { 9535d7652ecSHong Zhang Mat mat_elemental; 9545d7652ecSHong Zhang PetscInt row,ncols,rstart=A->rmap->rstart,rend=A->rmap->rend,j; 9555d7652ecSHong Zhang const PetscInt *cols; 9565d7652ecSHong Zhang const PetscScalar *vals; 9575d7652ecSHong Zhang 9585d7652ecSHong Zhang PetscFunctionBegin; 959bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 960bdeae278SStefano Zampini mat_elemental = *newmat; 9619566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(mat_elemental)); 962bdeae278SStefano Zampini } else { 9639566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental)); 9649566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,A->rmap->N,A->cmap->N)); 9659566063dSJacob Faibussowitsch PetscCall(MatSetType(mat_elemental,MATELEMENTAL)); 9669566063dSJacob Faibussowitsch PetscCall(MatSetUp(mat_elemental)); 967bdeae278SStefano Zampini } 9685d7652ecSHong Zhang for (row=rstart; row<rend; row++) { 9699566063dSJacob Faibussowitsch PetscCall(MatGetRow(A,row,&ncols,&cols,&vals)); 9705d7652ecSHong Zhang for (j=0; j<ncols; j++) { 971bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 9729566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental,1,&row,1,&cols[j],&vals[j],ADD_VALUES)); 9735d7652ecSHong Zhang } 9749566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A,row,&ncols,&cols,&vals)); 9755d7652ecSHong Zhang } 9769566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY)); 9779566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY)); 9785d7652ecSHong Zhang 979511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 9809566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&mat_elemental)); 9815d7652ecSHong Zhang } else { 9825d7652ecSHong Zhang *newmat = mat_elemental; 9835d7652ecSHong Zhang } 9845d7652ecSHong Zhang PetscFunctionReturn(0); 9855d7652ecSHong Zhang } 9865d7652ecSHong Zhang 987cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat) 9886214f412SHong Zhang { 9896214f412SHong Zhang Mat mat_elemental; 9906214f412SHong Zhang PetscInt M=A->rmap->N,N=A->cmap->N,row,ncols,j; 9916214f412SHong Zhang const PetscInt *cols; 9926214f412SHong Zhang const PetscScalar *vals; 9936214f412SHong Zhang 9946214f412SHong Zhang PetscFunctionBegin; 995bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 996bdeae278SStefano Zampini mat_elemental = *newmat; 9979566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(mat_elemental)); 998bdeae278SStefano Zampini } else { 9999566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental)); 10009566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N)); 10019566063dSJacob Faibussowitsch PetscCall(MatSetType(mat_elemental,MATELEMENTAL)); 10029566063dSJacob Faibussowitsch PetscCall(MatSetUp(mat_elemental)); 1003bdeae278SStefano Zampini } 10049566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(A)); 10056214f412SHong Zhang for (row=0; row<M; row++) { 10069566063dSJacob Faibussowitsch PetscCall(MatGetRow(A,row,&ncols,&cols,&vals)); 1007bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 10089566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES)); 10096214f412SHong Zhang for (j=0; j<ncols; j++) { /* lower triangular part */ 1010eb1ec7c1SStefano Zampini PetscScalar v; 10116214f412SHong Zhang if (cols[j] == row) continue; 1012*b94d7dedSBarry Smith v = A->hermitian == PETSC_BOOL3_TRUE ? PetscConj(vals[j]) : vals[j]; 10139566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental,1,&cols[j],1,&row,&v,ADD_VALUES)); 10146214f412SHong Zhang } 10159566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A,row,&ncols,&cols,&vals)); 10166214f412SHong Zhang } 10179566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(A)); 10189566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY)); 10199566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY)); 10206214f412SHong Zhang 1021511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 10229566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&mat_elemental)); 10236214f412SHong Zhang } else { 10246214f412SHong Zhang *newmat = mat_elemental; 10256214f412SHong Zhang } 10266214f412SHong Zhang PetscFunctionReturn(0); 10276214f412SHong Zhang } 10286214f412SHong Zhang 1029cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat) 10306214f412SHong Zhang { 10316214f412SHong Zhang Mat mat_elemental; 10326214f412SHong Zhang PetscInt M=A->rmap->N,N=A->cmap->N,row,ncols,j,rstart=A->rmap->rstart,rend=A->rmap->rend; 10336214f412SHong Zhang const PetscInt *cols; 10346214f412SHong Zhang const PetscScalar *vals; 10356214f412SHong Zhang 10366214f412SHong Zhang PetscFunctionBegin; 1037bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 1038bdeae278SStefano Zampini mat_elemental = *newmat; 10399566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(mat_elemental)); 1040bdeae278SStefano Zampini } else { 10419566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental)); 10429566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N)); 10439566063dSJacob Faibussowitsch PetscCall(MatSetType(mat_elemental,MATELEMENTAL)); 10449566063dSJacob Faibussowitsch PetscCall(MatSetUp(mat_elemental)); 1045bdeae278SStefano Zampini } 10469566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(A)); 10476214f412SHong Zhang for (row=rstart; row<rend; row++) { 10489566063dSJacob Faibussowitsch PetscCall(MatGetRow(A,row,&ncols,&cols,&vals)); 1049bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 10509566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES)); 10516214f412SHong Zhang for (j=0; j<ncols; j++) { /* lower triangular part */ 1052eb1ec7c1SStefano Zampini PetscScalar v; 10536214f412SHong Zhang if (cols[j] == row) continue; 1054*b94d7dedSBarry Smith v = A->hermitian == PETSC_BOOL3_TRUE ? PetscConj(vals[j]) : vals[j]; 10559566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental,1,&cols[j],1,&row,&v,ADD_VALUES)); 10566214f412SHong Zhang } 10579566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A,row,&ncols,&cols,&vals)); 10586214f412SHong Zhang } 10599566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(A)); 10609566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY)); 10619566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY)); 10626214f412SHong Zhang 1063511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 10649566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A,&mat_elemental)); 10656214f412SHong Zhang } else { 10666214f412SHong Zhang *newmat = mat_elemental; 10676214f412SHong Zhang } 10686214f412SHong Zhang PetscFunctionReturn(0); 10696214f412SHong Zhang } 10706214f412SHong Zhang 1071db31f6deSJed Brown static PetscErrorCode MatDestroy_Elemental(Mat A) 1072db31f6deSJed Brown { 1073db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 10745e9f5b67SHong Zhang Mat_Elemental_Grid *commgrid; 10755e9f5b67SHong Zhang PetscBool flg; 10765e9f5b67SHong Zhang MPI_Comm icomm; 1077db31f6deSJed Brown 1078db31f6deSJed Brown PetscFunctionBegin; 1079db31f6deSJed Brown delete a->emat; 1080ea394475SSatish Balay delete a->P; 1081ea394475SSatish Balay delete a->Q; 10825e9f5b67SHong Zhang 1083e8146892SSatish Balay El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A)); 10849566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(cxxcomm.comm,&icomm,NULL)); 10859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg)); 10865e9f5b67SHong Zhang if (--commgrid->grid_refct == 0) { 10875e9f5b67SHong Zhang delete commgrid->grid; 10889566063dSJacob Faibussowitsch PetscCall(PetscFree(commgrid)); 10899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Elemental_keyval)); 10905e9f5b67SHong Zhang } 10919566063dSJacob Faibussowitsch PetscCall(PetscCommDestroy(&icomm)); 10929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",NULL)); 10939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverType_C",NULL)); 10949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_elemental_mpidense_C",NULL)); 10959566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 1096db31f6deSJed Brown PetscFunctionReturn(0); 1097db31f6deSJed Brown } 1098db31f6deSJed Brown 1099db31f6deSJed Brown PetscErrorCode MatSetUp_Elemental(Mat A) 1100db31f6deSJed Brown { 1101db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental*)A->data; 1102f19600a0SHong Zhang MPI_Comm comm; 1103db31f6deSJed Brown PetscMPIInt rsize,csize; 1104f19600a0SHong Zhang PetscInt n; 1105db31f6deSJed Brown 1106db31f6deSJed Brown PetscFunctionBegin; 11079566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 11089566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 1109db31f6deSJed Brown 1110d8304050SJose E. Roman /* Check if local row and column sizes are equally distributed. 1111f19600a0SHong Zhang Jed: Elemental uses "element" cyclic ordering so the sizes need to match that 1112f19600a0SHong Zhang exactly. The strategy in MatElemental is for PETSc to implicitly permute to block ordering (like would be returned by 1113d8304050SJose E. Roman PetscSplitOwnership(comm,&n,&N), at which point Elemental matrices can act on PETSc vectors without redistributing the vectors. */ 11149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A,&comm)); 1115f19600a0SHong Zhang n = PETSC_DECIDE; 11169566063dSJacob Faibussowitsch PetscCall(PetscSplitOwnership(comm,&n,&A->rmap->N)); 11175f80ce2aSJacob Faibussowitsch PetscCheck(n == A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local row size %" PetscInt_FMT " of ELEMENTAL matrix must be equally distributed",A->rmap->n); 1118f19600a0SHong Zhang 1119f19600a0SHong Zhang n = PETSC_DECIDE; 11209566063dSJacob Faibussowitsch PetscCall(PetscSplitOwnership(comm,&n,&A->cmap->N)); 11215f80ce2aSJacob Faibussowitsch PetscCheck(n == A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local column size %" PetscInt_FMT " of ELEMENTAL matrix must be equally distributed",A->cmap->n); 1122f19600a0SHong Zhang 11232f613bf5SBarry Smith a->emat->Resize(A->rmap->N,A->cmap->N); 1124e8146892SSatish Balay El::Zero(*a->emat); 1125db31f6deSJed Brown 11269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(A->rmap->comm,&rsize)); 11279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(A->cmap->comm,&csize)); 11285f80ce2aSJacob Faibussowitsch PetscCheck(csize == rsize,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Cannot use row and column communicators of different sizes"); 1129db31f6deSJed Brown a->commsize = rsize; 1130db31f6deSJed Brown a->mr[0] = A->rmap->N % rsize; if (!a->mr[0]) a->mr[0] = rsize; 1131db31f6deSJed Brown a->mr[1] = A->cmap->N % csize; if (!a->mr[1]) a->mr[1] = csize; 1132db31f6deSJed Brown a->m[0] = A->rmap->N / rsize + (a->mr[0] != rsize); 1133db31f6deSJed Brown a->m[1] = A->cmap->N / csize + (a->mr[1] != csize); 1134db31f6deSJed Brown PetscFunctionReturn(0); 1135db31f6deSJed Brown } 1136db31f6deSJed Brown 1137aae2c449SHong Zhang PetscErrorCode MatAssemblyBegin_Elemental(Mat A, MatAssemblyType type) 1138aae2c449SHong Zhang { 1139aae2c449SHong Zhang Mat_Elemental *a = (Mat_Elemental*)A->data; 1140aae2c449SHong Zhang 1141aae2c449SHong Zhang PetscFunctionBegin; 1142fbbcb730SJack Poulson /* printf("Calling ProcessQueues\n"); */ 1143fbbcb730SJack Poulson a->emat->ProcessQueues(); 1144fbbcb730SJack Poulson /* printf("Finished ProcessQueues\n"); */ 1145aae2c449SHong Zhang PetscFunctionReturn(0); 1146aae2c449SHong Zhang } 1147aae2c449SHong Zhang 1148aae2c449SHong Zhang PetscErrorCode MatAssemblyEnd_Elemental(Mat A, MatAssemblyType type) 1149aae2c449SHong Zhang { 1150aae2c449SHong Zhang PetscFunctionBegin; 1151aae2c449SHong Zhang /* Currently does nothing */ 1152aae2c449SHong Zhang PetscFunctionReturn(0); 1153aae2c449SHong Zhang } 1154aae2c449SHong Zhang 11557b30e0f1SHong Zhang PetscErrorCode MatLoad_Elemental(Mat newMat, PetscViewer viewer) 11567b30e0f1SHong Zhang { 11577b30e0f1SHong Zhang Mat Adense,Ae; 11587b30e0f1SHong Zhang MPI_Comm comm; 11597b30e0f1SHong Zhang 11607b30e0f1SHong Zhang PetscFunctionBegin; 11619566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)newMat,&comm)); 11629566063dSJacob Faibussowitsch PetscCall(MatCreate(comm,&Adense)); 11639566063dSJacob Faibussowitsch PetscCall(MatSetType(Adense,MATDENSE)); 11649566063dSJacob Faibussowitsch PetscCall(MatLoad(Adense,viewer)); 11659566063dSJacob Faibussowitsch PetscCall(MatConvert(Adense, MATELEMENTAL, MAT_INITIAL_MATRIX,&Ae)); 11669566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Adense)); 11679566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(newMat,&Ae)); 11687b30e0f1SHong Zhang PetscFunctionReturn(0); 11697b30e0f1SHong Zhang } 11707b30e0f1SHong Zhang 117140d92e34SHong Zhang /* -------------------------------------------------------------------*/ 117240d92e34SHong Zhang static struct _MatOps MatOps_Values = { 117340d92e34SHong Zhang MatSetValues_Elemental, 117440d92e34SHong Zhang 0, 117540d92e34SHong Zhang 0, 117640d92e34SHong Zhang MatMult_Elemental, 117740d92e34SHong Zhang /* 4*/ MatMultAdd_Elemental, 11789426833fSXuan Zhou MatMultTranspose_Elemental, 1179e883f9d5SXuan Zhou MatMultTransposeAdd_Elemental, 118040d92e34SHong Zhang MatSolve_Elemental, 1181df311e6cSXuan Zhou MatSolveAdd_Elemental, 11822ef15aa2SHong Zhang 0, 11832ef15aa2SHong Zhang /*10*/ 0, 118440d92e34SHong Zhang MatLUFactor_Elemental, 118540d92e34SHong Zhang MatCholeskyFactor_Elemental, 118640d92e34SHong Zhang 0, 118740d92e34SHong Zhang MatTranspose_Elemental, 118840d92e34SHong Zhang /*15*/ MatGetInfo_Elemental, 118940d92e34SHong Zhang 0, 119061119200SXuan Zhou MatGetDiagonal_Elemental, 1191ade3cc5eSXuan Zhou MatDiagonalScale_Elemental, 119240d92e34SHong Zhang MatNorm_Elemental, 119340d92e34SHong Zhang /*20*/ MatAssemblyBegin_Elemental, 119440d92e34SHong Zhang MatAssemblyEnd_Elemental, 119532d7a744SHong Zhang MatSetOption_Elemental, 119640d92e34SHong Zhang MatZeroEntries_Elemental, 119740d92e34SHong Zhang /*24*/ 0, 119840d92e34SHong Zhang MatLUFactorSymbolic_Elemental, 119940d92e34SHong Zhang MatLUFactorNumeric_Elemental, 120040d92e34SHong Zhang MatCholeskyFactorSymbolic_Elemental, 120140d92e34SHong Zhang MatCholeskyFactorNumeric_Elemental, 120240d92e34SHong Zhang /*29*/ MatSetUp_Elemental, 120340d92e34SHong Zhang 0, 120440d92e34SHong Zhang 0, 120540d92e34SHong Zhang 0, 120640d92e34SHong Zhang 0, 1207df311e6cSXuan Zhou /*34*/ MatDuplicate_Elemental, 120840d92e34SHong Zhang 0, 120940d92e34SHong Zhang 0, 121040d92e34SHong Zhang 0, 121140d92e34SHong Zhang 0, 121240d92e34SHong Zhang /*39*/ MatAXPY_Elemental, 121340d92e34SHong Zhang 0, 121440d92e34SHong Zhang 0, 121540d92e34SHong Zhang 0, 121640d92e34SHong Zhang MatCopy_Elemental, 121740d92e34SHong Zhang /*44*/ 0, 121840d92e34SHong Zhang MatScale_Elemental, 12197d68702bSBarry Smith MatShift_Basic, 122040d92e34SHong Zhang 0, 122140d92e34SHong Zhang 0, 122240d92e34SHong Zhang /*49*/ 0, 122340d92e34SHong Zhang 0, 122440d92e34SHong Zhang 0, 122540d92e34SHong Zhang 0, 122640d92e34SHong Zhang 0, 122740d92e34SHong Zhang /*54*/ 0, 122840d92e34SHong Zhang 0, 122940d92e34SHong Zhang 0, 123040d92e34SHong Zhang 0, 123140d92e34SHong Zhang 0, 123240d92e34SHong Zhang /*59*/ 0, 123340d92e34SHong Zhang MatDestroy_Elemental, 123440d92e34SHong Zhang MatView_Elemental, 123540d92e34SHong Zhang 0, 123640d92e34SHong Zhang 0, 123740d92e34SHong Zhang /*64*/ 0, 123840d92e34SHong Zhang 0, 123940d92e34SHong Zhang 0, 124040d92e34SHong Zhang 0, 124140d92e34SHong Zhang 0, 124240d92e34SHong Zhang /*69*/ 0, 124340d92e34SHong Zhang 0, 12442ef0cf24SXuan Zhou MatConvert_Elemental_Dense, 124540d92e34SHong Zhang 0, 124640d92e34SHong Zhang 0, 124740d92e34SHong Zhang /*74*/ 0, 124840d92e34SHong Zhang 0, 124940d92e34SHong Zhang 0, 125040d92e34SHong Zhang 0, 125140d92e34SHong Zhang 0, 125240d92e34SHong Zhang /*79*/ 0, 125340d92e34SHong Zhang 0, 125440d92e34SHong Zhang 0, 125540d92e34SHong Zhang 0, 12567b30e0f1SHong Zhang MatLoad_Elemental, 125740d92e34SHong Zhang /*84*/ 0, 125840d92e34SHong Zhang 0, 125940d92e34SHong Zhang 0, 126040d92e34SHong Zhang 0, 126140d92e34SHong Zhang 0, 12624222ddf1SHong Zhang /*89*/ 0, 12634222ddf1SHong Zhang 0, 126440d92e34SHong Zhang MatMatMultNumeric_Elemental, 126540d92e34SHong Zhang 0, 126640d92e34SHong Zhang 0, 126740d92e34SHong Zhang /*94*/ 0, 12684222ddf1SHong Zhang 0, 12694222ddf1SHong Zhang 0, 1270df311e6cSXuan Zhou MatMatTransposeMultNumeric_Elemental, 127140d92e34SHong Zhang 0, 12724222ddf1SHong Zhang /*99*/ MatProductSetFromOptions_Elemental, 127340d92e34SHong Zhang 0, 127440d92e34SHong Zhang 0, 1275dfcb0403SXuan Zhou MatConjugate_Elemental, 127640d92e34SHong Zhang 0, 127740d92e34SHong Zhang /*104*/0, 127840d92e34SHong Zhang 0, 127940d92e34SHong Zhang 0, 128040d92e34SHong Zhang 0, 128140d92e34SHong Zhang 0, 128240d92e34SHong Zhang /*109*/MatMatSolve_Elemental, 128340d92e34SHong Zhang 0, 128440d92e34SHong Zhang 0, 128540d92e34SHong Zhang 0, 128634fa46e1SFrancesco Ballarin MatMissingDiagonal_Elemental, 128740d92e34SHong Zhang /*114*/0, 128840d92e34SHong Zhang 0, 128940d92e34SHong Zhang 0, 129040d92e34SHong Zhang 0, 129140d92e34SHong Zhang 0, 129240d92e34SHong Zhang /*119*/0, 12934a29722dSXuan Zhou MatHermitianTranspose_Elemental, 129440d92e34SHong Zhang 0, 129540d92e34SHong Zhang 0, 129640d92e34SHong Zhang 0, 129740d92e34SHong Zhang /*124*/0, 129840d92e34SHong Zhang 0, 129940d92e34SHong Zhang 0, 130040d92e34SHong Zhang 0, 130140d92e34SHong Zhang 0, 130240d92e34SHong Zhang /*129*/0, 130340d92e34SHong Zhang 0, 130440d92e34SHong Zhang 0, 130540d92e34SHong Zhang 0, 130640d92e34SHong Zhang 0, 130740d92e34SHong Zhang /*134*/0, 130840d92e34SHong Zhang 0, 130940d92e34SHong Zhang 0, 131040d92e34SHong Zhang 0, 13114222ddf1SHong Zhang 0, 13124222ddf1SHong Zhang 0, 13134222ddf1SHong Zhang /*140*/0, 13144222ddf1SHong Zhang 0, 13154222ddf1SHong Zhang 0, 13164222ddf1SHong Zhang 0, 13174222ddf1SHong Zhang 0, 13184222ddf1SHong Zhang /*145*/0, 13194222ddf1SHong Zhang 0, 132099a7f59eSMark Adams 0, 132199a7f59eSMark Adams 0, 132240d92e34SHong Zhang 0 132340d92e34SHong Zhang }; 132440d92e34SHong Zhang 1325ed36708cSHong Zhang /*MC 1326ed36708cSHong Zhang MATELEMENTAL = "elemental" - A matrix type for dense matrices using the Elemental package 1327ed36708cSHong Zhang 1328c2b89b5dSBarry Smith Use ./configure --download-elemental to install PETSc to use Elemental 1329c2b89b5dSBarry Smith 133089bba20eSBarry Smith Option Database Keys: 1331c2b89b5dSBarry Smith 1332ed36708cSHong Zhang Options Database Keys: 13335cc86fc1SJed Brown + -mat_type elemental - sets the matrix type to "elemental" during a call to MatSetFromOptions() 133489bba20eSBarry Smith . -pc_factor_mat_solver_type elemental - to use this direct solver with the option -pc_type lu 13355cc86fc1SJed Brown - -mat_elemental_grid_height - sets Grid Height for 2D cyclic ordering of internal matrix 1336ed36708cSHong Zhang 1337ed36708cSHong Zhang Level: beginner 1338ed36708cSHong Zhang 133989bba20eSBarry Smith Note: 134089bba20eSBarry Smith Note unlike most matrix formats, this format does not store all the matrix entries for a contiguous 134189bba20eSBarry Smith range of rows on an MPI rank. Use `MatGetOwnershipIS()` to determine what values are stored on 134289bba20eSBarry Smith the given rank. 134389bba20eSBarry Smith 134489bba20eSBarry Smith .seealso: `MATDENSE`, `MATSCALAPACK`, `MatGetOwnershipIS()` 1345ed36708cSHong Zhang M*/ 13464a29722dSXuan Zhou 13478cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Elemental(Mat A) 1348db31f6deSJed Brown { 1349db31f6deSJed Brown Mat_Elemental *a; 13505682a260SJack Poulson PetscBool flg,flg1; 13515e9f5b67SHong Zhang Mat_Elemental_Grid *commgrid; 13525e9f5b67SHong Zhang MPI_Comm icomm; 13535682a260SJack Poulson PetscInt optv1; 1354db31f6deSJed Brown 1355db31f6deSJed Brown PetscFunctionBegin; 13569566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps))); 135740d92e34SHong Zhang A->insertmode = NOT_SET_VALUES; 1358db31f6deSJed Brown 13599566063dSJacob Faibussowitsch PetscCall(PetscNewLog(A,&a)); 1360db31f6deSJed Brown A->data = (void*)a; 1361db31f6deSJed Brown 1362db31f6deSJed Brown /* Set up the elemental matrix */ 1363e8146892SSatish Balay El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A)); 13645e9f5b67SHong Zhang 13655e9f5b67SHong Zhang /* Grid needs to be shared between multiple Mats on the same communicator, implement by attribute caching on the MPI_Comm */ 13665e9f5b67SHong Zhang if (Petsc_Elemental_keyval == MPI_KEYVAL_INVALID) { 13679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Elemental_keyval,(void*)0)); 13689566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(ElementalCitation,&ElementalCite)); 13695e9f5b67SHong Zhang } 13709566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(cxxcomm.comm,&icomm,NULL)); 13719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg)); 13725e9f5b67SHong Zhang if (!flg) { 13739566063dSJacob Faibussowitsch PetscCall(PetscNewLog(A,&commgrid)); 13745cb544a0SHong Zhang 1375d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"Elemental Options","Mat"); 1376e8146892SSatish Balay /* displayed default grid sizes (CommSize,1) are set by us arbitrarily until El::Grid() is called */ 13779566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-mat_elemental_grid_height","Grid Height","None",El::mpi::Size(cxxcomm),&optv1,&flg1)); 13785682a260SJack Poulson if (flg1) { 1379aed4548fSBarry Smith PetscCheck((El::mpi::Size(cxxcomm) % optv1) == 0,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Grid Height %" PetscInt_FMT " must evenly divide CommSize %" PetscInt_FMT,optv1,(PetscInt)El::mpi::Size(cxxcomm)); 1380e8146892SSatish Balay commgrid->grid = new El::Grid(cxxcomm,optv1); /* use user-provided grid height */ 13812ef0cf24SXuan Zhou } else { 1382e8146892SSatish Balay commgrid->grid = new El::Grid(cxxcomm); /* use Elemental default grid sizes */ 1383da0640a4SHong Zhang /* printf("new commgrid->grid = %p\n",commgrid->grid); -- memory leak revealed by valgrind? */ 1384ed667823SXuan Zhou } 13855e9f5b67SHong Zhang commgrid->grid_refct = 1; 13869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_set_attr(icomm,Petsc_Elemental_keyval,(void*)commgrid)); 1387ea394475SSatish Balay 1388ea394475SSatish Balay a->pivoting = 1; 13899566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-mat_elemental_pivoting","Pivoting","None",a->pivoting,&a->pivoting,NULL)); 1390ea394475SSatish Balay 1391d0609cedSBarry Smith PetscOptionsEnd(); 13925e9f5b67SHong Zhang } else { 13935e9f5b67SHong Zhang commgrid->grid_refct++; 13945e9f5b67SHong Zhang } 13959566063dSJacob Faibussowitsch PetscCall(PetscCommDestroy(&icomm)); 13965e9f5b67SHong Zhang a->grid = commgrid->grid; 1397e8146892SSatish Balay a->emat = new El::DistMatrix<PetscElemScalar>(*a->grid); 139832d7a744SHong Zhang a->roworiented = PETSC_TRUE; 1399db31f6deSJed Brown 14009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",MatGetOwnershipIS_Elemental)); 14019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_elemental_mpidense_C",MatProductSetFromOptions_Elemental_MPIDense)); 14029566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A,MATELEMENTAL)); 1403db31f6deSJed Brown PetscFunctionReturn(0); 1404db31f6deSJed Brown } 1405