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 19*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_Elemental(Mat A, PetscViewer viewer) 20*d71ae5a4SJacob Faibussowitsch { 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 60*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_Elemental(Mat A, MatInfoType flag, MatInfo *info) 61*d71ae5a4SJacob Faibussowitsch { 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; 854dfa11a4SJacob Faibussowitsch info->memory = 0; /* REVIEW ME */ 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 92*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetOption_Elemental(Mat A, MatOption op, PetscBool flg) 93*d71ae5a4SJacob Faibussowitsch { 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: 103*d71ae5a4SJacob Faibussowitsch case MAT_HERMITIAN: 104*d71ae5a4SJacob Faibussowitsch break; 105*d71ae5a4SJacob Faibussowitsch case MAT_ROW_ORIENTED: 106*d71ae5a4SJacob Faibussowitsch a->roworiented = flg; 107*d71ae5a4SJacob Faibussowitsch break; 108*d71ae5a4SJacob Faibussowitsch default: 109*d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %s", MatOptions[op]); 11032d7a744SHong Zhang } 11132d7a744SHong Zhang PetscFunctionReturn(0); 11232d7a744SHong Zhang } 11332d7a744SHong Zhang 114*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_Elemental(Mat A, PetscInt nr, const PetscInt *rows, PetscInt nc, const PetscInt *cols, const PetscScalar *vals, InsertMode imode) 115*d71ae5a4SJacob Faibussowitsch { 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) { 142*d71ae5a4SJacob Faibussowitsch case INSERT_VALUES: 143*d71ae5a4SJacob Faibussowitsch a->emat->Set(erow, ecol, (PetscElemScalar)vals[i * nc + j]); 144*d71ae5a4SJacob Faibussowitsch break; 145*d71ae5a4SJacob Faibussowitsch case ADD_VALUES: 146*d71ae5a4SJacob Faibussowitsch a->emat->Update(erow, ecol, (PetscElemScalar)vals[i * nc + j]); 147*d71ae5a4SJacob Faibussowitsch break; 148*d71ae5a4SJacob Faibussowitsch default: 149*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for InsertMode %d", (int)imode); 150db31f6deSJed Brown } 151db31f6deSJed Brown } 152db31f6deSJed Brown } 153fbbcb730SJack Poulson 154fbbcb730SJack Poulson /* printf("numQueues=%d\n",numQueues); */ 155fbbcb730SJack Poulson a->emat->Reserve(numQueues); 156fbbcb730SJack Poulson for (i = 0; i < nr; i++) { 157fbbcb730SJack Poulson if (rows[i] < 0) continue; 158fbbcb730SJack Poulson P2RO(A, 0, rows[i], &rrank, &ridx); 159fbbcb730SJack Poulson RO2E(A, 0, rrank, ridx, &erow); 160fbbcb730SJack Poulson for (j = 0; j < nc; j++) { 161fbbcb730SJack Poulson if (cols[j] < 0) continue; 162fbbcb730SJack Poulson P2RO(A, 1, cols[j], &crank, &cidx); 163fbbcb730SJack Poulson RO2E(A, 1, crank, cidx, &ecol); 164fbbcb730SJack Poulson if (!a->emat->IsLocal(erow, ecol)) { /*off-proc entry*/ 165fbbcb730SJack Poulson /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */ 166fbbcb730SJack Poulson a->emat->QueueUpdate(erow, ecol, vals[i * nc + j]); 167fbbcb730SJack Poulson } 168fbbcb730SJack Poulson } 169fbbcb730SJack Poulson } 17032d7a744SHong Zhang } else { /* columnoriented */ 17132d7a744SHong Zhang for (j = 0; j < nc; j++) { 17232d7a744SHong Zhang if (cols[j] < 0) continue; 17332d7a744SHong Zhang P2RO(A, 1, cols[j], &crank, &cidx); 17432d7a744SHong Zhang RO2E(A, 1, crank, cidx, &ecol); 175aed4548fSBarry Smith PetscCheck(crank >= 0 && cidx >= 0 && ecol >= 0, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Incorrect col translation"); 17632d7a744SHong Zhang for (i = 0; i < nr; i++) { 17732d7a744SHong Zhang if (rows[i] < 0) continue; 17832d7a744SHong Zhang P2RO(A, 0, rows[i], &rrank, &ridx); 17932d7a744SHong Zhang RO2E(A, 0, rrank, ridx, &erow); 180aed4548fSBarry Smith PetscCheck(rrank >= 0 && ridx >= 0 && erow >= 0, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Incorrect row translation"); 18132d7a744SHong Zhang if (!a->emat->IsLocal(erow, ecol)) { /* off-proc entry */ 18232d7a744SHong Zhang /* printf("Will later remotely update (%d,%d)\n",erow,ecol); */ 18308401ef6SPierre Jolivet PetscCheck(imode == ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only ADD_VALUES to off-processor entry is supported"); 18432d7a744SHong Zhang ++numQueues; 18532d7a744SHong Zhang continue; 18632d7a744SHong Zhang } 18732d7a744SHong Zhang /* printf("Locally updating (%d,%d)\n",erow,ecol); */ 18832d7a744SHong Zhang switch (imode) { 189*d71ae5a4SJacob Faibussowitsch case INSERT_VALUES: 190*d71ae5a4SJacob Faibussowitsch a->emat->Set(erow, ecol, (PetscElemScalar)vals[i + j * nr]); 191*d71ae5a4SJacob Faibussowitsch break; 192*d71ae5a4SJacob Faibussowitsch case ADD_VALUES: 193*d71ae5a4SJacob Faibussowitsch a->emat->Update(erow, ecol, (PetscElemScalar)vals[i + j * nr]); 194*d71ae5a4SJacob Faibussowitsch break; 195*d71ae5a4SJacob Faibussowitsch default: 196*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for InsertMode %d", (int)imode); 19732d7a744SHong Zhang } 19832d7a744SHong Zhang } 19932d7a744SHong Zhang } 20032d7a744SHong Zhang 20132d7a744SHong Zhang /* printf("numQueues=%d\n",numQueues); */ 20232d7a744SHong Zhang a->emat->Reserve(numQueues); 20332d7a744SHong Zhang for (j = 0; j < nc; j++) { 20432d7a744SHong Zhang if (cols[j] < 0) continue; 20532d7a744SHong Zhang P2RO(A, 1, cols[j], &crank, &cidx); 20632d7a744SHong Zhang RO2E(A, 1, crank, cidx, &ecol); 20732d7a744SHong Zhang 20832d7a744SHong Zhang for (i = 0; i < nr; i++) { 20932d7a744SHong Zhang if (rows[i] < 0) continue; 21032d7a744SHong Zhang P2RO(A, 0, rows[i], &rrank, &ridx); 21132d7a744SHong Zhang RO2E(A, 0, rrank, ridx, &erow); 21232d7a744SHong Zhang if (!a->emat->IsLocal(erow, ecol)) { /*off-proc entry*/ 21332d7a744SHong Zhang /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */ 21432d7a744SHong Zhang a->emat->QueueUpdate(erow, ecol, vals[i + j * nr]); 21532d7a744SHong Zhang } 21632d7a744SHong Zhang } 21732d7a744SHong Zhang } 21832d7a744SHong Zhang } 219db31f6deSJed Brown PetscFunctionReturn(0); 220db31f6deSJed Brown } 221db31f6deSJed Brown 222*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_Elemental(Mat A, Vec X, Vec Y) 223*d71ae5a4SJacob Faibussowitsch { 224db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental *)A->data; 225e6dea9dbSXuan Zhou const PetscElemScalar *x; 226e6dea9dbSXuan Zhou PetscElemScalar *y; 227df311e6cSXuan Zhou PetscElemScalar one = 1, zero = 0; 228db31f6deSJed Brown 229db31f6deSJed Brown PetscFunctionBegin; 2309566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X, (const PetscScalar **)&x)); 2319566063dSJacob Faibussowitsch PetscCall(VecGetArray(Y, (PetscScalar **)&y)); 232db31f6deSJed Brown { /* Scoping so that constructor is called before pointer is returned */ 233e8146892SSatish Balay El::DistMatrix<PetscElemScalar, El::VC, El::STAR> xe, ye; 2340c18141cSBarry Smith xe.LockedAttach(A->cmap->N, 1, *a->grid, 0, 0, x, A->cmap->n); 2350c18141cSBarry Smith ye.Attach(A->rmap->N, 1, *a->grid, 0, 0, y, A->rmap->n); 236e8146892SSatish Balay El::Gemv(El::NORMAL, one, *a->emat, xe, zero, ye); 237db31f6deSJed Brown } 2389566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X, (const PetscScalar **)&x)); 2399566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(Y, (PetscScalar **)&y)); 240db31f6deSJed Brown PetscFunctionReturn(0); 241db31f6deSJed Brown } 242db31f6deSJed Brown 243*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_Elemental(Mat A, Vec X, Vec Y) 244*d71ae5a4SJacob Faibussowitsch { 2459426833fSXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 246df311e6cSXuan Zhou const PetscElemScalar *x; 247df311e6cSXuan Zhou PetscElemScalar *y; 248e6dea9dbSXuan Zhou PetscElemScalar one = 1, zero = 0; 2499426833fSXuan Zhou 2509426833fSXuan Zhou PetscFunctionBegin; 2519566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X, (const PetscScalar **)&x)); 2529566063dSJacob Faibussowitsch PetscCall(VecGetArray(Y, (PetscScalar **)&y)); 2539426833fSXuan Zhou { /* Scoping so that constructor is called before pointer is returned */ 254e8146892SSatish Balay El::DistMatrix<PetscElemScalar, El::VC, El::STAR> xe, ye; 2550c18141cSBarry Smith xe.LockedAttach(A->rmap->N, 1, *a->grid, 0, 0, x, A->rmap->n); 2560c18141cSBarry Smith ye.Attach(A->cmap->N, 1, *a->grid, 0, 0, y, A->cmap->n); 257e8146892SSatish Balay El::Gemv(El::TRANSPOSE, one, *a->emat, xe, zero, ye); 2589426833fSXuan Zhou } 2599566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X, (const PetscScalar **)&x)); 2609566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(Y, (PetscScalar **)&y)); 2619426833fSXuan Zhou PetscFunctionReturn(0); 2629426833fSXuan Zhou } 2639426833fSXuan Zhou 264*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_Elemental(Mat A, Vec X, Vec Y, Vec Z) 265*d71ae5a4SJacob Faibussowitsch { 266db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental *)A->data; 267df311e6cSXuan Zhou const PetscElemScalar *x; 268df311e6cSXuan Zhou PetscElemScalar *z; 269e6dea9dbSXuan Zhou PetscElemScalar one = 1; 270db31f6deSJed Brown 271db31f6deSJed Brown PetscFunctionBegin; 2729566063dSJacob Faibussowitsch if (Y != Z) PetscCall(VecCopy(Y, Z)); 2739566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X, (const PetscScalar **)&x)); 2749566063dSJacob Faibussowitsch PetscCall(VecGetArray(Z, (PetscScalar **)&z)); 275db31f6deSJed Brown { /* Scoping so that constructor is called before pointer is returned */ 276e8146892SSatish Balay El::DistMatrix<PetscElemScalar, El::VC, El::STAR> xe, ze; 2770c18141cSBarry Smith xe.LockedAttach(A->cmap->N, 1, *a->grid, 0, 0, x, A->cmap->n); 2780c18141cSBarry Smith ze.Attach(A->rmap->N, 1, *a->grid, 0, 0, z, A->rmap->n); 279e8146892SSatish Balay El::Gemv(El::NORMAL, one, *a->emat, xe, one, ze); 280db31f6deSJed Brown } 2819566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X, (const PetscScalar **)&x)); 2829566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(Z, (PetscScalar **)&z)); 283db31f6deSJed Brown PetscFunctionReturn(0); 284db31f6deSJed Brown } 285db31f6deSJed Brown 286*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_Elemental(Mat A, Vec X, Vec Y, Vec Z) 287*d71ae5a4SJacob Faibussowitsch { 288e883f9d5SXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 289df311e6cSXuan Zhou const PetscElemScalar *x; 290df311e6cSXuan Zhou PetscElemScalar *z; 291e6dea9dbSXuan Zhou PetscElemScalar one = 1; 292e883f9d5SXuan Zhou 293e883f9d5SXuan Zhou PetscFunctionBegin; 2949566063dSJacob Faibussowitsch if (Y != Z) PetscCall(VecCopy(Y, Z)); 2959566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X, (const PetscScalar **)&x)); 2969566063dSJacob Faibussowitsch PetscCall(VecGetArray(Z, (PetscScalar **)&z)); 297e883f9d5SXuan Zhou { /* Scoping so that constructor is called before pointer is returned */ 298e8146892SSatish Balay El::DistMatrix<PetscElemScalar, El::VC, El::STAR> xe, ze; 2990c18141cSBarry Smith xe.LockedAttach(A->rmap->N, 1, *a->grid, 0, 0, x, A->rmap->n); 3000c18141cSBarry Smith ze.Attach(A->cmap->N, 1, *a->grid, 0, 0, z, A->cmap->n); 301e8146892SSatish Balay El::Gemv(El::TRANSPOSE, one, *a->emat, xe, one, ze); 302e883f9d5SXuan Zhou } 3039566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X, (const PetscScalar **)&x)); 3049566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(Z, (PetscScalar **)&z)); 305e883f9d5SXuan Zhou PetscFunctionReturn(0); 306e883f9d5SXuan Zhou } 307e883f9d5SXuan Zhou 308*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_Elemental(Mat A, Mat B, Mat C) 309*d71ae5a4SJacob Faibussowitsch { 310c1d1b975SXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 311c1d1b975SXuan Zhou Mat_Elemental *b = (Mat_Elemental *)B->data; 3129a9e8502SHong Zhang Mat_Elemental *c = (Mat_Elemental *)C->data; 313e6dea9dbSXuan Zhou PetscElemScalar one = 1, zero = 0; 314c1d1b975SXuan Zhou 315c1d1b975SXuan Zhou PetscFunctionBegin; 316aae2c449SHong Zhang { /* Scoping so that constructor is called before pointer is returned */ 317e8146892SSatish Balay El::Gemm(El::NORMAL, El::NORMAL, one, *a->emat, *b->emat, zero, *c->emat); 318aae2c449SHong Zhang } 3199a9e8502SHong Zhang C->assembled = PETSC_TRUE; 3209a9e8502SHong Zhang PetscFunctionReturn(0); 3219a9e8502SHong Zhang } 3229a9e8502SHong Zhang 323*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_Elemental(Mat A, Mat B, PetscReal fill, Mat Ce) 324*d71ae5a4SJacob Faibussowitsch { 3259a9e8502SHong Zhang PetscFunctionBegin; 3269566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Ce, A->rmap->n, B->cmap->n, PETSC_DECIDE, PETSC_DECIDE)); 3279566063dSJacob Faibussowitsch PetscCall(MatSetType(Ce, MATELEMENTAL)); 3289566063dSJacob Faibussowitsch PetscCall(MatSetUp(Ce)); 3294222ddf1SHong Zhang Ce->ops->matmultnumeric = MatMatMultNumeric_Elemental; 330c1d1b975SXuan Zhou PetscFunctionReturn(0); 331c1d1b975SXuan Zhou } 332c1d1b975SXuan Zhou 333*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatTransposeMultNumeric_Elemental(Mat A, Mat B, Mat C) 334*d71ae5a4SJacob Faibussowitsch { 335df311e6cSXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 336df311e6cSXuan Zhou Mat_Elemental *b = (Mat_Elemental *)B->data; 337df311e6cSXuan Zhou Mat_Elemental *c = (Mat_Elemental *)C->data; 338e6dea9dbSXuan Zhou PetscElemScalar one = 1, zero = 0; 339df311e6cSXuan Zhou 340df311e6cSXuan Zhou PetscFunctionBegin; 341df311e6cSXuan Zhou { /* Scoping so that constructor is called before pointer is returned */ 342e8146892SSatish Balay El::Gemm(El::NORMAL, El::TRANSPOSE, one, *a->emat, *b->emat, zero, *c->emat); 343df311e6cSXuan Zhou } 344df311e6cSXuan Zhou C->assembled = PETSC_TRUE; 345df311e6cSXuan Zhou PetscFunctionReturn(0); 346df311e6cSXuan Zhou } 347df311e6cSXuan Zhou 348*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatTransposeMultSymbolic_Elemental(Mat A, Mat B, PetscReal fill, Mat C) 349*d71ae5a4SJacob Faibussowitsch { 350df311e6cSXuan Zhou PetscFunctionBegin; 3519566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, A->rmap->n, B->rmap->n, PETSC_DECIDE, PETSC_DECIDE)); 3529566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATELEMENTAL)); 3539566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 354df311e6cSXuan Zhou PetscFunctionReturn(0); 355df311e6cSXuan Zhou } 356df311e6cSXuan Zhou 3574222ddf1SHong Zhang /* --------------------------------------- */ 358*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_Elemental_AB(Mat C) 359*d71ae5a4SJacob Faibussowitsch { 3604222ddf1SHong Zhang PetscFunctionBegin; 3614222ddf1SHong Zhang C->ops->matmultsymbolic = MatMatMultSymbolic_Elemental; 3624222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_AB; 3634222ddf1SHong Zhang PetscFunctionReturn(0); 3644222ddf1SHong Zhang } 3654222ddf1SHong Zhang 366*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_Elemental_ABt(Mat C) 367*d71ae5a4SJacob Faibussowitsch { 3684222ddf1SHong Zhang PetscFunctionBegin; 3694222ddf1SHong Zhang C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_Elemental; 3704222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_ABt; 3714222ddf1SHong Zhang PetscFunctionReturn(0); 3724222ddf1SHong Zhang } 3734222ddf1SHong Zhang 374*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Elemental(Mat C) 375*d71ae5a4SJacob Faibussowitsch { 3764222ddf1SHong Zhang Mat_Product *product = C->product; 3774222ddf1SHong Zhang 3784222ddf1SHong Zhang PetscFunctionBegin; 3794222ddf1SHong Zhang switch (product->type) { 380*d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 381*d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Elemental_AB(C)); 382*d71ae5a4SJacob Faibussowitsch break; 383*d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABt: 384*d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Elemental_ABt(C)); 385*d71ae5a4SJacob Faibussowitsch break; 386*d71ae5a4SJacob Faibussowitsch default: 387*d71ae5a4SJacob Faibussowitsch break; 3884222ddf1SHong Zhang } 3894222ddf1SHong Zhang PetscFunctionReturn(0); 3904222ddf1SHong Zhang } 391f6e5db1bSPierre Jolivet 392*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_Elemental_MPIDense(Mat A, Mat B, Mat C) 393*d71ae5a4SJacob Faibussowitsch { 394f6e5db1bSPierre Jolivet Mat Be, Ce; 395f6e5db1bSPierre Jolivet 396f6e5db1bSPierre Jolivet PetscFunctionBegin; 3979566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATELEMENTAL, MAT_INITIAL_MATRIX, &Be)); 3989566063dSJacob Faibussowitsch PetscCall(MatMatMult(A, Be, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &Ce)); 3999566063dSJacob Faibussowitsch PetscCall(MatConvert(Ce, MATMPIDENSE, MAT_REUSE_MATRIX, &C)); 4009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Be)); 4019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ce)); 402f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 403f6e5db1bSPierre Jolivet } 404f6e5db1bSPierre Jolivet 405*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultSymbolic_Elemental_MPIDense(Mat A, Mat B, PetscReal fill, Mat C) 406*d71ae5a4SJacob Faibussowitsch { 407f6e5db1bSPierre Jolivet PetscFunctionBegin; 4089566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, A->rmap->n, B->cmap->n, PETSC_DECIDE, PETSC_DECIDE)); 4099566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATMPIDENSE)); 4109566063dSJacob Faibussowitsch PetscCall(MatSetUp(C)); 411f6e5db1bSPierre Jolivet C->ops->matmultnumeric = MatMatMultNumeric_Elemental_MPIDense; 412f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 413f6e5db1bSPierre Jolivet } 414f6e5db1bSPierre Jolivet 415*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetFromOptions_Elemental_MPIDense_AB(Mat C) 416*d71ae5a4SJacob Faibussowitsch { 417f6e5db1bSPierre Jolivet PetscFunctionBegin; 418f6e5db1bSPierre Jolivet C->ops->matmultsymbolic = MatMatMultSymbolic_Elemental_MPIDense; 419f6e5db1bSPierre Jolivet C->ops->productsymbolic = MatProductSymbolic_AB; 420f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 421f6e5db1bSPierre Jolivet } 422f6e5db1bSPierre Jolivet 423*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetFromOptions_Elemental_MPIDense(Mat C) 424*d71ae5a4SJacob Faibussowitsch { 425f6e5db1bSPierre Jolivet Mat_Product *product = C->product; 426f6e5db1bSPierre Jolivet 427f6e5db1bSPierre Jolivet PetscFunctionBegin; 42848a46eb9SPierre Jolivet if (product->type == MATPRODUCT_AB) PetscCall(MatProductSetFromOptions_Elemental_MPIDense_AB(C)); 429f6e5db1bSPierre Jolivet PetscFunctionReturn(0); 430f6e5db1bSPierre Jolivet } 4314222ddf1SHong Zhang /* --------------------------------------- */ 4324222ddf1SHong Zhang 433*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_Elemental(Mat A, Vec D) 434*d71ae5a4SJacob Faibussowitsch { 435a9d89745SXuan Zhou PetscInt i, nrows, ncols, nD, rrank, ridx, crank, cidx; 436a9d89745SXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 437a9d89745SXuan Zhou PetscElemScalar v; 438ce94432eSBarry Smith MPI_Comm comm; 43961119200SXuan Zhou 44061119200SXuan Zhou PetscFunctionBegin; 4419566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 4429566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &nrows, &ncols)); 443a9d89745SXuan Zhou nD = nrows > ncols ? ncols : nrows; 444a9d89745SXuan Zhou for (i = 0; i < nD; i++) { 445a9d89745SXuan Zhou PetscInt erow, ecol; 446a9d89745SXuan Zhou P2RO(A, 0, i, &rrank, &ridx); 447a9d89745SXuan Zhou RO2E(A, 0, rrank, ridx, &erow); 448aed4548fSBarry Smith PetscCheck(rrank >= 0 && ridx >= 0 && erow >= 0, comm, PETSC_ERR_PLIB, "Incorrect row translation"); 449a9d89745SXuan Zhou P2RO(A, 1, i, &crank, &cidx); 450a9d89745SXuan Zhou RO2E(A, 1, crank, cidx, &ecol); 451aed4548fSBarry Smith PetscCheck(crank >= 0 && cidx >= 0 && ecol >= 0, comm, PETSC_ERR_PLIB, "Incorrect col translation"); 452a9d89745SXuan Zhou v = a->emat->Get(erow, ecol); 4539566063dSJacob Faibussowitsch PetscCall(VecSetValues(D, 1, &i, (PetscScalar *)&v, INSERT_VALUES)); 454ade3cc5eSXuan Zhou } 4559566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(D)); 4569566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(D)); 45761119200SXuan Zhou PetscFunctionReturn(0); 45861119200SXuan Zhou } 45961119200SXuan Zhou 460*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_Elemental(Mat X, Vec L, Vec R) 461*d71ae5a4SJacob Faibussowitsch { 462ade3cc5eSXuan Zhou Mat_Elemental *x = (Mat_Elemental *)X->data; 463ade3cc5eSXuan Zhou const PetscElemScalar *d; 464ade3cc5eSXuan Zhou 465ade3cc5eSXuan Zhou PetscFunctionBegin; 4669065cd98SJed Brown if (R) { 4679566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(R, (const PetscScalar **)&d)); 468e8146892SSatish Balay El::DistMatrix<PetscElemScalar, El::VC, El::STAR> de; 4690c18141cSBarry Smith de.LockedAttach(X->cmap->N, 1, *x->grid, 0, 0, d, X->cmap->n); 470e8146892SSatish Balay El::DiagonalScale(El::RIGHT, El::NORMAL, de, *x->emat); 4719566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(R, (const PetscScalar **)&d)); 4729065cd98SJed Brown } 4739065cd98SJed Brown if (L) { 4749566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(L, (const PetscScalar **)&d)); 475e8146892SSatish Balay El::DistMatrix<PetscElemScalar, El::VC, El::STAR> de; 4760c18141cSBarry Smith de.LockedAttach(X->rmap->N, 1, *x->grid, 0, 0, d, X->rmap->n); 477e8146892SSatish Balay El::DiagonalScale(El::LEFT, El::NORMAL, de, *x->emat); 4789566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(L, (const PetscScalar **)&d)); 479ade3cc5eSXuan Zhou } 480ade3cc5eSXuan Zhou PetscFunctionReturn(0); 481ade3cc5eSXuan Zhou } 482ade3cc5eSXuan Zhou 483*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_Elemental(Mat A, PetscBool *missing, PetscInt *d) 484*d71ae5a4SJacob Faibussowitsch { 48534fa46e1SFrancesco Ballarin PetscFunctionBegin; 48634fa46e1SFrancesco Ballarin *missing = PETSC_FALSE; 48734fa46e1SFrancesco Ballarin PetscFunctionReturn(0); 48834fa46e1SFrancesco Ballarin } 48934fa46e1SFrancesco Ballarin 490*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_Elemental(Mat X, PetscScalar a) 491*d71ae5a4SJacob Faibussowitsch { 49265b78793SXuan Zhou Mat_Elemental *x = (Mat_Elemental *)X->data; 49365b78793SXuan Zhou 49465b78793SXuan Zhou PetscFunctionBegin; 495e8146892SSatish Balay El::Scale((PetscElemScalar)a, *x->emat); 49665b78793SXuan Zhou PetscFunctionReturn(0); 49765b78793SXuan Zhou } 49865b78793SXuan Zhou 499f82baa17SHong Zhang /* 500f82baa17SHong Zhang MatAXPY - Computes Y = a*X + Y. 501f82baa17SHong Zhang */ 502*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_Elemental(Mat Y, PetscScalar a, Mat X, MatStructure str) 503*d71ae5a4SJacob Faibussowitsch { 504e09a3074SHong Zhang Mat_Elemental *x = (Mat_Elemental *)X->data; 505e09a3074SHong Zhang Mat_Elemental *y = (Mat_Elemental *)Y->data; 506e09a3074SHong Zhang 507e09a3074SHong Zhang PetscFunctionBegin; 508e8146892SSatish Balay El::Axpy((PetscElemScalar)a, *x->emat, *y->emat); 5099566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 510e09a3074SHong Zhang PetscFunctionReturn(0); 511e09a3074SHong Zhang } 512e09a3074SHong Zhang 513*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_Elemental(Mat A, Mat B, MatStructure str) 514*d71ae5a4SJacob Faibussowitsch { 515d6223691SXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 516d6223691SXuan Zhou Mat_Elemental *b = (Mat_Elemental *)B->data; 517d6223691SXuan Zhou 518d6223691SXuan Zhou PetscFunctionBegin; 519e8146892SSatish Balay El::Copy(*a->emat, *b->emat); 5209566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 521d6223691SXuan Zhou PetscFunctionReturn(0); 522d6223691SXuan Zhou } 523d6223691SXuan Zhou 524*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDuplicate_Elemental(Mat A, MatDuplicateOption op, Mat *B) 525*d71ae5a4SJacob Faibussowitsch { 526df311e6cSXuan Zhou Mat Be; 527ce94432eSBarry Smith MPI_Comm comm; 528df311e6cSXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 529df311e6cSXuan Zhou 530df311e6cSXuan Zhou PetscFunctionBegin; 5319566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 5329566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &Be)); 5339566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Be, A->rmap->n, A->cmap->n, PETSC_DECIDE, PETSC_DECIDE)); 5349566063dSJacob Faibussowitsch PetscCall(MatSetType(Be, MATELEMENTAL)); 5359566063dSJacob Faibussowitsch PetscCall(MatSetUp(Be)); 536df311e6cSXuan Zhou *B = Be; 537df311e6cSXuan Zhou if (op == MAT_COPY_VALUES) { 538df311e6cSXuan Zhou Mat_Elemental *b = (Mat_Elemental *)Be->data; 539e8146892SSatish Balay El::Copy(*a->emat, *b->emat); 540df311e6cSXuan Zhou } 541df311e6cSXuan Zhou Be->assembled = PETSC_TRUE; 542df311e6cSXuan Zhou PetscFunctionReturn(0); 543df311e6cSXuan Zhou } 544df311e6cSXuan Zhou 545*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_Elemental(Mat A, MatReuse reuse, Mat *B) 546*d71ae5a4SJacob Faibussowitsch { 547ec8cb81fSBarry Smith Mat Be = *B; 548ce94432eSBarry Smith MPI_Comm comm; 5494fe7bbcaSHong Zhang Mat_Elemental *a = (Mat_Elemental *)A->data, *b; 550d6223691SXuan Zhou 551d6223691SXuan Zhou PetscFunctionBegin; 5527fb60732SBarry Smith if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B)); 5539566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 5545cb544a0SHong Zhang /* Only out-of-place supported */ 5555f80ce2aSJacob Faibussowitsch PetscCheck(reuse != MAT_INPLACE_MATRIX, comm, PETSC_ERR_SUP, "Only out-of-place supported"); 5565262d616SXuan Zhou if (reuse == MAT_INITIAL_MATRIX) { 5579566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &Be)); 5589566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Be, A->cmap->n, A->rmap->n, PETSC_DECIDE, PETSC_DECIDE)); 5599566063dSJacob Faibussowitsch PetscCall(MatSetType(Be, MATELEMENTAL)); 5609566063dSJacob Faibussowitsch PetscCall(MatSetUp(Be)); 5615262d616SXuan Zhou *B = Be; 5625262d616SXuan Zhou } 5634fe7bbcaSHong Zhang b = (Mat_Elemental *)Be->data; 564e8146892SSatish Balay El::Transpose(*a->emat, *b->emat); 5655262d616SXuan Zhou Be->assembled = PETSC_TRUE; 566d6223691SXuan Zhou PetscFunctionReturn(0); 567d6223691SXuan Zhou } 568d6223691SXuan Zhou 569*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConjugate_Elemental(Mat A) 570*d71ae5a4SJacob Faibussowitsch { 571dfcb0403SXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 572dfcb0403SXuan Zhou 573dfcb0403SXuan Zhou PetscFunctionBegin; 574e8146892SSatish Balay El::Conjugate(*a->emat); 575dfcb0403SXuan Zhou PetscFunctionReturn(0); 576dfcb0403SXuan Zhou } 577dfcb0403SXuan Zhou 578*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHermitianTranspose_Elemental(Mat A, MatReuse reuse, Mat *B) 579*d71ae5a4SJacob Faibussowitsch { 580ec8cb81fSBarry Smith Mat Be = *B; 581ce94432eSBarry Smith MPI_Comm comm; 5824a29722dSXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data, *b; 5834a29722dSXuan Zhou 5844a29722dSXuan Zhou PetscFunctionBegin; 5859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 5865cb544a0SHong Zhang /* Only out-of-place supported */ 5874a29722dSXuan Zhou if (reuse == MAT_INITIAL_MATRIX) { 5889566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &Be)); 5899566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Be, A->cmap->n, A->rmap->n, PETSC_DECIDE, PETSC_DECIDE)); 5909566063dSJacob Faibussowitsch PetscCall(MatSetType(Be, MATELEMENTAL)); 5919566063dSJacob Faibussowitsch PetscCall(MatSetUp(Be)); 5924a29722dSXuan Zhou *B = Be; 5934a29722dSXuan Zhou } 5944a29722dSXuan Zhou b = (Mat_Elemental *)Be->data; 595e8146892SSatish Balay El::Adjoint(*a->emat, *b->emat); 5964a29722dSXuan Zhou Be->assembled = PETSC_TRUE; 5974a29722dSXuan Zhou PetscFunctionReturn(0); 5984a29722dSXuan Zhou } 5994a29722dSXuan Zhou 600*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_Elemental(Mat A, Vec B, Vec X) 601*d71ae5a4SJacob Faibussowitsch { 6021f881ff8SXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 603df311e6cSXuan Zhou PetscElemScalar *x; 604ea394475SSatish Balay PetscInt pivoting = a->pivoting; 6051f881ff8SXuan Zhou 6061f881ff8SXuan Zhou PetscFunctionBegin; 6079566063dSJacob Faibussowitsch PetscCall(VecCopy(B, X)); 6089566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, (PetscScalar **)&x)); 609ea394475SSatish Balay 610e8146892SSatish Balay El::DistMatrix<PetscElemScalar, El::VC, El::STAR> xe; 6110c18141cSBarry Smith xe.Attach(A->rmap->N, 1, *a->grid, 0, 0, x, A->rmap->n); 612e8146892SSatish Balay El::DistMatrix<PetscElemScalar, El::MC, El::MR> xer(xe); 613fc54b460SXuan Zhou switch (A->factortype) { 614fc54b460SXuan Zhou case MAT_FACTOR_LU: 615ea394475SSatish Balay if (pivoting == 0) { 616e8146892SSatish Balay El::lu::SolveAfter(El::NORMAL, *a->emat, xer); 617ea394475SSatish Balay } else if (pivoting == 1) { 618ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL, *a->emat, *a->P, xer); 619ea394475SSatish Balay } else { /* pivoting == 2 */ 620ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL, *a->emat, *a->P, *a->Q, xer); 6211f881ff8SXuan Zhou } 622fc54b460SXuan Zhou break; 623*d71ae5a4SJacob Faibussowitsch case MAT_FACTOR_CHOLESKY: 624*d71ae5a4SJacob Faibussowitsch El::cholesky::SolveAfter(El::UPPER, El::NORMAL, *a->emat, xer); 625*d71ae5a4SJacob Faibussowitsch break; 626*d71ae5a4SJacob Faibussowitsch default: 627*d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unfactored Matrix or Unsupported MatFactorType"); 628*d71ae5a4SJacob Faibussowitsch break; 6291f881ff8SXuan Zhou } 630ea394475SSatish Balay El::Copy(xer, xe); 631ea394475SSatish Balay 6329566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, (PetscScalar **)&x)); 6331f881ff8SXuan Zhou PetscFunctionReturn(0); 6341f881ff8SXuan Zhou } 6351f881ff8SXuan Zhou 636*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveAdd_Elemental(Mat A, Vec B, Vec Y, Vec X) 637*d71ae5a4SJacob Faibussowitsch { 638df311e6cSXuan Zhou PetscFunctionBegin; 6399566063dSJacob Faibussowitsch PetscCall(MatSolve_Elemental(A, B, X)); 6409566063dSJacob Faibussowitsch PetscCall(VecAXPY(X, 1, Y)); 641df311e6cSXuan Zhou PetscFunctionReturn(0); 642df311e6cSXuan Zhou } 643df311e6cSXuan Zhou 644*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_Elemental(Mat A, Mat B, Mat X) 645*d71ae5a4SJacob Faibussowitsch { 6461f0e42cfSHong Zhang Mat_Elemental *a = (Mat_Elemental *)A->data; 64742ba530cSPierre Jolivet Mat_Elemental *x; 64842ba530cSPierre Jolivet Mat C; 649ea394475SSatish Balay PetscInt pivoting = a->pivoting; 65042ba530cSPierre Jolivet PetscBool flg; 65142ba530cSPierre Jolivet MatType type; 6521f0e42cfSHong Zhang 653ae844d54SHong Zhang PetscFunctionBegin; 6549566063dSJacob Faibussowitsch PetscCall(MatGetType(X, &type)); 6559566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(type, MATELEMENTAL, &flg)); 65642ba530cSPierre Jolivet if (!flg) { 6579566063dSJacob Faibussowitsch PetscCall(MatConvert(B, MATELEMENTAL, MAT_INITIAL_MATRIX, &C)); 65842ba530cSPierre Jolivet x = (Mat_Elemental *)C->data; 65942ba530cSPierre Jolivet } else { 66042ba530cSPierre Jolivet x = (Mat_Elemental *)X->data; 66142ba530cSPierre Jolivet El::Copy(*((Mat_Elemental *)B->data)->emat, *x->emat); 66242ba530cSPierre Jolivet } 663fc54b460SXuan Zhou switch (A->factortype) { 664fc54b460SXuan Zhou case MAT_FACTOR_LU: 665ea394475SSatish Balay if (pivoting == 0) { 666e8146892SSatish Balay El::lu::SolveAfter(El::NORMAL, *a->emat, *x->emat); 667ea394475SSatish Balay } else if (pivoting == 1) { 668ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL, *a->emat, *a->P, *x->emat); 669ea394475SSatish Balay } else { 670ea394475SSatish Balay El::lu::SolveAfter(El::NORMAL, *a->emat, *a->P, *a->Q, *x->emat); 671d6223691SXuan Zhou } 672fc54b460SXuan Zhou break; 673*d71ae5a4SJacob Faibussowitsch case MAT_FACTOR_CHOLESKY: 674*d71ae5a4SJacob Faibussowitsch El::cholesky::SolveAfter(El::UPPER, El::NORMAL, *a->emat, *x->emat); 675*d71ae5a4SJacob Faibussowitsch break; 676*d71ae5a4SJacob Faibussowitsch default: 677*d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unfactored Matrix or Unsupported MatFactorType"); 678*d71ae5a4SJacob Faibussowitsch break; 679fc54b460SXuan Zhou } 68042ba530cSPierre Jolivet if (!flg) { 6819566063dSJacob Faibussowitsch PetscCall(MatConvert(C, type, MAT_REUSE_MATRIX, &X)); 6829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&C)); 68342ba530cSPierre Jolivet } 684ae844d54SHong Zhang PetscFunctionReturn(0); 685ae844d54SHong Zhang } 686ae844d54SHong Zhang 687*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactor_Elemental(Mat A, IS row, IS col, const MatFactorInfo *info) 688*d71ae5a4SJacob Faibussowitsch { 6897c920d81SXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 690ea394475SSatish Balay PetscInt pivoting = a->pivoting; 6917c920d81SXuan Zhou 692ae844d54SHong Zhang PetscFunctionBegin; 693ea394475SSatish Balay if (pivoting == 0) { 694e8146892SSatish Balay El::LU(*a->emat); 695ea394475SSatish Balay } else if (pivoting == 1) { 696ea394475SSatish Balay El::LU(*a->emat, *a->P); 697ea394475SSatish Balay } else { 698ea394475SSatish Balay El::LU(*a->emat, *a->P, *a->Q); 699d6223691SXuan Zhou } 7001293973dSHong Zhang A->factortype = MAT_FACTOR_LU; 701834d3fecSHong Zhang A->assembled = PETSC_TRUE; 702f6224b95SHong Zhang 7039566063dSJacob Faibussowitsch PetscCall(PetscFree(A->solvertype)); 7049566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERELEMENTAL, &A->solvertype)); 705ae844d54SHong Zhang PetscFunctionReturn(0); 706ae844d54SHong Zhang } 707ae844d54SHong Zhang 708*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorNumeric_Elemental(Mat F, Mat A, const MatFactorInfo *info) 709*d71ae5a4SJacob Faibussowitsch { 710d7c3f9d8SHong Zhang PetscFunctionBegin; 7119566063dSJacob Faibussowitsch PetscCall(MatCopy(A, F, SAME_NONZERO_PATTERN)); 7129566063dSJacob Faibussowitsch PetscCall(MatLUFactor_Elemental(F, 0, 0, info)); 713d7c3f9d8SHong Zhang PetscFunctionReturn(0); 714d7c3f9d8SHong Zhang } 715d7c3f9d8SHong Zhang 716*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorSymbolic_Elemental(Mat F, Mat A, IS r, IS c, const MatFactorInfo *info) 717*d71ae5a4SJacob Faibussowitsch { 718d7c3f9d8SHong Zhang PetscFunctionBegin; 719d8304050SJose E. Roman /* F is created and allocated by MatGetFactor_elemental_petsc(), skip this routine. */ 720d7c3f9d8SHong Zhang PetscFunctionReturn(0); 721d7c3f9d8SHong Zhang } 722d7c3f9d8SHong Zhang 723*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCholeskyFactor_Elemental(Mat A, IS perm, const MatFactorInfo *info) 724*d71ae5a4SJacob Faibussowitsch { 72545cf121fSXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 726e8146892SSatish Balay El::DistMatrix<PetscElemScalar, El::MC, El::STAR> d; 72745cf121fSXuan Zhou 72845cf121fSXuan Zhou PetscFunctionBegin; 729e8146892SSatish Balay El::Cholesky(El::UPPER, *a->emat); 730fc54b460SXuan Zhou A->factortype = MAT_FACTOR_CHOLESKY; 731834d3fecSHong Zhang A->assembled = PETSC_TRUE; 732f6224b95SHong Zhang 7339566063dSJacob Faibussowitsch PetscCall(PetscFree(A->solvertype)); 7349566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERELEMENTAL, &A->solvertype)); 73545cf121fSXuan Zhou PetscFunctionReturn(0); 73645cf121fSXuan Zhou } 73745cf121fSXuan Zhou 738*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCholeskyFactorNumeric_Elemental(Mat F, Mat A, const MatFactorInfo *info) 739*d71ae5a4SJacob Faibussowitsch { 740cb76c1d8SXuan Zhou PetscFunctionBegin; 7419566063dSJacob Faibussowitsch PetscCall(MatCopy(A, F, SAME_NONZERO_PATTERN)); 7429566063dSJacob Faibussowitsch PetscCall(MatCholeskyFactor_Elemental(F, 0, info)); 743cb76c1d8SXuan Zhou PetscFunctionReturn(0); 74479673f7bSHong Zhang } 745cb76c1d8SXuan Zhou 746*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCholeskyFactorSymbolic_Elemental(Mat F, Mat A, IS perm, const MatFactorInfo *info) 747*d71ae5a4SJacob Faibussowitsch { 74879673f7bSHong Zhang PetscFunctionBegin; 749d8304050SJose E. Roman /* F is created and allocated by MatGetFactor_elemental_petsc(), skip this routine. */ 75079673f7bSHong Zhang PetscFunctionReturn(0); 75179673f7bSHong Zhang } 75279673f7bSHong Zhang 753*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatFactorGetSolverType_elemental_elemental(Mat A, MatSolverType *type) 754*d71ae5a4SJacob Faibussowitsch { 75515767789SHong Zhang PetscFunctionBegin; 75615767789SHong Zhang *type = MATSOLVERELEMENTAL; 75715767789SHong Zhang PetscFunctionReturn(0); 75815767789SHong Zhang } 75915767789SHong Zhang 760*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetFactor_elemental_elemental(Mat A, MatFactorType ftype, Mat *F) 761*d71ae5a4SJacob Faibussowitsch { 7621293973dSHong Zhang Mat B; 7631293973dSHong Zhang 7641293973dSHong Zhang PetscFunctionBegin; 7651293973dSHong Zhang /* Create the factorization matrix */ 7669566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B)); 7679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, PETSC_DECIDE, PETSC_DECIDE)); 7689566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATELEMENTAL)); 7699566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 7701293973dSHong Zhang B->factortype = ftype; 77166e17bc3SBarry Smith B->trivialsymbolic = PETSC_TRUE; 7729566063dSJacob Faibussowitsch PetscCall(PetscFree(B->solvertype)); 7739566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATSOLVERELEMENTAL, &B->solvertype)); 77400c67f3bSHong Zhang 7759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatFactorGetSolverType_C", MatFactorGetSolverType_elemental_elemental)); 7761293973dSHong Zhang *F = B; 7771293973dSHong Zhang PetscFunctionReturn(0); 7781293973dSHong Zhang } 7791293973dSHong Zhang 780*d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Elemental(void) 781*d71ae5a4SJacob Faibussowitsch { 78242c9c57cSBarry Smith PetscFunctionBegin; 7839566063dSJacob Faibussowitsch PetscCall(MatSolverTypeRegister(MATSOLVERELEMENTAL, MATELEMENTAL, MAT_FACTOR_LU, MatGetFactor_elemental_elemental)); 7849566063dSJacob Faibussowitsch PetscCall(MatSolverTypeRegister(MATSOLVERELEMENTAL, MATELEMENTAL, MAT_FACTOR_CHOLESKY, MatGetFactor_elemental_elemental)); 78542c9c57cSBarry Smith PetscFunctionReturn(0); 78642c9c57cSBarry Smith } 78742c9c57cSBarry Smith 788*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatNorm_Elemental(Mat A, NormType type, PetscReal *nrm) 789*d71ae5a4SJacob Faibussowitsch { 7901f881ff8SXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 7911f881ff8SXuan Zhou 7921f881ff8SXuan Zhou PetscFunctionBegin; 7931f881ff8SXuan Zhou switch (type) { 794*d71ae5a4SJacob Faibussowitsch case NORM_1: 795*d71ae5a4SJacob Faibussowitsch *nrm = El::OneNorm(*a->emat); 796*d71ae5a4SJacob Faibussowitsch break; 797*d71ae5a4SJacob Faibussowitsch case NORM_FROBENIUS: 798*d71ae5a4SJacob Faibussowitsch *nrm = El::FrobeniusNorm(*a->emat); 799*d71ae5a4SJacob Faibussowitsch break; 800*d71ae5a4SJacob Faibussowitsch case NORM_INFINITY: 801*d71ae5a4SJacob Faibussowitsch *nrm = El::InfinityNorm(*a->emat); 802*d71ae5a4SJacob Faibussowitsch break; 803*d71ae5a4SJacob Faibussowitsch default: 804*d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unsupported norm type"); 8051f881ff8SXuan Zhou } 8061f881ff8SXuan Zhou PetscFunctionReturn(0); 8071f881ff8SXuan Zhou } 8081f881ff8SXuan Zhou 809*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_Elemental(Mat A) 810*d71ae5a4SJacob Faibussowitsch { 8115262d616SXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 8125262d616SXuan Zhou 8135262d616SXuan Zhou PetscFunctionBegin; 814e8146892SSatish Balay El::Zero(*a->emat); 8155262d616SXuan Zhou PetscFunctionReturn(0); 8165262d616SXuan Zhou } 8175262d616SXuan Zhou 818*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetOwnershipIS_Elemental(Mat A, IS *rows, IS *cols) 819*d71ae5a4SJacob Faibussowitsch { 820db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental *)A->data; 821db31f6deSJed Brown PetscInt i, m, shift, stride, *idx; 822db31f6deSJed Brown 823db31f6deSJed Brown PetscFunctionBegin; 824db31f6deSJed Brown if (rows) { 825db31f6deSJed Brown m = a->emat->LocalHeight(); 826db31f6deSJed Brown shift = a->emat->ColShift(); 827db31f6deSJed Brown stride = a->emat->ColStride(); 8289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idx)); 829db31f6deSJed Brown for (i = 0; i < m; i++) { 830db31f6deSJed Brown PetscInt rank, offset; 831db31f6deSJed Brown E2RO(A, 0, shift + i * stride, &rank, &offset); 832db31f6deSJed Brown RO2P(A, 0, rank, offset, &idx[i]); 833db31f6deSJed Brown } 8349566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, idx, PETSC_OWN_POINTER, rows)); 835db31f6deSJed Brown } 836db31f6deSJed Brown if (cols) { 837db31f6deSJed Brown m = a->emat->LocalWidth(); 838db31f6deSJed Brown shift = a->emat->RowShift(); 839db31f6deSJed Brown stride = a->emat->RowStride(); 8409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m, &idx)); 841db31f6deSJed Brown for (i = 0; i < m; i++) { 842db31f6deSJed Brown PetscInt rank, offset; 843db31f6deSJed Brown E2RO(A, 1, shift + i * stride, &rank, &offset); 844db31f6deSJed Brown RO2P(A, 1, rank, offset, &idx[i]); 845db31f6deSJed Brown } 8469566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, idx, PETSC_OWN_POINTER, cols)); 847db31f6deSJed Brown } 848db31f6deSJed Brown PetscFunctionReturn(0); 849db31f6deSJed Brown } 850db31f6deSJed Brown 851*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_Elemental_Dense(Mat A, MatType newtype, MatReuse reuse, Mat *B) 852*d71ae5a4SJacob Faibussowitsch { 8532ef0cf24SXuan Zhou Mat Bmpi; 854af295397SXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 855ce94432eSBarry Smith MPI_Comm comm; 856fa9e26c8SHong Zhang IS isrows, iscols; 857fa9e26c8SHong Zhang PetscInt rrank, ridx, crank, cidx, nrows, ncols, i, j, erow, ecol, elrow, elcol; 858fa9e26c8SHong Zhang const PetscInt *rows, *cols; 859df311e6cSXuan Zhou PetscElemScalar v; 860fa9e26c8SHong Zhang const El::Grid &grid = a->emat->Grid(); 861af295397SXuan Zhou 862af295397SXuan Zhou PetscFunctionBegin; 8639566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 864a000e53bSHong Zhang 865de0a22f0SHong Zhang if (reuse == MAT_REUSE_MATRIX) { 866de0a22f0SHong Zhang Bmpi = *B; 867de0a22f0SHong Zhang } else { 8689566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &Bmpi)); 8699566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Bmpi, A->rmap->n, A->cmap->n, PETSC_DECIDE, PETSC_DECIDE)); 8709566063dSJacob Faibussowitsch PetscCall(MatSetType(Bmpi, MATDENSE)); 8719566063dSJacob Faibussowitsch PetscCall(MatSetUp(Bmpi)); 872de0a22f0SHong Zhang } 873fa9e26c8SHong Zhang 874fa9e26c8SHong Zhang /* Get local entries of A */ 8759566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipIS(A, &isrows, &iscols)); 8769566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(isrows, &nrows)); 8779566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrows, &rows)); 8789566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(iscols, &ncols)); 8799566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscols, &cols)); 880fa9e26c8SHong Zhang 88157299f2fSHong Zhang if (a->roworiented) { 8822ef0cf24SXuan Zhou for (i = 0; i < nrows; i++) { 883fa9e26c8SHong Zhang P2RO(A, 0, rows[i], &rrank, &ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */ 8842ef0cf24SXuan Zhou RO2E(A, 0, rrank, ridx, &erow); 885aed4548fSBarry Smith PetscCheck(rrank >= 0 && ridx >= 0 && erow >= 0, comm, PETSC_ERR_PLIB, "Incorrect row translation"); 8862ef0cf24SXuan Zhou for (j = 0; j < ncols; j++) { 887fa9e26c8SHong Zhang P2RO(A, 1, cols[j], &crank, &cidx); 8882ef0cf24SXuan Zhou RO2E(A, 1, crank, cidx, &ecol); 889aed4548fSBarry Smith PetscCheck(crank >= 0 && cidx >= 0 && ecol >= 0, comm, PETSC_ERR_PLIB, "Incorrect col translation"); 890fa9e26c8SHong Zhang 891fa9e26c8SHong Zhang elrow = erow / grid.MCSize(); /* Elemental local row index */ 892fa9e26c8SHong Zhang elcol = ecol / grid.MRSize(); /* Elemental local column index */ 893fa9e26c8SHong Zhang v = a->emat->GetLocal(elrow, elcol); 8949566063dSJacob Faibussowitsch PetscCall(MatSetValues(Bmpi, 1, &rows[i], 1, &cols[j], (PetscScalar *)&v, INSERT_VALUES)); 8952ef0cf24SXuan Zhou } 8962ef0cf24SXuan Zhou } 89757299f2fSHong Zhang } else { /* column-oriented */ 89857299f2fSHong Zhang for (j = 0; j < ncols; j++) { 89957299f2fSHong Zhang P2RO(A, 1, cols[j], &crank, &cidx); 90057299f2fSHong Zhang RO2E(A, 1, crank, cidx, &ecol); 901aed4548fSBarry Smith PetscCheck(crank >= 0 && cidx >= 0 && ecol >= 0, comm, PETSC_ERR_PLIB, "Incorrect col translation"); 90257299f2fSHong Zhang for (i = 0; i < nrows; i++) { 90357299f2fSHong Zhang P2RO(A, 0, rows[i], &rrank, &ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */ 90457299f2fSHong Zhang RO2E(A, 0, rrank, ridx, &erow); 905aed4548fSBarry Smith PetscCheck(rrank >= 0 && ridx >= 0 && erow >= 0, comm, PETSC_ERR_PLIB, "Incorrect row translation"); 90657299f2fSHong Zhang 90757299f2fSHong Zhang elrow = erow / grid.MCSize(); /* Elemental local row index */ 90857299f2fSHong Zhang elcol = ecol / grid.MRSize(); /* Elemental local column index */ 90957299f2fSHong Zhang v = a->emat->GetLocal(elrow, elcol); 9109566063dSJacob Faibussowitsch PetscCall(MatSetValues(Bmpi, 1, &rows[i], 1, &cols[j], (PetscScalar *)&v, INSERT_VALUES)); 91157299f2fSHong Zhang } 91257299f2fSHong Zhang } 91357299f2fSHong Zhang } 9149566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Bmpi, MAT_FINAL_ASSEMBLY)); 9159566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Bmpi, MAT_FINAL_ASSEMBLY)); 916511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 9179566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &Bmpi)); 918c4ad791aSXuan Zhou } else { 919c4ad791aSXuan Zhou *B = Bmpi; 920c4ad791aSXuan Zhou } 9219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&isrows)); 9229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&iscols)); 923af295397SXuan Zhou PetscFunctionReturn(0); 924af295397SXuan Zhou } 925af295397SXuan Zhou 926*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) 927*d71ae5a4SJacob Faibussowitsch { 928af8000cdSHong Zhang Mat mat_elemental; 929af8000cdSHong Zhang PetscInt M = A->rmap->N, N = A->cmap->N, row, ncols; 930af8000cdSHong Zhang const PetscInt *cols; 931af8000cdSHong Zhang const PetscScalar *vals; 932af8000cdSHong Zhang 933af8000cdSHong Zhang PetscFunctionBegin; 934bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 935bdeae278SStefano Zampini mat_elemental = *newmat; 9369566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(mat_elemental)); 937bdeae278SStefano Zampini } else { 9389566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental)); 9399566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N)); 9409566063dSJacob Faibussowitsch PetscCall(MatSetType(mat_elemental, MATELEMENTAL)); 9419566063dSJacob Faibussowitsch PetscCall(MatSetUp(mat_elemental)); 942bdeae278SStefano Zampini } 943af8000cdSHong Zhang for (row = 0; row < M; row++) { 9449566063dSJacob Faibussowitsch PetscCall(MatGetRow(A, row, &ncols, &cols, &vals)); 945bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 9469566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental, 1, &row, ncols, cols, vals, ADD_VALUES)); 9479566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A, row, &ncols, &cols, &vals)); 948af8000cdSHong Zhang } 9499566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY)); 9509566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY)); 951af8000cdSHong Zhang 952511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 9539566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &mat_elemental)); 954af8000cdSHong Zhang } else { 955af8000cdSHong Zhang *newmat = mat_elemental; 956af8000cdSHong Zhang } 957af8000cdSHong Zhang PetscFunctionReturn(0); 958af8000cdSHong Zhang } 959af8000cdSHong Zhang 960*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) 961*d71ae5a4SJacob Faibussowitsch { 9625d7652ecSHong Zhang Mat mat_elemental; 9635d7652ecSHong Zhang PetscInt row, ncols, rstart = A->rmap->rstart, rend = A->rmap->rend, j; 9645d7652ecSHong Zhang const PetscInt *cols; 9655d7652ecSHong Zhang const PetscScalar *vals; 9665d7652ecSHong Zhang 9675d7652ecSHong Zhang PetscFunctionBegin; 968bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 969bdeae278SStefano Zampini mat_elemental = *newmat; 9709566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(mat_elemental)); 971bdeae278SStefano Zampini } else { 9729566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental)); 9739566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, A->rmap->N, A->cmap->N)); 9749566063dSJacob Faibussowitsch PetscCall(MatSetType(mat_elemental, MATELEMENTAL)); 9759566063dSJacob Faibussowitsch PetscCall(MatSetUp(mat_elemental)); 976bdeae278SStefano Zampini } 9775d7652ecSHong Zhang for (row = rstart; row < rend; row++) { 9789566063dSJacob Faibussowitsch PetscCall(MatGetRow(A, row, &ncols, &cols, &vals)); 9795d7652ecSHong Zhang for (j = 0; j < ncols; j++) { 980bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 9819566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental, 1, &row, 1, &cols[j], &vals[j], ADD_VALUES)); 9825d7652ecSHong Zhang } 9839566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A, row, &ncols, &cols, &vals)); 9845d7652ecSHong Zhang } 9859566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY)); 9869566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY)); 9875d7652ecSHong Zhang 988511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 9899566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &mat_elemental)); 9905d7652ecSHong Zhang } else { 9915d7652ecSHong Zhang *newmat = mat_elemental; 9925d7652ecSHong Zhang } 9935d7652ecSHong Zhang PetscFunctionReturn(0); 9945d7652ecSHong Zhang } 9955d7652ecSHong Zhang 996*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) 997*d71ae5a4SJacob Faibussowitsch { 9986214f412SHong Zhang Mat mat_elemental; 9996214f412SHong Zhang PetscInt M = A->rmap->N, N = A->cmap->N, row, ncols, j; 10006214f412SHong Zhang const PetscInt *cols; 10016214f412SHong Zhang const PetscScalar *vals; 10026214f412SHong Zhang 10036214f412SHong Zhang PetscFunctionBegin; 1004bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 1005bdeae278SStefano Zampini mat_elemental = *newmat; 10069566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(mat_elemental)); 1007bdeae278SStefano Zampini } else { 10089566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental)); 10099566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N)); 10109566063dSJacob Faibussowitsch PetscCall(MatSetType(mat_elemental, MATELEMENTAL)); 10119566063dSJacob Faibussowitsch PetscCall(MatSetUp(mat_elemental)); 1012bdeae278SStefano Zampini } 10139566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(A)); 10146214f412SHong Zhang for (row = 0; row < M; row++) { 10159566063dSJacob Faibussowitsch PetscCall(MatGetRow(A, row, &ncols, &cols, &vals)); 1016bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 10179566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental, 1, &row, ncols, cols, vals, ADD_VALUES)); 10186214f412SHong Zhang for (j = 0; j < ncols; j++) { /* lower triangular part */ 1019eb1ec7c1SStefano Zampini PetscScalar v; 10206214f412SHong Zhang if (cols[j] == row) continue; 1021b94d7dedSBarry Smith v = A->hermitian == PETSC_BOOL3_TRUE ? PetscConj(vals[j]) : vals[j]; 10229566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental, 1, &cols[j], 1, &row, &v, ADD_VALUES)); 10236214f412SHong Zhang } 10249566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A, row, &ncols, &cols, &vals)); 10256214f412SHong Zhang } 10269566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(A)); 10279566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY)); 10289566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY)); 10296214f412SHong Zhang 1030511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 10319566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &mat_elemental)); 10326214f412SHong Zhang } else { 10336214f412SHong Zhang *newmat = mat_elemental; 10346214f412SHong Zhang } 10356214f412SHong Zhang PetscFunctionReturn(0); 10366214f412SHong Zhang } 10376214f412SHong Zhang 1038*d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Elemental(Mat A, MatType newtype, MatReuse reuse, Mat *newmat) 1039*d71ae5a4SJacob Faibussowitsch { 10406214f412SHong Zhang Mat mat_elemental; 10416214f412SHong Zhang PetscInt M = A->rmap->N, N = A->cmap->N, row, ncols, j, rstart = A->rmap->rstart, rend = A->rmap->rend; 10426214f412SHong Zhang const PetscInt *cols; 10436214f412SHong Zhang const PetscScalar *vals; 10446214f412SHong Zhang 10456214f412SHong Zhang PetscFunctionBegin; 1046bdeae278SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 1047bdeae278SStefano Zampini mat_elemental = *newmat; 10489566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(mat_elemental)); 1049bdeae278SStefano Zampini } else { 10509566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental)); 10519566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat_elemental, PETSC_DECIDE, PETSC_DECIDE, M, N)); 10529566063dSJacob Faibussowitsch PetscCall(MatSetType(mat_elemental, MATELEMENTAL)); 10539566063dSJacob Faibussowitsch PetscCall(MatSetUp(mat_elemental)); 1054bdeae278SStefano Zampini } 10559566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(A)); 10566214f412SHong Zhang for (row = rstart; row < rend; row++) { 10579566063dSJacob Faibussowitsch PetscCall(MatGetRow(A, row, &ncols, &cols, &vals)); 1058bdeae278SStefano Zampini /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */ 10599566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental, 1, &row, ncols, cols, vals, ADD_VALUES)); 10606214f412SHong Zhang for (j = 0; j < ncols; j++) { /* lower triangular part */ 1061eb1ec7c1SStefano Zampini PetscScalar v; 10626214f412SHong Zhang if (cols[j] == row) continue; 1063b94d7dedSBarry Smith v = A->hermitian == PETSC_BOOL3_TRUE ? PetscConj(vals[j]) : vals[j]; 10649566063dSJacob Faibussowitsch PetscCall(MatSetValues(mat_elemental, 1, &cols[j], 1, &row, &v, ADD_VALUES)); 10656214f412SHong Zhang } 10669566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A, row, &ncols, &cols, &vals)); 10676214f412SHong Zhang } 10689566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(A)); 10699566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY)); 10709566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY)); 10716214f412SHong Zhang 1072511c6705SHong Zhang if (reuse == MAT_INPLACE_MATRIX) { 10739566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &mat_elemental)); 10746214f412SHong Zhang } else { 10756214f412SHong Zhang *newmat = mat_elemental; 10766214f412SHong Zhang } 10776214f412SHong Zhang PetscFunctionReturn(0); 10786214f412SHong Zhang } 10796214f412SHong Zhang 1080*d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_Elemental(Mat A) 1081*d71ae5a4SJacob Faibussowitsch { 1082db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental *)A->data; 10835e9f5b67SHong Zhang Mat_Elemental_Grid *commgrid; 10845e9f5b67SHong Zhang PetscBool flg; 10855e9f5b67SHong Zhang MPI_Comm icomm; 1086db31f6deSJed Brown 1087db31f6deSJed Brown PetscFunctionBegin; 1088db31f6deSJed Brown delete a->emat; 1089ea394475SSatish Balay delete a->P; 1090ea394475SSatish Balay delete a->Q; 10915e9f5b67SHong Zhang 1092e8146892SSatish Balay El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A)); 10939566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(cxxcomm.comm, &icomm, NULL)); 10949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(icomm, Petsc_Elemental_keyval, (void **)&commgrid, (int *)&flg)); 10955e9f5b67SHong Zhang if (--commgrid->grid_refct == 0) { 10965e9f5b67SHong Zhang delete commgrid->grid; 10979566063dSJacob Faibussowitsch PetscCall(PetscFree(commgrid)); 10989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Elemental_keyval)); 10995e9f5b67SHong Zhang } 11009566063dSJacob Faibussowitsch PetscCall(PetscCommDestroy(&icomm)); 11019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatGetOwnershipIS_C", NULL)); 11029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatFactorGetSolverType_C", NULL)); 11039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_elemental_mpidense_C", NULL)); 11049566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 1105db31f6deSJed Brown PetscFunctionReturn(0); 1106db31f6deSJed Brown } 1107db31f6deSJed Brown 1108*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_Elemental(Mat A) 1109*d71ae5a4SJacob Faibussowitsch { 1110db31f6deSJed Brown Mat_Elemental *a = (Mat_Elemental *)A->data; 1111f19600a0SHong Zhang MPI_Comm comm; 1112db31f6deSJed Brown PetscMPIInt rsize, csize; 1113f19600a0SHong Zhang PetscInt n; 1114db31f6deSJed Brown 1115db31f6deSJed Brown PetscFunctionBegin; 11169566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 11179566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 1118db31f6deSJed Brown 1119d8304050SJose E. Roman /* Check if local row and column sizes are equally distributed. 1120f19600a0SHong Zhang Jed: Elemental uses "element" cyclic ordering so the sizes need to match that 1121f19600a0SHong Zhang exactly. The strategy in MatElemental is for PETSc to implicitly permute to block ordering (like would be returned by 1122d8304050SJose E. Roman PetscSplitOwnership(comm,&n,&N), at which point Elemental matrices can act on PETSc vectors without redistributing the vectors. */ 11239566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 1124f19600a0SHong Zhang n = PETSC_DECIDE; 11259566063dSJacob Faibussowitsch PetscCall(PetscSplitOwnership(comm, &n, &A->rmap->N)); 11265f80ce2aSJacob 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); 1127f19600a0SHong Zhang 1128f19600a0SHong Zhang n = PETSC_DECIDE; 11299566063dSJacob Faibussowitsch PetscCall(PetscSplitOwnership(comm, &n, &A->cmap->N)); 11305f80ce2aSJacob 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); 1131f19600a0SHong Zhang 11322f613bf5SBarry Smith a->emat->Resize(A->rmap->N, A->cmap->N); 1133e8146892SSatish Balay El::Zero(*a->emat); 1134db31f6deSJed Brown 11359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(A->rmap->comm, &rsize)); 11369566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(A->cmap->comm, &csize)); 11375f80ce2aSJacob Faibussowitsch PetscCheck(csize == rsize, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_INCOMP, "Cannot use row and column communicators of different sizes"); 1138db31f6deSJed Brown a->commsize = rsize; 11399371c9d4SSatish Balay a->mr[0] = A->rmap->N % rsize; 11409371c9d4SSatish Balay if (!a->mr[0]) a->mr[0] = rsize; 11419371c9d4SSatish Balay a->mr[1] = A->cmap->N % csize; 11429371c9d4SSatish Balay if (!a->mr[1]) a->mr[1] = csize; 1143db31f6deSJed Brown a->m[0] = A->rmap->N / rsize + (a->mr[0] != rsize); 1144db31f6deSJed Brown a->m[1] = A->cmap->N / csize + (a->mr[1] != csize); 1145db31f6deSJed Brown PetscFunctionReturn(0); 1146db31f6deSJed Brown } 1147db31f6deSJed Brown 1148*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyBegin_Elemental(Mat A, MatAssemblyType type) 1149*d71ae5a4SJacob Faibussowitsch { 1150aae2c449SHong Zhang Mat_Elemental *a = (Mat_Elemental *)A->data; 1151aae2c449SHong Zhang 1152aae2c449SHong Zhang PetscFunctionBegin; 1153fbbcb730SJack Poulson /* printf("Calling ProcessQueues\n"); */ 1154fbbcb730SJack Poulson a->emat->ProcessQueues(); 1155fbbcb730SJack Poulson /* printf("Finished ProcessQueues\n"); */ 1156aae2c449SHong Zhang PetscFunctionReturn(0); 1157aae2c449SHong Zhang } 1158aae2c449SHong Zhang 1159*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyEnd_Elemental(Mat A, MatAssemblyType type) 1160*d71ae5a4SJacob Faibussowitsch { 1161aae2c449SHong Zhang PetscFunctionBegin; 1162aae2c449SHong Zhang /* Currently does nothing */ 1163aae2c449SHong Zhang PetscFunctionReturn(0); 1164aae2c449SHong Zhang } 1165aae2c449SHong Zhang 1166*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_Elemental(Mat newMat, PetscViewer viewer) 1167*d71ae5a4SJacob Faibussowitsch { 11687b30e0f1SHong Zhang Mat Adense, Ae; 11697b30e0f1SHong Zhang MPI_Comm comm; 11707b30e0f1SHong Zhang 11717b30e0f1SHong Zhang PetscFunctionBegin; 11729566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)newMat, &comm)); 11739566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &Adense)); 11749566063dSJacob Faibussowitsch PetscCall(MatSetType(Adense, MATDENSE)); 11759566063dSJacob Faibussowitsch PetscCall(MatLoad(Adense, viewer)); 11769566063dSJacob Faibussowitsch PetscCall(MatConvert(Adense, MATELEMENTAL, MAT_INITIAL_MATRIX, &Ae)); 11779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Adense)); 11789566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(newMat, &Ae)); 11797b30e0f1SHong Zhang PetscFunctionReturn(0); 11807b30e0f1SHong Zhang } 11817b30e0f1SHong Zhang 118240d92e34SHong Zhang /* -------------------------------------------------------------------*/ 11839371c9d4SSatish Balay static struct _MatOps MatOps_Values = {MatSetValues_Elemental, 118440d92e34SHong Zhang 0, 118540d92e34SHong Zhang 0, 118640d92e34SHong Zhang MatMult_Elemental, 118740d92e34SHong Zhang /* 4*/ MatMultAdd_Elemental, 11889426833fSXuan Zhou MatMultTranspose_Elemental, 1189e883f9d5SXuan Zhou MatMultTransposeAdd_Elemental, 119040d92e34SHong Zhang MatSolve_Elemental, 1191df311e6cSXuan Zhou MatSolveAdd_Elemental, 11922ef15aa2SHong Zhang 0, 11932ef15aa2SHong Zhang /*10*/ 0, 119440d92e34SHong Zhang MatLUFactor_Elemental, 119540d92e34SHong Zhang MatCholeskyFactor_Elemental, 119640d92e34SHong Zhang 0, 119740d92e34SHong Zhang MatTranspose_Elemental, 119840d92e34SHong Zhang /*15*/ MatGetInfo_Elemental, 119940d92e34SHong Zhang 0, 120061119200SXuan Zhou MatGetDiagonal_Elemental, 1201ade3cc5eSXuan Zhou MatDiagonalScale_Elemental, 120240d92e34SHong Zhang MatNorm_Elemental, 120340d92e34SHong Zhang /*20*/ MatAssemblyBegin_Elemental, 120440d92e34SHong Zhang MatAssemblyEnd_Elemental, 120532d7a744SHong Zhang MatSetOption_Elemental, 120640d92e34SHong Zhang MatZeroEntries_Elemental, 120740d92e34SHong Zhang /*24*/ 0, 120840d92e34SHong Zhang MatLUFactorSymbolic_Elemental, 120940d92e34SHong Zhang MatLUFactorNumeric_Elemental, 121040d92e34SHong Zhang MatCholeskyFactorSymbolic_Elemental, 121140d92e34SHong Zhang MatCholeskyFactorNumeric_Elemental, 121240d92e34SHong Zhang /*29*/ MatSetUp_Elemental, 121340d92e34SHong Zhang 0, 121440d92e34SHong Zhang 0, 121540d92e34SHong Zhang 0, 121640d92e34SHong Zhang 0, 1217df311e6cSXuan Zhou /*34*/ MatDuplicate_Elemental, 121840d92e34SHong Zhang 0, 121940d92e34SHong Zhang 0, 122040d92e34SHong Zhang 0, 122140d92e34SHong Zhang 0, 122240d92e34SHong Zhang /*39*/ MatAXPY_Elemental, 122340d92e34SHong Zhang 0, 122440d92e34SHong Zhang 0, 122540d92e34SHong Zhang 0, 122640d92e34SHong Zhang MatCopy_Elemental, 122740d92e34SHong Zhang /*44*/ 0, 122840d92e34SHong Zhang MatScale_Elemental, 12297d68702bSBarry Smith MatShift_Basic, 123040d92e34SHong Zhang 0, 123140d92e34SHong Zhang 0, 123240d92e34SHong Zhang /*49*/ 0, 123340d92e34SHong Zhang 0, 123440d92e34SHong Zhang 0, 123540d92e34SHong Zhang 0, 123640d92e34SHong Zhang 0, 123740d92e34SHong Zhang /*54*/ 0, 123840d92e34SHong Zhang 0, 123940d92e34SHong Zhang 0, 124040d92e34SHong Zhang 0, 124140d92e34SHong Zhang 0, 124240d92e34SHong Zhang /*59*/ 0, 124340d92e34SHong Zhang MatDestroy_Elemental, 124440d92e34SHong Zhang MatView_Elemental, 124540d92e34SHong Zhang 0, 124640d92e34SHong Zhang 0, 124740d92e34SHong Zhang /*64*/ 0, 124840d92e34SHong Zhang 0, 124940d92e34SHong Zhang 0, 125040d92e34SHong Zhang 0, 125140d92e34SHong Zhang 0, 125240d92e34SHong Zhang /*69*/ 0, 125340d92e34SHong Zhang 0, 12542ef0cf24SXuan Zhou MatConvert_Elemental_Dense, 125540d92e34SHong Zhang 0, 125640d92e34SHong Zhang 0, 125740d92e34SHong Zhang /*74*/ 0, 125840d92e34SHong Zhang 0, 125940d92e34SHong Zhang 0, 126040d92e34SHong Zhang 0, 126140d92e34SHong Zhang 0, 126240d92e34SHong Zhang /*79*/ 0, 126340d92e34SHong Zhang 0, 126440d92e34SHong Zhang 0, 126540d92e34SHong Zhang 0, 12667b30e0f1SHong Zhang MatLoad_Elemental, 126740d92e34SHong Zhang /*84*/ 0, 126840d92e34SHong Zhang 0, 126940d92e34SHong Zhang 0, 127040d92e34SHong Zhang 0, 127140d92e34SHong Zhang 0, 12724222ddf1SHong Zhang /*89*/ 0, 12734222ddf1SHong Zhang 0, 127440d92e34SHong Zhang MatMatMultNumeric_Elemental, 127540d92e34SHong Zhang 0, 127640d92e34SHong Zhang 0, 127740d92e34SHong Zhang /*94*/ 0, 12784222ddf1SHong Zhang 0, 12794222ddf1SHong Zhang 0, 1280df311e6cSXuan Zhou MatMatTransposeMultNumeric_Elemental, 128140d92e34SHong Zhang 0, 12824222ddf1SHong Zhang /*99*/ MatProductSetFromOptions_Elemental, 128340d92e34SHong Zhang 0, 128440d92e34SHong Zhang 0, 1285dfcb0403SXuan Zhou MatConjugate_Elemental, 128640d92e34SHong Zhang 0, 128740d92e34SHong Zhang /*104*/ 0, 128840d92e34SHong Zhang 0, 128940d92e34SHong Zhang 0, 129040d92e34SHong Zhang 0, 129140d92e34SHong Zhang 0, 129240d92e34SHong Zhang /*109*/ MatMatSolve_Elemental, 129340d92e34SHong Zhang 0, 129440d92e34SHong Zhang 0, 129540d92e34SHong Zhang 0, 129634fa46e1SFrancesco Ballarin MatMissingDiagonal_Elemental, 129740d92e34SHong Zhang /*114*/ 0, 129840d92e34SHong Zhang 0, 129940d92e34SHong Zhang 0, 130040d92e34SHong Zhang 0, 130140d92e34SHong Zhang 0, 130240d92e34SHong Zhang /*119*/ 0, 13034a29722dSXuan Zhou MatHermitianTranspose_Elemental, 130440d92e34SHong Zhang 0, 130540d92e34SHong Zhang 0, 130640d92e34SHong Zhang 0, 130740d92e34SHong Zhang /*124*/ 0, 130840d92e34SHong Zhang 0, 130940d92e34SHong Zhang 0, 131040d92e34SHong Zhang 0, 131140d92e34SHong Zhang 0, 131240d92e34SHong Zhang /*129*/ 0, 131340d92e34SHong Zhang 0, 131440d92e34SHong Zhang 0, 131540d92e34SHong Zhang 0, 131640d92e34SHong Zhang 0, 131740d92e34SHong Zhang /*134*/ 0, 131840d92e34SHong Zhang 0, 131940d92e34SHong Zhang 0, 132040d92e34SHong Zhang 0, 13214222ddf1SHong Zhang 0, 13224222ddf1SHong Zhang 0, 13234222ddf1SHong Zhang /*140*/ 0, 13244222ddf1SHong Zhang 0, 13254222ddf1SHong Zhang 0, 13264222ddf1SHong Zhang 0, 13274222ddf1SHong Zhang 0, 13284222ddf1SHong Zhang /*145*/ 0, 13294222ddf1SHong Zhang 0, 133099a7f59eSMark Adams 0, 133199a7f59eSMark Adams 0, 13327fb60732SBarry Smith 0, 13339371c9d4SSatish Balay /*150*/ 0}; 133440d92e34SHong Zhang 1335ed36708cSHong Zhang /*MC 1336ed36708cSHong Zhang MATELEMENTAL = "elemental" - A matrix type for dense matrices using the Elemental package 1337ed36708cSHong Zhang 1338c2b89b5dSBarry Smith Use ./configure --download-elemental to install PETSc to use Elemental 1339c2b89b5dSBarry Smith 1340ed36708cSHong Zhang Options Database Keys: 13415cc86fc1SJed Brown + -mat_type elemental - sets the matrix type to "elemental" during a call to MatSetFromOptions() 134289bba20eSBarry Smith . -pc_factor_mat_solver_type elemental - to use this direct solver with the option -pc_type lu 13435cc86fc1SJed Brown - -mat_elemental_grid_height - sets Grid Height for 2D cyclic ordering of internal matrix 1344ed36708cSHong Zhang 1345ed36708cSHong Zhang Level: beginner 1346ed36708cSHong Zhang 134789bba20eSBarry Smith Note: 134889bba20eSBarry Smith Note unlike most matrix formats, this format does not store all the matrix entries for a contiguous 134989bba20eSBarry Smith range of rows on an MPI rank. Use `MatGetOwnershipIS()` to determine what values are stored on 135089bba20eSBarry Smith the given rank. 135189bba20eSBarry Smith 135289bba20eSBarry Smith .seealso: `MATDENSE`, `MATSCALAPACK`, `MatGetOwnershipIS()` 1353ed36708cSHong Zhang M*/ 13544a29722dSXuan Zhou 1355*d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_Elemental(Mat A) 1356*d71ae5a4SJacob Faibussowitsch { 1357db31f6deSJed Brown Mat_Elemental *a; 13585682a260SJack Poulson PetscBool flg, flg1; 13595e9f5b67SHong Zhang Mat_Elemental_Grid *commgrid; 13605e9f5b67SHong Zhang MPI_Comm icomm; 13615682a260SJack Poulson PetscInt optv1; 1362db31f6deSJed Brown 1363db31f6deSJed Brown PetscFunctionBegin; 13649566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(A->ops, &MatOps_Values, sizeof(struct _MatOps))); 136540d92e34SHong Zhang A->insertmode = NOT_SET_VALUES; 1366db31f6deSJed Brown 13674dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&a)); 1368db31f6deSJed Brown A->data = (void *)a; 1369db31f6deSJed Brown 1370db31f6deSJed Brown /* Set up the elemental matrix */ 1371e8146892SSatish Balay El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A)); 13725e9f5b67SHong Zhang 13735e9f5b67SHong Zhang /* Grid needs to be shared between multiple Mats on the same communicator, implement by attribute caching on the MPI_Comm */ 13745e9f5b67SHong Zhang if (Petsc_Elemental_keyval == MPI_KEYVAL_INVALID) { 13759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Elemental_keyval, (void *)0)); 13769566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(ElementalCitation, &ElementalCite)); 13775e9f5b67SHong Zhang } 13789566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(cxxcomm.comm, &icomm, NULL)); 13799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(icomm, Petsc_Elemental_keyval, (void **)&commgrid, (int *)&flg)); 13805e9f5b67SHong Zhang if (!flg) { 13814dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&commgrid)); 13825cb544a0SHong Zhang 1383d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)A), ((PetscObject)A)->prefix, "Elemental Options", "Mat"); 1384e8146892SSatish Balay /* displayed default grid sizes (CommSize,1) are set by us arbitrarily until El::Grid() is called */ 13859566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-mat_elemental_grid_height", "Grid Height", "None", El::mpi::Size(cxxcomm), &optv1, &flg1)); 13865682a260SJack Poulson if (flg1) { 1387aed4548fSBarry 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)); 1388e8146892SSatish Balay commgrid->grid = new El::Grid(cxxcomm, optv1); /* use user-provided grid height */ 13892ef0cf24SXuan Zhou } else { 1390e8146892SSatish Balay commgrid->grid = new El::Grid(cxxcomm); /* use Elemental default grid sizes */ 1391da0640a4SHong Zhang /* printf("new commgrid->grid = %p\n",commgrid->grid); -- memory leak revealed by valgrind? */ 1392ed667823SXuan Zhou } 13935e9f5b67SHong Zhang commgrid->grid_refct = 1; 13949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_set_attr(icomm, Petsc_Elemental_keyval, (void *)commgrid)); 1395ea394475SSatish Balay 1396ea394475SSatish Balay a->pivoting = 1; 13979566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-mat_elemental_pivoting", "Pivoting", "None", a->pivoting, &a->pivoting, NULL)); 1398ea394475SSatish Balay 1399d0609cedSBarry Smith PetscOptionsEnd(); 14005e9f5b67SHong Zhang } else { 14015e9f5b67SHong Zhang commgrid->grid_refct++; 14025e9f5b67SHong Zhang } 14039566063dSJacob Faibussowitsch PetscCall(PetscCommDestroy(&icomm)); 14045e9f5b67SHong Zhang a->grid = commgrid->grid; 1405e8146892SSatish Balay a->emat = new El::DistMatrix<PetscElemScalar>(*a->grid); 140632d7a744SHong Zhang a->roworiented = PETSC_TRUE; 1407db31f6deSJed Brown 14089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatGetOwnershipIS_C", MatGetOwnershipIS_Elemental)); 14099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_elemental_mpidense_C", MatProductSetFromOptions_Elemental_MPIDense)); 14109566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATELEMENTAL)); 1411db31f6deSJed Brown PetscFunctionReturn(0); 1412db31f6deSJed Brown } 1413