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 19d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_Elemental(Mat A, PetscViewer viewer) 20d71ae5a4SJacob 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 60d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_Elemental(Mat A, MatInfoType flag, MatInfo *info) 61d71ae5a4SJacob 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 92d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetOption_Elemental(Mat A, MatOption op, PetscBool flg) 93d71ae5a4SJacob 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: 103d71ae5a4SJacob Faibussowitsch case MAT_HERMITIAN: 104d71ae5a4SJacob Faibussowitsch break; 105d71ae5a4SJacob Faibussowitsch case MAT_ROW_ORIENTED: 106d71ae5a4SJacob Faibussowitsch a->roworiented = flg; 107d71ae5a4SJacob Faibussowitsch break; 108d71ae5a4SJacob Faibussowitsch default: 109d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "unknown option %s", MatOptions[op]); 11032d7a744SHong Zhang } 11132d7a744SHong Zhang PetscFunctionReturn(0); 11232d7a744SHong Zhang } 11332d7a744SHong Zhang 114d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_Elemental(Mat A, PetscInt nr, const PetscInt *rows, PetscInt nc, const PetscInt *cols, const PetscScalar *vals, InsertMode imode) 115d71ae5a4SJacob 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) { 142d71ae5a4SJacob Faibussowitsch case INSERT_VALUES: 143d71ae5a4SJacob Faibussowitsch a->emat->Set(erow, ecol, (PetscElemScalar)vals[i * nc + j]); 144d71ae5a4SJacob Faibussowitsch break; 145d71ae5a4SJacob Faibussowitsch case ADD_VALUES: 146d71ae5a4SJacob Faibussowitsch a->emat->Update(erow, ecol, (PetscElemScalar)vals[i * nc + j]); 147d71ae5a4SJacob Faibussowitsch break; 148d71ae5a4SJacob Faibussowitsch default: 149d71ae5a4SJacob 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) { 189d71ae5a4SJacob Faibussowitsch case INSERT_VALUES: 190d71ae5a4SJacob Faibussowitsch a->emat->Set(erow, ecol, (PetscElemScalar)vals[i + j * nr]); 191d71ae5a4SJacob Faibussowitsch break; 192d71ae5a4SJacob Faibussowitsch case ADD_VALUES: 193d71ae5a4SJacob Faibussowitsch a->emat->Update(erow, ecol, (PetscElemScalar)vals[i + j * nr]); 194d71ae5a4SJacob Faibussowitsch break; 195d71ae5a4SJacob Faibussowitsch default: 196d71ae5a4SJacob 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 222d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_Elemental(Mat A, Vec X, Vec Y) 223d71ae5a4SJacob 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 243d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_Elemental(Mat A, Vec X, Vec Y) 244d71ae5a4SJacob 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 264d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_Elemental(Mat A, Vec X, Vec Y, Vec Z) 265d71ae5a4SJacob 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 286d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_Elemental(Mat A, Vec X, Vec Y, Vec Z) 287d71ae5a4SJacob 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 308d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_Elemental(Mat A, Mat B, Mat C) 309d71ae5a4SJacob 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*cedd07caSPierre Jolivet PetscErrorCode MatMatMultSymbolic_Elemental(Mat A, Mat B, PetscReal, Mat Ce) 324d71ae5a4SJacob 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 333d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatTransposeMultNumeric_Elemental(Mat A, Mat B, Mat C) 334d71ae5a4SJacob 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*cedd07caSPierre Jolivet static PetscErrorCode MatMatTransposeMultSymbolic_Elemental(Mat A, Mat B, PetscReal, Mat C) 349d71ae5a4SJacob 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 /* --------------------------------------- */ 358d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_Elemental_AB(Mat C) 359d71ae5a4SJacob 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 366d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_Elemental_ABt(Mat C) 367d71ae5a4SJacob 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 374d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Elemental(Mat C) 375d71ae5a4SJacob Faibussowitsch { 3764222ddf1SHong Zhang Mat_Product *product = C->product; 3774222ddf1SHong Zhang 3784222ddf1SHong Zhang PetscFunctionBegin; 3794222ddf1SHong Zhang switch (product->type) { 380d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 381d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Elemental_AB(C)); 382d71ae5a4SJacob Faibussowitsch break; 383d71ae5a4SJacob Faibussowitsch case MATPRODUCT_ABt: 384d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_Elemental_ABt(C)); 385d71ae5a4SJacob Faibussowitsch break; 386d71ae5a4SJacob Faibussowitsch default: 387d71ae5a4SJacob Faibussowitsch break; 3884222ddf1SHong Zhang } 3894222ddf1SHong Zhang PetscFunctionReturn(0); 3904222ddf1SHong Zhang } 391f6e5db1bSPierre Jolivet 392d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMatMultNumeric_Elemental_MPIDense(Mat A, Mat B, Mat C) 393d71ae5a4SJacob 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*cedd07caSPierre Jolivet PetscErrorCode MatMatMultSymbolic_Elemental_MPIDense(Mat A, Mat B, PetscReal, Mat C) 406d71ae5a4SJacob 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 415d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetFromOptions_Elemental_MPIDense_AB(Mat C) 416d71ae5a4SJacob 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 423d71ae5a4SJacob Faibussowitsch PetscErrorCode MatProductSetFromOptions_Elemental_MPIDense(Mat C) 424d71ae5a4SJacob 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 433d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_Elemental(Mat A, Vec D) 434d71ae5a4SJacob 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 460d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_Elemental(Mat X, Vec L, Vec R) 461d71ae5a4SJacob 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*cedd07caSPierre Jolivet static PetscErrorCode MatMissingDiagonal_Elemental(Mat, PetscBool *missing, PetscInt *) 484d71ae5a4SJacob Faibussowitsch { 48534fa46e1SFrancesco Ballarin PetscFunctionBegin; 48634fa46e1SFrancesco Ballarin *missing = PETSC_FALSE; 48734fa46e1SFrancesco Ballarin PetscFunctionReturn(0); 48834fa46e1SFrancesco Ballarin } 48934fa46e1SFrancesco Ballarin 490d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_Elemental(Mat X, PetscScalar a) 491d71ae5a4SJacob 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*cedd07caSPierre Jolivet static PetscErrorCode MatAXPY_Elemental(Mat Y, PetscScalar a, Mat X, MatStructure) 503d71ae5a4SJacob 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*cedd07caSPierre Jolivet static PetscErrorCode MatCopy_Elemental(Mat A, Mat B, MatStructure) 514d71ae5a4SJacob 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 524d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDuplicate_Elemental(Mat A, MatDuplicateOption op, Mat *B) 525d71ae5a4SJacob 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 545d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_Elemental(Mat A, MatReuse reuse, Mat *B) 546d71ae5a4SJacob 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 569d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConjugate_Elemental(Mat A) 570d71ae5a4SJacob 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 578d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHermitianTranspose_Elemental(Mat A, MatReuse reuse, Mat *B) 579d71ae5a4SJacob 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 600d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolve_Elemental(Mat A, Vec B, Vec X) 601d71ae5a4SJacob 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; 623d71ae5a4SJacob Faibussowitsch case MAT_FACTOR_CHOLESKY: 624d71ae5a4SJacob Faibussowitsch El::cholesky::SolveAfter(El::UPPER, El::NORMAL, *a->emat, xer); 625d71ae5a4SJacob Faibussowitsch break; 626d71ae5a4SJacob Faibussowitsch default: 627d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unfactored Matrix or Unsupported MatFactorType"); 628d71ae5a4SJacob 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 636d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSolveAdd_Elemental(Mat A, Vec B, Vec Y, Vec X) 637d71ae5a4SJacob 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 644d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatSolve_Elemental(Mat A, Mat B, Mat X) 645d71ae5a4SJacob 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; 673d71ae5a4SJacob Faibussowitsch case MAT_FACTOR_CHOLESKY: 674d71ae5a4SJacob Faibussowitsch El::cholesky::SolveAfter(El::UPPER, El::NORMAL, *a->emat, *x->emat); 675d71ae5a4SJacob Faibussowitsch break; 676d71ae5a4SJacob Faibussowitsch default: 677d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unfactored Matrix or Unsupported MatFactorType"); 678d71ae5a4SJacob 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*cedd07caSPierre Jolivet static PetscErrorCode MatLUFactor_Elemental(Mat A, IS, IS, const MatFactorInfo *) 688d71ae5a4SJacob 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 708d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatLUFactorNumeric_Elemental(Mat F, Mat A, const MatFactorInfo *info) 709d71ae5a4SJacob 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*cedd07caSPierre Jolivet static PetscErrorCode MatLUFactorSymbolic_Elemental(Mat, Mat, IS, IS, const MatFactorInfo *) 717d71ae5a4SJacob 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*cedd07caSPierre Jolivet static PetscErrorCode MatCholeskyFactor_Elemental(Mat A, IS, const MatFactorInfo *) 724d71ae5a4SJacob 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 738d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCholeskyFactorNumeric_Elemental(Mat F, Mat A, const MatFactorInfo *info) 739d71ae5a4SJacob 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*cedd07caSPierre Jolivet static PetscErrorCode MatCholeskyFactorSymbolic_Elemental(Mat, Mat, IS, const MatFactorInfo *) 747d71ae5a4SJacob 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*cedd07caSPierre Jolivet PetscErrorCode MatFactorGetSolverType_elemental_elemental(Mat, MatSolverType *type) 754d71ae5a4SJacob Faibussowitsch { 75515767789SHong Zhang PetscFunctionBegin; 75615767789SHong Zhang *type = MATSOLVERELEMENTAL; 75715767789SHong Zhang PetscFunctionReturn(0); 75815767789SHong Zhang } 75915767789SHong Zhang 760d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetFactor_elemental_elemental(Mat A, MatFactorType ftype, Mat *F) 761d71ae5a4SJacob 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 780d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Elemental(void) 781d71ae5a4SJacob 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 788d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatNorm_Elemental(Mat A, NormType type, PetscReal *nrm) 789d71ae5a4SJacob Faibussowitsch { 7901f881ff8SXuan Zhou Mat_Elemental *a = (Mat_Elemental *)A->data; 7911f881ff8SXuan Zhou 7921f881ff8SXuan Zhou PetscFunctionBegin; 7931f881ff8SXuan Zhou switch (type) { 794d71ae5a4SJacob Faibussowitsch case NORM_1: 795d71ae5a4SJacob Faibussowitsch *nrm = El::OneNorm(*a->emat); 796d71ae5a4SJacob Faibussowitsch break; 797d71ae5a4SJacob Faibussowitsch case NORM_FROBENIUS: 798d71ae5a4SJacob Faibussowitsch *nrm = El::FrobeniusNorm(*a->emat); 799d71ae5a4SJacob Faibussowitsch break; 800d71ae5a4SJacob Faibussowitsch case NORM_INFINITY: 801d71ae5a4SJacob Faibussowitsch *nrm = El::InfinityNorm(*a->emat); 802d71ae5a4SJacob Faibussowitsch break; 803d71ae5a4SJacob Faibussowitsch default: 804d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unsupported norm type"); 8051f881ff8SXuan Zhou } 8061f881ff8SXuan Zhou PetscFunctionReturn(0); 8071f881ff8SXuan Zhou } 8081f881ff8SXuan Zhou 809d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_Elemental(Mat A) 810d71ae5a4SJacob 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 818d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetOwnershipIS_Elemental(Mat A, IS *rows, IS *cols) 819d71ae5a4SJacob 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*cedd07caSPierre Jolivet static PetscErrorCode MatConvert_Elemental_Dense(Mat A, MatType, MatReuse reuse, Mat *B) 852d71ae5a4SJacob 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*cedd07caSPierre Jolivet PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat A, MatType, MatReuse reuse, Mat *newmat) 927d71ae5a4SJacob 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*cedd07caSPierre Jolivet PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_Elemental(Mat A, MatType, MatReuse reuse, Mat *newmat) 961d71ae5a4SJacob 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*cedd07caSPierre Jolivet PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat A, MatType, MatReuse reuse, Mat *newmat) 997d71ae5a4SJacob 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*cedd07caSPierre Jolivet PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Elemental(Mat A, MatType, MatReuse reuse, Mat *newmat) 1039d71ae5a4SJacob 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 1080d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_Elemental(Mat A) 1081d71ae5a4SJacob 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 1108d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetUp_Elemental(Mat A) 1109d71ae5a4SJacob 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*cedd07caSPierre Jolivet PetscErrorCode MatAssemblyBegin_Elemental(Mat A, MatAssemblyType) 1149d71ae5a4SJacob 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*cedd07caSPierre Jolivet PetscErrorCode MatAssemblyEnd_Elemental(Mat, MatAssemblyType) 1160d71ae5a4SJacob Faibussowitsch { 1161aae2c449SHong Zhang PetscFunctionBegin; 1162aae2c449SHong Zhang /* Currently does nothing */ 1163aae2c449SHong Zhang PetscFunctionReturn(0); 1164aae2c449SHong Zhang } 1165aae2c449SHong Zhang 1166d71ae5a4SJacob Faibussowitsch PetscErrorCode MatLoad_Elemental(Mat newMat, PetscViewer viewer) 1167d71ae5a4SJacob 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, 1333ed6168d8SPierre Jolivet /*150*/ 0, 1334ed6168d8SPierre Jolivet 0}; 133540d92e34SHong Zhang 1336ed36708cSHong Zhang /*MC 1337ed36708cSHong Zhang MATELEMENTAL = "elemental" - A matrix type for dense matrices using the Elemental package 1338ed36708cSHong Zhang 1339c2b89b5dSBarry Smith Use ./configure --download-elemental to install PETSc to use Elemental 1340c2b89b5dSBarry Smith 1341ed36708cSHong Zhang Options Database Keys: 13425cc86fc1SJed Brown + -mat_type elemental - sets the matrix type to "elemental" during a call to MatSetFromOptions() 134389bba20eSBarry Smith . -pc_factor_mat_solver_type elemental - to use this direct solver with the option -pc_type lu 13445cc86fc1SJed Brown - -mat_elemental_grid_height - sets Grid Height for 2D cyclic ordering of internal matrix 1345ed36708cSHong Zhang 1346ed36708cSHong Zhang Level: beginner 1347ed36708cSHong Zhang 134889bba20eSBarry Smith Note: 134989bba20eSBarry Smith Note unlike most matrix formats, this format does not store all the matrix entries for a contiguous 135089bba20eSBarry Smith range of rows on an MPI rank. Use `MatGetOwnershipIS()` to determine what values are stored on 135189bba20eSBarry Smith the given rank. 135289bba20eSBarry Smith 135389bba20eSBarry Smith .seealso: `MATDENSE`, `MATSCALAPACK`, `MatGetOwnershipIS()` 1354ed36708cSHong Zhang M*/ 13554a29722dSXuan Zhou 1356d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_Elemental(Mat A) 1357d71ae5a4SJacob Faibussowitsch { 1358db31f6deSJed Brown Mat_Elemental *a; 13595682a260SJack Poulson PetscBool flg, flg1; 13605e9f5b67SHong Zhang Mat_Elemental_Grid *commgrid; 13615e9f5b67SHong Zhang MPI_Comm icomm; 13625682a260SJack Poulson PetscInt optv1; 1363db31f6deSJed Brown 1364db31f6deSJed Brown PetscFunctionBegin; 13659566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(A->ops, &MatOps_Values, sizeof(struct _MatOps))); 136640d92e34SHong Zhang A->insertmode = NOT_SET_VALUES; 1367db31f6deSJed Brown 13684dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&a)); 1369db31f6deSJed Brown A->data = (void *)a; 1370db31f6deSJed Brown 1371db31f6deSJed Brown /* Set up the elemental matrix */ 1372e8146892SSatish Balay El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A)); 13735e9f5b67SHong Zhang 13745e9f5b67SHong Zhang /* Grid needs to be shared between multiple Mats on the same communicator, implement by attribute caching on the MPI_Comm */ 13755e9f5b67SHong Zhang if (Petsc_Elemental_keyval == MPI_KEYVAL_INVALID) { 13769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Elemental_keyval, (void *)0)); 13779566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(ElementalCitation, &ElementalCite)); 13785e9f5b67SHong Zhang } 13799566063dSJacob Faibussowitsch PetscCall(PetscCommDuplicate(cxxcomm.comm, &icomm, NULL)); 13809566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(icomm, Petsc_Elemental_keyval, (void **)&commgrid, (int *)&flg)); 13815e9f5b67SHong Zhang if (!flg) { 13824dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&commgrid)); 13835cb544a0SHong Zhang 1384d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)A), ((PetscObject)A)->prefix, "Elemental Options", "Mat"); 1385e8146892SSatish Balay /* displayed default grid sizes (CommSize,1) are set by us arbitrarily until El::Grid() is called */ 13869566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-mat_elemental_grid_height", "Grid Height", "None", El::mpi::Size(cxxcomm), &optv1, &flg1)); 13875682a260SJack Poulson if (flg1) { 1388aed4548fSBarry 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)); 1389e8146892SSatish Balay commgrid->grid = new El::Grid(cxxcomm, optv1); /* use user-provided grid height */ 13902ef0cf24SXuan Zhou } else { 1391e8146892SSatish Balay commgrid->grid = new El::Grid(cxxcomm); /* use Elemental default grid sizes */ 1392da0640a4SHong Zhang /* printf("new commgrid->grid = %p\n",commgrid->grid); -- memory leak revealed by valgrind? */ 1393ed667823SXuan Zhou } 13945e9f5b67SHong Zhang commgrid->grid_refct = 1; 13959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_set_attr(icomm, Petsc_Elemental_keyval, (void *)commgrid)); 1396ea394475SSatish Balay 1397ea394475SSatish Balay a->pivoting = 1; 13989566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-mat_elemental_pivoting", "Pivoting", "None", a->pivoting, &a->pivoting, NULL)); 1399ea394475SSatish Balay 1400d0609cedSBarry Smith PetscOptionsEnd(); 14015e9f5b67SHong Zhang } else { 14025e9f5b67SHong Zhang commgrid->grid_refct++; 14035e9f5b67SHong Zhang } 14049566063dSJacob Faibussowitsch PetscCall(PetscCommDestroy(&icomm)); 14055e9f5b67SHong Zhang a->grid = commgrid->grid; 1406e8146892SSatish Balay a->emat = new El::DistMatrix<PetscElemScalar>(*a->grid); 140732d7a744SHong Zhang a->roworiented = PETSC_TRUE; 1408db31f6deSJed Brown 14099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatGetOwnershipIS_C", MatGetOwnershipIS_Elemental)); 14109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_elemental_mpidense_C", MatProductSetFromOptions_Elemental_MPIDense)); 14119566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATELEMENTAL)); 1412db31f6deSJed Brown PetscFunctionReturn(0); 1413db31f6deSJed Brown } 1414