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