xref: /petsc/src/mat/impls/elemental/matelem.cxx (revision 42ba530c738d005d9eeca900c59bbf79156ea919)
11673f470SJose E. Roman #include <petsc/private/petscelemental.h>
2db31f6deSJed Brown 
35e9f5b67SHong Zhang /*
45e9f5b67SHong Zhang     The variable Petsc_Elemental_keyval is used to indicate an MPI attribute that
55e9f5b67SHong Zhang   is attached to a communicator, in this case the attribute is a Mat_Elemental_Grid
65e9f5b67SHong Zhang */
75e9f5b67SHong Zhang static PetscMPIInt Petsc_Elemental_keyval = MPI_KEYVAL_INVALID;
85e9f5b67SHong Zhang 
9db31f6deSJed Brown static PetscErrorCode MatView_Elemental(Mat A,PetscViewer viewer)
10db31f6deSJed Brown {
11db31f6deSJed Brown   PetscErrorCode ierr;
12db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
13db31f6deSJed Brown   PetscBool      iascii;
14db31f6deSJed Brown 
15db31f6deSJed Brown   PetscFunctionBegin;
16db31f6deSJed Brown   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
17db31f6deSJed Brown   if (iascii) {
18db31f6deSJed Brown     PetscViewerFormat format;
19db31f6deSJed Brown     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
20db31f6deSJed Brown     if (format == PETSC_VIEWER_ASCII_INFO) {
2179673f7bSHong Zhang       /* call elemental viewing function */
222d8adcc7SHong Zhang       ierr = PetscViewerASCIIPrintf(viewer,"Elemental run parameters:\n");CHKERRQ(ierr);
23ed667823SXuan Zhou       ierr = PetscViewerASCIIPrintf(viewer,"  allocated entries=%d\n",(*a->emat).AllocatedMemory());CHKERRQ(ierr);
24ed667823SXuan Zhou       ierr = PetscViewerASCIIPrintf(viewer,"  grid height=%d, grid width=%d\n",(*a->emat).Grid().Height(),(*a->emat).Grid().Width());CHKERRQ(ierr);
254fe7bbcaSHong Zhang       if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
2679673f7bSHong Zhang         /* call elemental viewing function */
27ce94432eSBarry Smith         ierr = PetscPrintf(PetscObjectComm((PetscObject)viewer),"test matview_elemental 2\n");CHKERRQ(ierr);
284fe7bbcaSHong Zhang       }
2979673f7bSHong Zhang 
30db31f6deSJed Brown     } else if (format == PETSC_VIEWER_DEFAULT) {
31db31f6deSJed Brown       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
32e8146892SSatish Balay       El::Print( *a->emat, "Elemental matrix (cyclic ordering)" );
33db31f6deSJed Brown       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
34834d3fecSHong Zhang       if (A->factortype == MAT_FACTOR_NONE){
3561119200SXuan Zhou         Mat Adense;
3661119200SXuan Zhou         ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense);CHKERRQ(ierr);
3761119200SXuan Zhou         ierr = MatView(Adense,viewer);CHKERRQ(ierr);
3861119200SXuan Zhou         ierr = MatDestroy(&Adense);CHKERRQ(ierr);
39834d3fecSHong Zhang       }
40ce94432eSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Format");
41d2daa67eSHong Zhang   } else {
425cb544a0SHong Zhang     /* convert to dense format and call MatView() */
4361119200SXuan Zhou     Mat Adense;
4461119200SXuan Zhou     ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense);CHKERRQ(ierr);
4561119200SXuan Zhou     ierr = MatView(Adense,viewer);CHKERRQ(ierr);
4661119200SXuan Zhou     ierr = MatDestroy(&Adense);CHKERRQ(ierr);
47d2daa67eSHong Zhang   }
48db31f6deSJed Brown   PetscFunctionReturn(0);
49db31f6deSJed Brown }
50db31f6deSJed Brown 
5115767789SHong Zhang static PetscErrorCode MatGetInfo_Elemental(Mat A,MatInfoType flag,MatInfo *info)
52180a43e4SHong Zhang {
5315767789SHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data;
5415767789SHong Zhang 
55180a43e4SHong Zhang   PetscFunctionBegin;
565cb544a0SHong Zhang   info->block_size = 1.0;
5715767789SHong Zhang 
5815767789SHong Zhang   if (flag == MAT_LOCAL) {
593966268fSBarry Smith     info->nz_allocated   = (*a->emat).AllocatedMemory(); /* locally allocated */
6015767789SHong Zhang     info->nz_used        = info->nz_allocated;
6115767789SHong Zhang   } else if (flag == MAT_GLOBAL_MAX) {
62b2566f29SBarry Smith     //ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)matin));CHKERRQ(ierr);
6315767789SHong Zhang     /* see MatGetInfo_MPIAIJ() for getting global info->nz_allocated! */
6415767789SHong Zhang     //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_MAX not written yet");
6515767789SHong Zhang   } else if (flag == MAT_GLOBAL_SUM) {
6615767789SHong Zhang     //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_SUM not written yet");
673966268fSBarry Smith     info->nz_allocated   = (*a->emat).AllocatedMemory(); /* locally allocated */
6815767789SHong Zhang     info->nz_used        = info->nz_allocated; /* assume Elemental does accurate allocation */
69b2566f29SBarry Smith     //ierr = MPIU_Allreduce(isend,irecv,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
7015767789SHong Zhang     //PetscPrintf(PETSC_COMM_SELF,"    ... [%d] locally allocated %g\n",rank,info->nz_allocated);
7115767789SHong Zhang   }
7215767789SHong Zhang 
7315767789SHong Zhang   info->nz_unneeded       = 0.0;
743966268fSBarry Smith   info->assemblies        = A->num_ass;
7515767789SHong Zhang   info->mallocs           = 0;
7615767789SHong Zhang   info->memory            = ((PetscObject)A)->mem;
7715767789SHong Zhang   info->fill_ratio_given  = 0; /* determined by Elemental */
7815767789SHong Zhang   info->fill_ratio_needed = 0;
7915767789SHong Zhang   info->factor_mallocs    = 0;
80180a43e4SHong Zhang   PetscFunctionReturn(0);
81180a43e4SHong Zhang }
82180a43e4SHong Zhang 
8332d7a744SHong Zhang PetscErrorCode MatSetOption_Elemental(Mat A,MatOption op,PetscBool flg)
8432d7a744SHong Zhang {
8532d7a744SHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data;
8632d7a744SHong Zhang 
8732d7a744SHong Zhang   PetscFunctionBegin;
8832d7a744SHong Zhang   switch (op) {
8932d7a744SHong Zhang   case MAT_NEW_NONZERO_LOCATIONS:
9032d7a744SHong Zhang   case MAT_NEW_NONZERO_LOCATION_ERR:
9132d7a744SHong Zhang   case MAT_NEW_NONZERO_ALLOCATION_ERR:
92891a0571SHong Zhang   case MAT_SYMMETRIC:
93071fcb05SBarry Smith   case MAT_SORTED_FULL:
94eb1ec7c1SStefano Zampini   case MAT_HERMITIAN:
95891a0571SHong Zhang     break;
9632d7a744SHong Zhang   case MAT_ROW_ORIENTED:
9732d7a744SHong Zhang     a->roworiented = flg;
9832d7a744SHong Zhang     break;
9932d7a744SHong Zhang   default:
10032d7a744SHong Zhang     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %s",MatOptions[op]);
10132d7a744SHong Zhang   }
10232d7a744SHong Zhang   PetscFunctionReturn(0);
10332d7a744SHong Zhang }
10432d7a744SHong Zhang 
105e6dea9dbSXuan Zhou static PetscErrorCode MatSetValues_Elemental(Mat A,PetscInt nr,const PetscInt *rows,PetscInt nc,const PetscInt *cols,const PetscScalar *vals,InsertMode imode)
106db31f6deSJed Brown {
107db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
108fbbcb730SJack Poulson   PetscInt       i,j,rrank,ridx,crank,cidx,erow,ecol,numQueues=0;
109db31f6deSJed Brown 
110db31f6deSJed Brown   PetscFunctionBegin;
111fbbcb730SJack Poulson   // TODO: Initialize matrix to all zeros?
112fbbcb730SJack Poulson 
113fbbcb730SJack Poulson   // Count the number of queues from this process
11432d7a744SHong Zhang   if (a->roworiented) {
115db31f6deSJed Brown     for (i=0; i<nr; i++) {
116db31f6deSJed Brown       if (rows[i] < 0) continue;
117db31f6deSJed Brown       P2RO(A,0,rows[i],&rrank,&ridx);
118db31f6deSJed Brown       RO2E(A,0,rrank,ridx,&erow);
119ce94432eSBarry Smith       if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect row translation");
120db31f6deSJed Brown       for (j=0; j<nc; j++) {
121db31f6deSJed Brown         if (cols[j] < 0) continue;
122db31f6deSJed Brown         P2RO(A,1,cols[j],&crank,&cidx);
123db31f6deSJed Brown         RO2E(A,1,crank,cidx,&ecol);
124ce94432eSBarry Smith         if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect col translation");
125fbbcb730SJack Poulson         if (!a->emat->IsLocal(erow,ecol) ){ /* off-proc entry */
126fbbcb730SJack Poulson           /* printf("Will later remotely update (%d,%d)\n",erow,ecol); */
127aae2c449SHong Zhang           if (imode != ADD_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported");
128fbbcb730SJack Poulson           ++numQueues;
129aae2c449SHong Zhang           continue;
130ed36708cSHong Zhang         }
131fbbcb730SJack Poulson         /* printf("Locally updating (%d,%d)\n",erow,ecol); */
132db31f6deSJed Brown         switch (imode) {
133fbbcb730SJack Poulson         case INSERT_VALUES: a->emat->Set(erow,ecol,(PetscElemScalar)vals[i*nc+j]); break;
134fbbcb730SJack Poulson         case ADD_VALUES: a->emat->Update(erow,ecol,(PetscElemScalar)vals[i*nc+j]); break;
135ce94432eSBarry Smith         default: SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode);
136db31f6deSJed Brown         }
137db31f6deSJed Brown       }
138db31f6deSJed Brown     }
139fbbcb730SJack Poulson 
140fbbcb730SJack Poulson     /* printf("numQueues=%d\n",numQueues); */
141fbbcb730SJack Poulson     a->emat->Reserve( numQueues );
142fbbcb730SJack Poulson     for (i=0; i<nr; i++) {
143fbbcb730SJack Poulson       if (rows[i] < 0) continue;
144fbbcb730SJack Poulson       P2RO(A,0,rows[i],&rrank,&ridx);
145fbbcb730SJack Poulson       RO2E(A,0,rrank,ridx,&erow);
146fbbcb730SJack Poulson       for (j=0; j<nc; j++) {
147fbbcb730SJack Poulson         if (cols[j] < 0) continue;
148fbbcb730SJack Poulson         P2RO(A,1,cols[j],&crank,&cidx);
149fbbcb730SJack Poulson         RO2E(A,1,crank,cidx,&ecol);
150fbbcb730SJack Poulson         if ( !a->emat->IsLocal(erow,ecol) ) { /*off-proc entry*/
151fbbcb730SJack Poulson           /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */
152fbbcb730SJack Poulson           a->emat->QueueUpdate( erow, ecol, vals[i*nc+j] );
153fbbcb730SJack Poulson         }
154fbbcb730SJack Poulson       }
155fbbcb730SJack Poulson     }
15632d7a744SHong Zhang   } else { /* columnoriented */
15732d7a744SHong Zhang     for (j=0; j<nc; j++) {
15832d7a744SHong Zhang       if (cols[j] < 0) continue;
15932d7a744SHong Zhang       P2RO(A,1,cols[j],&crank,&cidx);
16032d7a744SHong Zhang       RO2E(A,1,crank,cidx,&ecol);
16132d7a744SHong Zhang       if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect col translation");
16232d7a744SHong Zhang       for (i=0; i<nr; i++) {
16332d7a744SHong Zhang         if (rows[i] < 0) continue;
16432d7a744SHong Zhang         P2RO(A,0,rows[i],&rrank,&ridx);
16532d7a744SHong Zhang         RO2E(A,0,rrank,ridx,&erow);
16632d7a744SHong Zhang         if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect row translation");
16732d7a744SHong Zhang         if (!a->emat->IsLocal(erow,ecol) ){ /* off-proc entry */
16832d7a744SHong Zhang           /* printf("Will later remotely update (%d,%d)\n",erow,ecol); */
16932d7a744SHong Zhang           if (imode != ADD_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported");
17032d7a744SHong Zhang           ++numQueues;
17132d7a744SHong Zhang           continue;
17232d7a744SHong Zhang         }
17332d7a744SHong Zhang         /* printf("Locally updating (%d,%d)\n",erow,ecol); */
17432d7a744SHong Zhang         switch (imode) {
17532d7a744SHong Zhang         case INSERT_VALUES: a->emat->Set(erow,ecol,(PetscElemScalar)vals[i+j*nr]); break;
17632d7a744SHong Zhang         case ADD_VALUES: a->emat->Update(erow,ecol,(PetscElemScalar)vals[i+j*nr]); break;
17732d7a744SHong Zhang         default: SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode);
17832d7a744SHong Zhang         }
17932d7a744SHong Zhang       }
18032d7a744SHong Zhang     }
18132d7a744SHong Zhang 
18232d7a744SHong Zhang     /* printf("numQueues=%d\n",numQueues); */
18332d7a744SHong Zhang     a->emat->Reserve( numQueues );
18432d7a744SHong Zhang     for (j=0; j<nc; j++) {
18532d7a744SHong Zhang       if (cols[j] < 0) continue;
18632d7a744SHong Zhang       P2RO(A,1,cols[j],&crank,&cidx);
18732d7a744SHong Zhang       RO2E(A,1,crank,cidx,&ecol);
18832d7a744SHong Zhang 
18932d7a744SHong Zhang       for (i=0; i<nr; i++) {
19032d7a744SHong Zhang         if (rows[i] < 0) continue;
19132d7a744SHong Zhang         P2RO(A,0,rows[i],&rrank,&ridx);
19232d7a744SHong Zhang         RO2E(A,0,rrank,ridx,&erow);
19332d7a744SHong Zhang         if ( !a->emat->IsLocal(erow,ecol) ) { /*off-proc entry*/
19432d7a744SHong Zhang           /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */
19532d7a744SHong Zhang           a->emat->QueueUpdate( erow, ecol, vals[i+j*nr] );
19632d7a744SHong Zhang         }
19732d7a744SHong Zhang       }
19832d7a744SHong Zhang     }
19932d7a744SHong Zhang   }
200db31f6deSJed Brown   PetscFunctionReturn(0);
201db31f6deSJed Brown }
202db31f6deSJed Brown 
203db31f6deSJed Brown static PetscErrorCode MatMult_Elemental(Mat A,Vec X,Vec Y)
204db31f6deSJed Brown {
205db31f6deSJed Brown   Mat_Elemental         *a = (Mat_Elemental*)A->data;
206db31f6deSJed Brown   PetscErrorCode        ierr;
207e6dea9dbSXuan Zhou   const PetscElemScalar *x;
208e6dea9dbSXuan Zhou   PetscElemScalar       *y;
209df311e6cSXuan Zhou   PetscElemScalar       one = 1,zero = 0;
210db31f6deSJed Brown 
211db31f6deSJed Brown   PetscFunctionBegin;
212e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
213e6dea9dbSXuan Zhou   ierr = VecGetArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
214db31f6deSJed Brown   { /* Scoping so that constructor is called before pointer is returned */
215e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ye;
2160c18141cSBarry Smith     xe.LockedAttach(A->cmap->N,1,*a->grid,0,0,x,A->cmap->n);
2170c18141cSBarry Smith     ye.Attach(A->rmap->N,1,*a->grid,0,0,y,A->rmap->n);
218e8146892SSatish Balay     El::Gemv(El::NORMAL,one,*a->emat,xe,zero,ye);
219db31f6deSJed Brown   }
220e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
221e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
222db31f6deSJed Brown   PetscFunctionReturn(0);
223db31f6deSJed Brown }
224db31f6deSJed Brown 
2259426833fSXuan Zhou static PetscErrorCode MatMultTranspose_Elemental(Mat A,Vec X,Vec Y)
2269426833fSXuan Zhou {
2279426833fSXuan Zhou   Mat_Elemental         *a = (Mat_Elemental*)A->data;
2289426833fSXuan Zhou   PetscErrorCode        ierr;
229df311e6cSXuan Zhou   const PetscElemScalar *x;
230df311e6cSXuan Zhou   PetscElemScalar       *y;
231e6dea9dbSXuan Zhou   PetscElemScalar       one = 1,zero = 0;
2329426833fSXuan Zhou 
2339426833fSXuan Zhou   PetscFunctionBegin;
234e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
235e6dea9dbSXuan Zhou   ierr = VecGetArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
2369426833fSXuan Zhou   { /* Scoping so that constructor is called before pointer is returned */
237e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ye;
2380c18141cSBarry Smith     xe.LockedAttach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n);
2390c18141cSBarry Smith     ye.Attach(A->cmap->N,1,*a->grid,0,0,y,A->cmap->n);
240e8146892SSatish Balay     El::Gemv(El::TRANSPOSE,one,*a->emat,xe,zero,ye);
2419426833fSXuan Zhou   }
242e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
243e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
2449426833fSXuan Zhou   PetscFunctionReturn(0);
2459426833fSXuan Zhou }
2469426833fSXuan Zhou 
247db31f6deSJed Brown static PetscErrorCode MatMultAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z)
248db31f6deSJed Brown {
249db31f6deSJed Brown   Mat_Elemental         *a = (Mat_Elemental*)A->data;
250db31f6deSJed Brown   PetscErrorCode        ierr;
251df311e6cSXuan Zhou   const PetscElemScalar *x;
252df311e6cSXuan Zhou   PetscElemScalar       *z;
253e6dea9dbSXuan Zhou   PetscElemScalar       one = 1;
254db31f6deSJed Brown 
255db31f6deSJed Brown   PetscFunctionBegin;
256db31f6deSJed Brown   if (Y != Z) {ierr = VecCopy(Y,Z);CHKERRQ(ierr);}
257e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
258e6dea9dbSXuan Zhou   ierr = VecGetArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
259db31f6deSJed Brown   { /* Scoping so that constructor is called before pointer is returned */
260e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ze;
2610c18141cSBarry Smith     xe.LockedAttach(A->cmap->N,1,*a->grid,0,0,x,A->cmap->n);
2620c18141cSBarry Smith     ze.Attach(A->rmap->N,1,*a->grid,0,0,z,A->rmap->n);
263e8146892SSatish Balay     El::Gemv(El::NORMAL,one,*a->emat,xe,one,ze);
264db31f6deSJed Brown   }
265e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
266e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
267db31f6deSJed Brown   PetscFunctionReturn(0);
268db31f6deSJed Brown }
269db31f6deSJed Brown 
270e883f9d5SXuan Zhou static PetscErrorCode MatMultTransposeAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z)
271e883f9d5SXuan Zhou {
272e883f9d5SXuan Zhou   Mat_Elemental         *a = (Mat_Elemental*)A->data;
273e883f9d5SXuan Zhou   PetscErrorCode        ierr;
274df311e6cSXuan Zhou   const PetscElemScalar *x;
275df311e6cSXuan Zhou   PetscElemScalar       *z;
276e6dea9dbSXuan Zhou   PetscElemScalar       one = 1;
277e883f9d5SXuan Zhou 
278e883f9d5SXuan Zhou   PetscFunctionBegin;
279e883f9d5SXuan Zhou   if (Y != Z) {ierr = VecCopy(Y,Z);CHKERRQ(ierr);}
280e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
281e6dea9dbSXuan Zhou   ierr = VecGetArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
282e883f9d5SXuan Zhou   { /* Scoping so that constructor is called before pointer is returned */
283e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ze;
2840c18141cSBarry Smith     xe.LockedAttach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n);
2850c18141cSBarry Smith     ze.Attach(A->cmap->N,1,*a->grid,0,0,z,A->cmap->n);
286e8146892SSatish Balay     El::Gemv(El::TRANSPOSE,one,*a->emat,xe,one,ze);
287e883f9d5SXuan Zhou   }
288e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
289e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
290e883f9d5SXuan Zhou   PetscFunctionReturn(0);
291e883f9d5SXuan Zhou }
292e883f9d5SXuan Zhou 
2934222ddf1SHong Zhang PetscErrorCode MatMatMultNumeric_Elemental(Mat A,Mat B,Mat C)
294c1d1b975SXuan Zhou {
295c1d1b975SXuan Zhou   Mat_Elemental    *a = (Mat_Elemental*)A->data;
296c1d1b975SXuan Zhou   Mat_Elemental    *b = (Mat_Elemental*)B->data;
2979a9e8502SHong Zhang   Mat_Elemental    *c = (Mat_Elemental*)C->data;
298e6dea9dbSXuan Zhou   PetscElemScalar  one = 1,zero = 0;
299c1d1b975SXuan Zhou 
300c1d1b975SXuan Zhou   PetscFunctionBegin;
301aae2c449SHong Zhang   { /* Scoping so that constructor is called before pointer is returned */
302e8146892SSatish Balay     El::Gemm(El::NORMAL,El::NORMAL,one,*a->emat,*b->emat,zero,*c->emat);
303aae2c449SHong Zhang   }
3049a9e8502SHong Zhang   C->assembled = PETSC_TRUE;
3059a9e8502SHong Zhang   PetscFunctionReturn(0);
3069a9e8502SHong Zhang }
3079a9e8502SHong Zhang 
3084222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat Ce)
3099a9e8502SHong Zhang {
3109a9e8502SHong Zhang   PetscErrorCode ierr;
3119a9e8502SHong Zhang 
3129a9e8502SHong Zhang   PetscFunctionBegin;
3139a9e8502SHong Zhang   ierr = MatSetSizes(Ce,A->rmap->n,B->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
3149a9e8502SHong Zhang   ierr = MatSetType(Ce,MATELEMENTAL);CHKERRQ(ierr);
3159a9e8502SHong Zhang   ierr = MatSetUp(Ce);CHKERRQ(ierr);
3164222ddf1SHong Zhang   Ce->ops->matmultnumeric = MatMatMultNumeric_Elemental;
317c1d1b975SXuan Zhou   PetscFunctionReturn(0);
318c1d1b975SXuan Zhou }
319c1d1b975SXuan Zhou 
320df311e6cSXuan Zhou static PetscErrorCode MatMatTransposeMultNumeric_Elemental(Mat A,Mat B,Mat C)
321df311e6cSXuan Zhou {
322df311e6cSXuan Zhou   Mat_Elemental      *a = (Mat_Elemental*)A->data;
323df311e6cSXuan Zhou   Mat_Elemental      *b = (Mat_Elemental*)B->data;
324df311e6cSXuan Zhou   Mat_Elemental      *c = (Mat_Elemental*)C->data;
325e6dea9dbSXuan Zhou   PetscElemScalar    one = 1,zero = 0;
326df311e6cSXuan Zhou 
327df311e6cSXuan Zhou   PetscFunctionBegin;
328df311e6cSXuan Zhou   { /* Scoping so that constructor is called before pointer is returned */
329e8146892SSatish Balay     El::Gemm(El::NORMAL,El::TRANSPOSE,one,*a->emat,*b->emat,zero,*c->emat);
330df311e6cSXuan Zhou   }
331df311e6cSXuan Zhou   C->assembled = PETSC_TRUE;
332df311e6cSXuan Zhou   PetscFunctionReturn(0);
333df311e6cSXuan Zhou }
334df311e6cSXuan Zhou 
3354222ddf1SHong Zhang static PetscErrorCode MatMatTransposeMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat C)
336df311e6cSXuan Zhou {
337df311e6cSXuan Zhou   PetscErrorCode ierr;
338df311e6cSXuan Zhou 
339df311e6cSXuan Zhou   PetscFunctionBegin;
3404222ddf1SHong Zhang   ierr = MatSetSizes(C,A->rmap->n,B->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
3414222ddf1SHong Zhang   ierr = MatSetType(C,MATELEMENTAL);CHKERRQ(ierr);
3424222ddf1SHong Zhang   ierr = MatSetUp(C);CHKERRQ(ierr);
343df311e6cSXuan Zhou   PetscFunctionReturn(0);
344df311e6cSXuan Zhou }
345df311e6cSXuan Zhou 
3464222ddf1SHong Zhang /* --------------------------------------- */
3474222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_Elemental_AB(Mat C)
3484222ddf1SHong Zhang {
3494222ddf1SHong Zhang   PetscFunctionBegin;
3504222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_Elemental;
3514222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
3524222ddf1SHong Zhang   PetscFunctionReturn(0);
3534222ddf1SHong Zhang }
3544222ddf1SHong Zhang 
3554222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_Elemental_ABt(Mat C)
3564222ddf1SHong Zhang {
3574222ddf1SHong Zhang   PetscFunctionBegin;
3584222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_Elemental;
3594222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
3604222ddf1SHong Zhang   PetscFunctionReturn(0);
3614222ddf1SHong Zhang }
3624222ddf1SHong Zhang 
3634222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Elemental(Mat C)
3644222ddf1SHong Zhang {
3654222ddf1SHong Zhang   PetscErrorCode ierr;
3664222ddf1SHong Zhang   Mat_Product    *product = C->product;
3674222ddf1SHong Zhang 
3684222ddf1SHong Zhang   PetscFunctionBegin;
3694222ddf1SHong Zhang   switch (product->type) {
3704222ddf1SHong Zhang   case MATPRODUCT_AB:
3714222ddf1SHong Zhang     ierr = MatProductSetFromOptions_Elemental_AB(C);CHKERRQ(ierr);
3724222ddf1SHong Zhang     break;
3734222ddf1SHong Zhang   case MATPRODUCT_ABt:
3744222ddf1SHong Zhang     ierr = MatProductSetFromOptions_Elemental_ABt(C);CHKERRQ(ierr);
3754222ddf1SHong Zhang     break;
3766718818eSStefano Zampini   default:
3776718818eSStefano Zampini     break;
3784222ddf1SHong Zhang   }
3794222ddf1SHong Zhang   PetscFunctionReturn(0);
3804222ddf1SHong Zhang }
381f6e5db1bSPierre Jolivet 
382f6e5db1bSPierre Jolivet PetscErrorCode MatMatMultNumeric_Elemental_MPIDense(Mat A,Mat B,Mat C)
383f6e5db1bSPierre Jolivet {
384f6e5db1bSPierre Jolivet   Mat            Be,Ce;
385f6e5db1bSPierre Jolivet   PetscErrorCode ierr;
386f6e5db1bSPierre Jolivet 
387f6e5db1bSPierre Jolivet   PetscFunctionBegin;
388f6e5db1bSPierre Jolivet   ierr = MatConvert(B,MATELEMENTAL,MAT_INITIAL_MATRIX,&Be);CHKERRQ(ierr);
389f6e5db1bSPierre Jolivet   ierr = MatMatMult(A,Be,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&Ce);CHKERRQ(ierr);
390f6e5db1bSPierre Jolivet   ierr = MatConvert(Ce,MATMPIDENSE,MAT_REUSE_MATRIX,&C);CHKERRQ(ierr);
391f6e5db1bSPierre Jolivet   ierr = MatDestroy(&Be);CHKERRQ(ierr);
392f6e5db1bSPierre Jolivet   ierr = MatDestroy(&Ce);CHKERRQ(ierr);
393f6e5db1bSPierre Jolivet   PetscFunctionReturn(0);
394f6e5db1bSPierre Jolivet }
395f6e5db1bSPierre Jolivet 
396f6e5db1bSPierre Jolivet PetscErrorCode MatMatMultSymbolic_Elemental_MPIDense(Mat A,Mat B,PetscReal fill,Mat C)
397f6e5db1bSPierre Jolivet {
398f6e5db1bSPierre Jolivet   PetscErrorCode ierr;
399f6e5db1bSPierre Jolivet 
400f6e5db1bSPierre Jolivet   PetscFunctionBegin;
401f6e5db1bSPierre Jolivet   ierr = MatSetSizes(C,A->rmap->n,B->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
402f6e5db1bSPierre Jolivet   ierr = MatSetType(C,MATMPIDENSE);CHKERRQ(ierr);
403f6e5db1bSPierre Jolivet   ierr = MatSetUp(C);CHKERRQ(ierr);
404f6e5db1bSPierre Jolivet   C->ops->matmultnumeric = MatMatMultNumeric_Elemental_MPIDense;
405f6e5db1bSPierre Jolivet   PetscFunctionReturn(0);
406f6e5db1bSPierre Jolivet }
407f6e5db1bSPierre Jolivet 
408f6e5db1bSPierre Jolivet PetscErrorCode MatProductSetFromOptions_Elemental_MPIDense_AB(Mat C)
409f6e5db1bSPierre Jolivet {
410f6e5db1bSPierre Jolivet   PetscFunctionBegin;
411f6e5db1bSPierre Jolivet   C->ops->matmultsymbolic = MatMatMultSymbolic_Elemental_MPIDense;
412f6e5db1bSPierre Jolivet   C->ops->productsymbolic = MatProductSymbolic_AB;
413f6e5db1bSPierre Jolivet   PetscFunctionReturn(0);
414f6e5db1bSPierre Jolivet }
415f6e5db1bSPierre Jolivet 
416f6e5db1bSPierre Jolivet PetscErrorCode MatProductSetFromOptions_Elemental_MPIDense(Mat C)
417f6e5db1bSPierre Jolivet {
418f6e5db1bSPierre Jolivet   PetscErrorCode ierr;
419f6e5db1bSPierre Jolivet   Mat_Product    *product = C->product;
420f6e5db1bSPierre Jolivet 
421f6e5db1bSPierre Jolivet   PetscFunctionBegin;
422f6e5db1bSPierre Jolivet   if (product->type == MATPRODUCT_AB) {
423f6e5db1bSPierre Jolivet     ierr = MatProductSetFromOptions_Elemental_MPIDense_AB(C);CHKERRQ(ierr);
424f6e5db1bSPierre Jolivet   }
425f6e5db1bSPierre Jolivet   PetscFunctionReturn(0);
426f6e5db1bSPierre Jolivet }
4274222ddf1SHong Zhang /* --------------------------------------- */
4284222ddf1SHong Zhang 
429a9d89745SXuan Zhou static PetscErrorCode MatGetDiagonal_Elemental(Mat A,Vec D)
43061119200SXuan Zhou {
431a9d89745SXuan Zhou   PetscInt        i,nrows,ncols,nD,rrank,ridx,crank,cidx;
432a9d89745SXuan Zhou   Mat_Elemental   *a = (Mat_Elemental*)A->data;
43361119200SXuan Zhou   PetscErrorCode  ierr;
434a9d89745SXuan Zhou   PetscElemScalar v;
435ce94432eSBarry Smith   MPI_Comm        comm;
43661119200SXuan Zhou 
43761119200SXuan Zhou   PetscFunctionBegin;
438ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
439a9d89745SXuan Zhou   ierr = MatGetSize(A,&nrows,&ncols);CHKERRQ(ierr);
440a9d89745SXuan Zhou   nD = nrows>ncols ? ncols : nrows;
441a9d89745SXuan Zhou   for (i=0; i<nD; i++) {
442a9d89745SXuan Zhou     PetscInt erow,ecol;
443a9d89745SXuan Zhou     P2RO(A,0,i,&rrank,&ridx);
444a9d89745SXuan Zhou     RO2E(A,0,rrank,ridx,&erow);
445a9d89745SXuan Zhou     if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
446a9d89745SXuan Zhou     P2RO(A,1,i,&crank,&cidx);
447a9d89745SXuan Zhou     RO2E(A,1,crank,cidx,&ecol);
448a9d89745SXuan Zhou     if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
449a9d89745SXuan Zhou     v = a->emat->Get(erow,ecol);
4507c8b904fSSatish Balay     ierr = VecSetValues(D,1,&i,(PetscScalar*)&v,INSERT_VALUES);CHKERRQ(ierr);
451ade3cc5eSXuan Zhou   }
452a9d89745SXuan Zhou   ierr = VecAssemblyBegin(D);CHKERRQ(ierr);
453a9d89745SXuan Zhou   ierr = VecAssemblyEnd(D);CHKERRQ(ierr);
45461119200SXuan Zhou   PetscFunctionReturn(0);
45561119200SXuan Zhou }
45661119200SXuan Zhou 
457ade3cc5eSXuan Zhou static PetscErrorCode MatDiagonalScale_Elemental(Mat X,Vec L,Vec R)
458ade3cc5eSXuan Zhou {
459ade3cc5eSXuan Zhou   Mat_Elemental         *x = (Mat_Elemental*)X->data;
460ade3cc5eSXuan Zhou   const PetscElemScalar *d;
461ade3cc5eSXuan Zhou   PetscErrorCode        ierr;
462ade3cc5eSXuan Zhou 
463ade3cc5eSXuan Zhou   PetscFunctionBegin;
4649065cd98SJed Brown   if (R) {
465ade3cc5eSXuan Zhou     ierr = VecGetArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr);
466e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de;
4670c18141cSBarry Smith     de.LockedAttach(X->cmap->N,1,*x->grid,0,0,d,X->cmap->n);
468e8146892SSatish Balay     El::DiagonalScale(El::RIGHT,El::NORMAL,de,*x->emat);
469ade3cc5eSXuan Zhou     ierr = VecRestoreArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr);
4709065cd98SJed Brown   }
4719065cd98SJed Brown   if (L) {
472ade3cc5eSXuan Zhou     ierr = VecGetArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr);
473e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de;
4740c18141cSBarry Smith     de.LockedAttach(X->rmap->N,1,*x->grid,0,0,d,X->rmap->n);
475e8146892SSatish Balay     El::DiagonalScale(El::LEFT,El::NORMAL,de,*x->emat);
476ade3cc5eSXuan Zhou     ierr = VecRestoreArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr);
477ade3cc5eSXuan Zhou   }
478ade3cc5eSXuan Zhou   PetscFunctionReturn(0);
479ade3cc5eSXuan Zhou }
480ade3cc5eSXuan Zhou 
48134fa46e1SFrancesco Ballarin static PetscErrorCode MatMissingDiagonal_Elemental(Mat A,PetscBool *missing,PetscInt *d)
48234fa46e1SFrancesco Ballarin {
48334fa46e1SFrancesco Ballarin   PetscFunctionBegin;
48434fa46e1SFrancesco Ballarin   *missing = PETSC_FALSE;
48534fa46e1SFrancesco Ballarin   PetscFunctionReturn(0);
48634fa46e1SFrancesco Ballarin }
48734fa46e1SFrancesco Ballarin 
488e6dea9dbSXuan Zhou static PetscErrorCode MatScale_Elemental(Mat X,PetscScalar a)
48965b78793SXuan Zhou {
49065b78793SXuan Zhou   Mat_Elemental  *x = (Mat_Elemental*)X->data;
49165b78793SXuan Zhou 
49265b78793SXuan Zhou   PetscFunctionBegin;
493e8146892SSatish Balay   El::Scale((PetscElemScalar)a,*x->emat);
49465b78793SXuan Zhou   PetscFunctionReturn(0);
49565b78793SXuan Zhou }
49665b78793SXuan Zhou 
497f82baa17SHong Zhang /*
498f82baa17SHong Zhang   MatAXPY - Computes Y = a*X + Y.
499f82baa17SHong Zhang */
500e6dea9dbSXuan Zhou static PetscErrorCode MatAXPY_Elemental(Mat Y,PetscScalar a,Mat X,MatStructure str)
501e09a3074SHong Zhang {
502e09a3074SHong Zhang   Mat_Elemental  *x = (Mat_Elemental*)X->data;
503e09a3074SHong Zhang   Mat_Elemental  *y = (Mat_Elemental*)Y->data;
50468446cf8SJed Brown   PetscErrorCode ierr;
505e09a3074SHong Zhang 
506e09a3074SHong Zhang   PetscFunctionBegin;
507e8146892SSatish Balay   El::Axpy((PetscElemScalar)a,*x->emat,*y->emat);
50821f6c9c4SJed Brown   ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
509e09a3074SHong Zhang   PetscFunctionReturn(0);
510e09a3074SHong Zhang }
511e09a3074SHong Zhang 
512d6223691SXuan Zhou static PetscErrorCode MatCopy_Elemental(Mat A,Mat B,MatStructure str)
513d6223691SXuan Zhou {
514d6223691SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
515d6223691SXuan Zhou   Mat_Elemental *b=(Mat_Elemental*)B->data;
516a4ee3bb6SSatish Balay   PetscErrorCode ierr;
517d6223691SXuan Zhou 
518d6223691SXuan Zhou   PetscFunctionBegin;
519e8146892SSatish Balay   El::Copy(*a->emat,*b->emat);
520cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
521d6223691SXuan Zhou   PetscFunctionReturn(0);
522d6223691SXuan Zhou }
523d6223691SXuan Zhou 
524df311e6cSXuan Zhou static PetscErrorCode MatDuplicate_Elemental(Mat A,MatDuplicateOption op,Mat *B)
525df311e6cSXuan Zhou {
526df311e6cSXuan Zhou   Mat            Be;
527ce94432eSBarry Smith   MPI_Comm       comm;
528df311e6cSXuan Zhou   Mat_Elemental  *a=(Mat_Elemental*)A->data;
529df311e6cSXuan Zhou   PetscErrorCode ierr;
530df311e6cSXuan Zhou 
531df311e6cSXuan Zhou   PetscFunctionBegin;
532ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
533df311e6cSXuan Zhou   ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
534df311e6cSXuan Zhou   ierr = MatSetSizes(Be,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
535df311e6cSXuan Zhou   ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
536df311e6cSXuan Zhou   ierr = MatSetUp(Be);CHKERRQ(ierr);
537df311e6cSXuan Zhou   *B = Be;
538df311e6cSXuan Zhou   if (op == MAT_COPY_VALUES) {
539df311e6cSXuan Zhou     Mat_Elemental *b=(Mat_Elemental*)Be->data;
540e8146892SSatish Balay     El::Copy(*a->emat,*b->emat);
541df311e6cSXuan Zhou   }
542df311e6cSXuan Zhou   Be->assembled = PETSC_TRUE;
543df311e6cSXuan Zhou   PetscFunctionReturn(0);
544df311e6cSXuan Zhou }
545df311e6cSXuan Zhou 
546d6223691SXuan Zhou static PetscErrorCode MatTranspose_Elemental(Mat A,MatReuse reuse,Mat *B)
547d6223691SXuan Zhou {
548ec8cb81fSBarry Smith   Mat            Be = *B;
5495262d616SXuan Zhou   PetscErrorCode ierr;
550ce94432eSBarry Smith   MPI_Comm       comm;
5514fe7bbcaSHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data, *b;
552d6223691SXuan Zhou 
553d6223691SXuan Zhou   PetscFunctionBegin;
554ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
5555cb544a0SHong Zhang   /* Only out-of-place supported */
5562847e3fdSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) SETERRQ(comm,PETSC_ERR_SUP,"Only out-of-place supported");
5575262d616SXuan Zhou   if (reuse == MAT_INITIAL_MATRIX) {
5585262d616SXuan Zhou     ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
5595262d616SXuan Zhou     ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
5605262d616SXuan Zhou     ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
5615262d616SXuan Zhou     ierr = MatSetUp(Be);CHKERRQ(ierr);
5625262d616SXuan Zhou     *B = Be;
5635262d616SXuan Zhou   }
5644fe7bbcaSHong Zhang   b = (Mat_Elemental*)Be->data;
565e8146892SSatish Balay   El::Transpose(*a->emat,*b->emat);
5665262d616SXuan Zhou   Be->assembled = PETSC_TRUE;
567d6223691SXuan Zhou   PetscFunctionReturn(0);
568d6223691SXuan Zhou }
569d6223691SXuan Zhou 
570dfcb0403SXuan Zhou static PetscErrorCode MatConjugate_Elemental(Mat A)
571dfcb0403SXuan Zhou {
572dfcb0403SXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
573dfcb0403SXuan Zhou 
574dfcb0403SXuan Zhou   PetscFunctionBegin;
575e8146892SSatish Balay   El::Conjugate(*a->emat);
576dfcb0403SXuan Zhou   PetscFunctionReturn(0);
577dfcb0403SXuan Zhou }
578dfcb0403SXuan Zhou 
5794a29722dSXuan Zhou static PetscErrorCode MatHermitianTranspose_Elemental(Mat A,MatReuse reuse,Mat *B)
5804a29722dSXuan Zhou {
581ec8cb81fSBarry Smith   Mat            Be = *B;
5824a29722dSXuan Zhou   PetscErrorCode ierr;
583ce94432eSBarry Smith   MPI_Comm       comm;
5844a29722dSXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data, *b;
5854a29722dSXuan Zhou 
5864a29722dSXuan Zhou   PetscFunctionBegin;
587ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
5885cb544a0SHong Zhang   /* Only out-of-place supported */
5894a29722dSXuan Zhou   if (reuse == MAT_INITIAL_MATRIX){
5904a29722dSXuan Zhou     ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
5914a29722dSXuan Zhou     ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
5924a29722dSXuan Zhou     ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
5934a29722dSXuan Zhou     ierr = MatSetUp(Be);CHKERRQ(ierr);
5944a29722dSXuan Zhou     *B = Be;
5954a29722dSXuan Zhou   }
5964a29722dSXuan Zhou   b = (Mat_Elemental*)Be->data;
597e8146892SSatish Balay   El::Adjoint(*a->emat,*b->emat);
5984a29722dSXuan Zhou   Be->assembled = PETSC_TRUE;
5994a29722dSXuan Zhou   PetscFunctionReturn(0);
6004a29722dSXuan Zhou }
6014a29722dSXuan Zhou 
6021f881ff8SXuan Zhou static PetscErrorCode MatSolve_Elemental(Mat A,Vec B,Vec X)
6031f881ff8SXuan Zhou {
6041f881ff8SXuan Zhou   Mat_Elemental     *a = (Mat_Elemental*)A->data;
6051f881ff8SXuan Zhou   PetscErrorCode    ierr;
606df311e6cSXuan Zhou   PetscElemScalar   *x;
607ea394475SSatish Balay   PetscInt          pivoting = a->pivoting;
6081f881ff8SXuan Zhou 
6091f881ff8SXuan Zhou   PetscFunctionBegin;
61045cf121fSXuan Zhou   ierr = VecCopy(B,X);CHKERRQ(ierr);
611e6dea9dbSXuan Zhou   ierr = VecGetArray(X,(PetscScalar **)&x);CHKERRQ(ierr);
612ea394475SSatish Balay 
613e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe;
6140c18141cSBarry Smith   xe.Attach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n);
615e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::MC,El::MR> xer(xe);
616fc54b460SXuan Zhou   switch (A->factortype) {
617fc54b460SXuan Zhou   case MAT_FACTOR_LU:
618ea394475SSatish Balay     if (pivoting == 0) {
619e8146892SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,xer);
620ea394475SSatish Balay     } else if (pivoting == 1) {
621ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,xer);
622ea394475SSatish Balay     } else { /* pivoting == 2 */
623ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,xer);
6241f881ff8SXuan Zhou     }
625fc54b460SXuan Zhou     break;
626fc54b460SXuan Zhou   case MAT_FACTOR_CHOLESKY:
627e8146892SSatish Balay     El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,xer);
628fc54b460SXuan Zhou     break;
629fc54b460SXuan Zhou   default:
6304fe7bbcaSHong Zhang     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType");
631fc54b460SXuan Zhou     break;
6321f881ff8SXuan Zhou   }
633ea394475SSatish Balay   El::Copy(xer,xe);
634ea394475SSatish Balay 
635e6dea9dbSXuan Zhou   ierr = VecRestoreArray(X,(PetscScalar **)&x);CHKERRQ(ierr);
6361f881ff8SXuan Zhou   PetscFunctionReturn(0);
6371f881ff8SXuan Zhou }
6381f881ff8SXuan Zhou 
639df311e6cSXuan Zhou static PetscErrorCode MatSolveAdd_Elemental(Mat A,Vec B,Vec Y,Vec X)
640df311e6cSXuan Zhou {
641df311e6cSXuan Zhou   PetscErrorCode    ierr;
642df311e6cSXuan Zhou 
643df311e6cSXuan Zhou   PetscFunctionBegin;
644df311e6cSXuan Zhou   ierr = MatSolve_Elemental(A,B,X);CHKERRQ(ierr);
6453d7f40dbSXuan Zhou   ierr = VecAXPY(X,1,Y);CHKERRQ(ierr);
646df311e6cSXuan Zhou   PetscFunctionReturn(0);
647df311e6cSXuan Zhou }
648df311e6cSXuan Zhou 
649ae844d54SHong Zhang static PetscErrorCode MatMatSolve_Elemental(Mat A,Mat B,Mat X)
650ae844d54SHong Zhang {
6511f0e42cfSHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data;
652*42ba530cSPierre Jolivet   Mat_Elemental  *x;
653*42ba530cSPierre Jolivet   Mat            C;
654ea394475SSatish Balay   PetscInt       pivoting = a->pivoting;
655*42ba530cSPierre Jolivet   PetscBool      flg;
656*42ba530cSPierre Jolivet   MatType        type;
657*42ba530cSPierre Jolivet   PetscErrorCode ierr;
6581f0e42cfSHong Zhang 
659ae844d54SHong Zhang   PetscFunctionBegin;
660*42ba530cSPierre Jolivet   ierr = MatGetType(X,&type);CHKERRQ(ierr);
661*42ba530cSPierre Jolivet   ierr = PetscStrcmp(type,MATELEMENTAL,&flg);CHKERRQ(ierr);
662*42ba530cSPierre Jolivet   if (!flg) {
663*42ba530cSPierre Jolivet     ierr = MatConvert(B,MATELEMENTAL,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr);
664*42ba530cSPierre Jolivet     x = (Mat_Elemental*)C->data;
665*42ba530cSPierre Jolivet   } else {
666*42ba530cSPierre Jolivet     x = (Mat_Elemental*)X->data;
667*42ba530cSPierre Jolivet     El::Copy(*((Mat_Elemental*)B->data)->emat,*x->emat);
668*42ba530cSPierre Jolivet   }
669fc54b460SXuan Zhou   switch (A->factortype) {
670fc54b460SXuan Zhou   case MAT_FACTOR_LU:
671ea394475SSatish Balay     if (pivoting == 0) {
672e8146892SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*x->emat);
673ea394475SSatish Balay     } else if (pivoting == 1) {
674ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*x->emat);
675ea394475SSatish Balay     } else {
676ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,*x->emat);
677d6223691SXuan Zhou     }
678fc54b460SXuan Zhou     break;
679fc54b460SXuan Zhou   case MAT_FACTOR_CHOLESKY:
680e8146892SSatish Balay     El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,*x->emat);
681fc54b460SXuan Zhou     break;
682fc54b460SXuan Zhou   default:
6834fe7bbcaSHong Zhang     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType");
684fc54b460SXuan Zhou     break;
685fc54b460SXuan Zhou   }
686*42ba530cSPierre Jolivet   if (!flg) {
687*42ba530cSPierre Jolivet     ierr = MatConvert(C,type,MAT_REUSE_MATRIX,&X);CHKERRQ(ierr);
688*42ba530cSPierre Jolivet     ierr = MatDestroy(&C);CHKERRQ(ierr);
689*42ba530cSPierre Jolivet   }
690ae844d54SHong Zhang   PetscFunctionReturn(0);
691ae844d54SHong Zhang }
692ae844d54SHong Zhang 
693ae844d54SHong Zhang static PetscErrorCode MatLUFactor_Elemental(Mat A,IS row,IS col,const MatFactorInfo *info)
694ae844d54SHong Zhang {
6957c920d81SXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
696124af5d2SSatish Balay   PetscErrorCode ierr;
697ea394475SSatish Balay   PetscInt       pivoting = a->pivoting;
6987c920d81SXuan Zhou 
699ae844d54SHong Zhang   PetscFunctionBegin;
700ea394475SSatish Balay   if (pivoting == 0) {
701e8146892SSatish Balay     El::LU(*a->emat);
702ea394475SSatish Balay   } else if (pivoting == 1) {
703ea394475SSatish Balay     El::LU(*a->emat,*a->P);
704ea394475SSatish Balay   } else {
705ea394475SSatish Balay     El::LU(*a->emat,*a->P,*a->Q);
706d6223691SXuan Zhou   }
7071293973dSHong Zhang   A->factortype = MAT_FACTOR_LU;
708834d3fecSHong Zhang   A->assembled  = PETSC_TRUE;
709f6224b95SHong Zhang 
710f6224b95SHong Zhang   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
711f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype);CHKERRQ(ierr);
712ae844d54SHong Zhang   PetscFunctionReturn(0);
713ae844d54SHong Zhang }
714ae844d54SHong Zhang 
715d7c3f9d8SHong Zhang static PetscErrorCode  MatLUFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info)
716d7c3f9d8SHong Zhang {
717d7c3f9d8SHong Zhang   PetscErrorCode ierr;
718d7c3f9d8SHong Zhang 
719d7c3f9d8SHong Zhang   PetscFunctionBegin;
720d7c3f9d8SHong Zhang   ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
721d7c3f9d8SHong Zhang   ierr = MatLUFactor_Elemental(F,0,0,info);CHKERRQ(ierr);
722d7c3f9d8SHong Zhang   PetscFunctionReturn(0);
723d7c3f9d8SHong Zhang }
724d7c3f9d8SHong Zhang 
725d7c3f9d8SHong Zhang static PetscErrorCode  MatLUFactorSymbolic_Elemental(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
726d7c3f9d8SHong Zhang {
727d7c3f9d8SHong Zhang   PetscFunctionBegin;
728d8304050SJose E. Roman   /* F is created and allocated by MatGetFactor_elemental_petsc(), skip this routine. */
729d7c3f9d8SHong Zhang   PetscFunctionReturn(0);
730d7c3f9d8SHong Zhang }
731d7c3f9d8SHong Zhang 
73245cf121fSXuan Zhou static PetscErrorCode MatCholeskyFactor_Elemental(Mat A,IS perm,const MatFactorInfo *info)
73345cf121fSXuan Zhou {
73445cf121fSXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
735e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::MC,El::STAR> d;
736124af5d2SSatish Balay   PetscErrorCode ierr;
73745cf121fSXuan Zhou 
73845cf121fSXuan Zhou   PetscFunctionBegin;
739e8146892SSatish Balay   El::Cholesky(El::UPPER,*a->emat);
740fc54b460SXuan Zhou   A->factortype = MAT_FACTOR_CHOLESKY;
741834d3fecSHong Zhang   A->assembled  = PETSC_TRUE;
742f6224b95SHong Zhang 
743f6224b95SHong Zhang   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
744f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype);CHKERRQ(ierr);
74545cf121fSXuan Zhou   PetscFunctionReturn(0);
74645cf121fSXuan Zhou }
74745cf121fSXuan Zhou 
74879673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info)
74979673f7bSHong Zhang {
750cb76c1d8SXuan Zhou   PetscErrorCode ierr;
751cb76c1d8SXuan Zhou 
752cb76c1d8SXuan Zhou   PetscFunctionBegin;
753cb76c1d8SXuan Zhou   ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
754cb76c1d8SXuan Zhou   ierr = MatCholeskyFactor_Elemental(F,0,info);CHKERRQ(ierr);
755cb76c1d8SXuan Zhou   PetscFunctionReturn(0);
75679673f7bSHong Zhang }
757cb76c1d8SXuan Zhou 
75879673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorSymbolic_Elemental(Mat F,Mat A,IS perm,const MatFactorInfo *info)
75979673f7bSHong Zhang {
76079673f7bSHong Zhang   PetscFunctionBegin;
761d8304050SJose E. Roman   /* F is created and allocated by MatGetFactor_elemental_petsc(), skip this routine. */
76279673f7bSHong Zhang   PetscFunctionReturn(0);
76379673f7bSHong Zhang }
76479673f7bSHong Zhang 
765ea799195SBarry Smith PetscErrorCode MatFactorGetSolverType_elemental_elemental(Mat A,MatSolverType *type)
76615767789SHong Zhang {
76715767789SHong Zhang   PetscFunctionBegin;
76815767789SHong Zhang   *type = MATSOLVERELEMENTAL;
76915767789SHong Zhang   PetscFunctionReturn(0);
77015767789SHong Zhang }
77115767789SHong Zhang 
77215767789SHong Zhang static PetscErrorCode MatGetFactor_elemental_elemental(Mat A,MatFactorType ftype,Mat *F)
7731293973dSHong Zhang {
7741293973dSHong Zhang   Mat            B;
7751293973dSHong Zhang   PetscErrorCode ierr;
7761293973dSHong Zhang 
7771293973dSHong Zhang   PetscFunctionBegin;
7781293973dSHong Zhang   /* Create the factorization matrix */
779ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
7801293973dSHong Zhang   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
7811293973dSHong Zhang   ierr = MatSetType(B,MATELEMENTAL);CHKERRQ(ierr);
7821293973dSHong Zhang   ierr = MatSetUp(B);CHKERRQ(ierr);
7831293973dSHong Zhang   B->factortype = ftype;
78400c67f3bSHong Zhang   ierr = PetscFree(B->solvertype);CHKERRQ(ierr);
78500c67f3bSHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&B->solvertype);CHKERRQ(ierr);
78600c67f3bSHong Zhang 
7873ca39a21SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_elemental_elemental);CHKERRQ(ierr);
7881293973dSHong Zhang   *F            = B;
7891293973dSHong Zhang   PetscFunctionReturn(0);
7901293973dSHong Zhang }
7911293973dSHong Zhang 
7923ca39a21SBarry Smith PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Elemental(void)
79342c9c57cSBarry Smith {
79418713533SBarry Smith   PetscErrorCode ierr;
79518713533SBarry Smith 
79642c9c57cSBarry Smith   PetscFunctionBegin;
7973ca39a21SBarry Smith   ierr = MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL,        MAT_FACTOR_LU,MatGetFactor_elemental_elemental);CHKERRQ(ierr);
7983ca39a21SBarry Smith   ierr = MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL,        MAT_FACTOR_CHOLESKY,MatGetFactor_elemental_elemental);CHKERRQ(ierr);
79942c9c57cSBarry Smith   PetscFunctionReturn(0);
80042c9c57cSBarry Smith }
80142c9c57cSBarry Smith 
8021f881ff8SXuan Zhou static PetscErrorCode MatNorm_Elemental(Mat A,NormType type,PetscReal *nrm)
8031f881ff8SXuan Zhou {
8041f881ff8SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
8051f881ff8SXuan Zhou 
8061f881ff8SXuan Zhou   PetscFunctionBegin;
8071f881ff8SXuan Zhou   switch (type){
8081f881ff8SXuan Zhou   case NORM_1:
809e8146892SSatish Balay     *nrm = El::OneNorm(*a->emat);
8101f881ff8SXuan Zhou     break;
8111f881ff8SXuan Zhou   case NORM_FROBENIUS:
812e8146892SSatish Balay     *nrm = El::FrobeniusNorm(*a->emat);
8131f881ff8SXuan Zhou     break;
8141f881ff8SXuan Zhou   case NORM_INFINITY:
815e8146892SSatish Balay     *nrm = El::InfinityNorm(*a->emat);
8161f881ff8SXuan Zhou     break;
8171f881ff8SXuan Zhou   default:
818d8304050SJose E. Roman     SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unsupported norm type");
8191f881ff8SXuan Zhou   }
8201f881ff8SXuan Zhou   PetscFunctionReturn(0);
8211f881ff8SXuan Zhou }
8221f881ff8SXuan Zhou 
8235262d616SXuan Zhou static PetscErrorCode MatZeroEntries_Elemental(Mat A)
8245262d616SXuan Zhou {
8255262d616SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
8265262d616SXuan Zhou 
8275262d616SXuan Zhou   PetscFunctionBegin;
828e8146892SSatish Balay   El::Zero(*a->emat);
8295262d616SXuan Zhou   PetscFunctionReturn(0);
8305262d616SXuan Zhou }
8315262d616SXuan Zhou 
832db31f6deSJed Brown static PetscErrorCode MatGetOwnershipIS_Elemental(Mat A,IS *rows,IS *cols)
833db31f6deSJed Brown {
834db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
835db31f6deSJed Brown   PetscErrorCode ierr;
836db31f6deSJed Brown   PetscInt       i,m,shift,stride,*idx;
837db31f6deSJed Brown 
838db31f6deSJed Brown   PetscFunctionBegin;
839db31f6deSJed Brown   if (rows) {
840db31f6deSJed Brown     m = a->emat->LocalHeight();
841db31f6deSJed Brown     shift = a->emat->ColShift();
842db31f6deSJed Brown     stride = a->emat->ColStride();
843785e854fSJed Brown     ierr = PetscMalloc1(m,&idx);CHKERRQ(ierr);
844db31f6deSJed Brown     for (i=0; i<m; i++) {
845db31f6deSJed Brown       PetscInt rank,offset;
846db31f6deSJed Brown       E2RO(A,0,shift+i*stride,&rank,&offset);
847db31f6deSJed Brown       RO2P(A,0,rank,offset,&idx[i]);
848db31f6deSJed Brown     }
849db31f6deSJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,rows);CHKERRQ(ierr);
850db31f6deSJed Brown   }
851db31f6deSJed Brown   if (cols) {
852db31f6deSJed Brown     m = a->emat->LocalWidth();
853db31f6deSJed Brown     shift = a->emat->RowShift();
854db31f6deSJed Brown     stride = a->emat->RowStride();
855785e854fSJed Brown     ierr = PetscMalloc1(m,&idx);CHKERRQ(ierr);
856db31f6deSJed Brown     for (i=0; i<m; i++) {
857db31f6deSJed Brown       PetscInt rank,offset;
858db31f6deSJed Brown       E2RO(A,1,shift+i*stride,&rank,&offset);
859db31f6deSJed Brown       RO2P(A,1,rank,offset,&idx[i]);
860db31f6deSJed Brown     }
861db31f6deSJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,cols);CHKERRQ(ierr);
862db31f6deSJed Brown   }
863db31f6deSJed Brown   PetscFunctionReturn(0);
864db31f6deSJed Brown }
865db31f6deSJed Brown 
86619fd82e9SBarry Smith static PetscErrorCode MatConvert_Elemental_Dense(Mat A,MatType newtype,MatReuse reuse,Mat *B)
867af295397SXuan Zhou {
8682ef0cf24SXuan Zhou   Mat                Bmpi;
869af295397SXuan Zhou   Mat_Elemental      *a = (Mat_Elemental*)A->data;
870ce94432eSBarry Smith   MPI_Comm           comm;
8712ef0cf24SXuan Zhou   PetscErrorCode     ierr;
872fa9e26c8SHong Zhang   IS                 isrows,iscols;
873fa9e26c8SHong Zhang   PetscInt           rrank,ridx,crank,cidx,nrows,ncols,i,j,erow,ecol,elrow,elcol;
874fa9e26c8SHong Zhang   const PetscInt     *rows,*cols;
875df311e6cSXuan Zhou   PetscElemScalar    v;
876fa9e26c8SHong Zhang   const El::Grid     &grid = a->emat->Grid();
877af295397SXuan Zhou 
878af295397SXuan Zhou   PetscFunctionBegin;
879ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
880a000e53bSHong Zhang 
881de0a22f0SHong Zhang   if (reuse == MAT_REUSE_MATRIX) {
882de0a22f0SHong Zhang     Bmpi = *B;
883de0a22f0SHong Zhang   } else {
884af295397SXuan Zhou     ierr = MatCreate(comm,&Bmpi);CHKERRQ(ierr);
885af295397SXuan Zhou     ierr = MatSetSizes(Bmpi,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
8862ef0cf24SXuan Zhou     ierr = MatSetType(Bmpi,MATDENSE);CHKERRQ(ierr);
887af295397SXuan Zhou     ierr = MatSetUp(Bmpi);CHKERRQ(ierr);
888de0a22f0SHong Zhang   }
889fa9e26c8SHong Zhang 
890fa9e26c8SHong Zhang   /* Get local entries of A */
891fa9e26c8SHong Zhang   ierr = MatGetOwnershipIS(A,&isrows,&iscols);CHKERRQ(ierr);
892fa9e26c8SHong Zhang   ierr = ISGetLocalSize(isrows,&nrows);CHKERRQ(ierr);
893fa9e26c8SHong Zhang   ierr = ISGetIndices(isrows,&rows);CHKERRQ(ierr);
894fa9e26c8SHong Zhang   ierr = ISGetLocalSize(iscols,&ncols);CHKERRQ(ierr);
895fa9e26c8SHong Zhang   ierr = ISGetIndices(iscols,&cols);CHKERRQ(ierr);
896fa9e26c8SHong Zhang 
89757299f2fSHong Zhang   if (a->roworiented) {
8982ef0cf24SXuan Zhou     for (i=0; i<nrows; i++) {
899fa9e26c8SHong Zhang       P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */
9002ef0cf24SXuan Zhou       RO2E(A,0,rrank,ridx,&erow);
9012ef0cf24SXuan Zhou       if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
9022ef0cf24SXuan Zhou       for (j=0; j<ncols; j++) {
903fa9e26c8SHong Zhang         P2RO(A,1,cols[j],&crank,&cidx);
9042ef0cf24SXuan Zhou         RO2E(A,1,crank,cidx,&ecol);
9052ef0cf24SXuan Zhou         if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
906fa9e26c8SHong Zhang 
907fa9e26c8SHong Zhang         elrow = erow / grid.MCSize(); /* Elemental local row index */
908fa9e26c8SHong Zhang         elcol = ecol / grid.MRSize(); /* Elemental local column index */
909fa9e26c8SHong Zhang         v = a->emat->GetLocal(elrow,elcol);
910fa9e26c8SHong Zhang         ierr = MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr);
9112ef0cf24SXuan Zhou       }
9122ef0cf24SXuan Zhou     }
91357299f2fSHong Zhang   } else { /* column-oriented */
91457299f2fSHong Zhang     for (j=0; j<ncols; j++) {
91557299f2fSHong Zhang       P2RO(A,1,cols[j],&crank,&cidx);
91657299f2fSHong Zhang       RO2E(A,1,crank,cidx,&ecol);
91757299f2fSHong Zhang       if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
91857299f2fSHong Zhang       for (i=0; i<nrows; i++) {
91957299f2fSHong Zhang         P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */
92057299f2fSHong Zhang         RO2E(A,0,rrank,ridx,&erow);
92157299f2fSHong Zhang         if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
92257299f2fSHong Zhang 
92357299f2fSHong Zhang         elrow = erow / grid.MCSize(); /* Elemental local row index */
92457299f2fSHong Zhang         elcol = ecol / grid.MRSize(); /* Elemental local column index */
92557299f2fSHong Zhang         v = a->emat->GetLocal(elrow,elcol);
92657299f2fSHong Zhang         ierr = MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr);
92757299f2fSHong Zhang       }
92857299f2fSHong Zhang     }
92957299f2fSHong Zhang   }
930af295397SXuan Zhou   ierr = MatAssemblyBegin(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
931af295397SXuan Zhou   ierr = MatAssemblyEnd(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
932511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
93328be2f97SBarry Smith     ierr = MatHeaderReplace(A,&Bmpi);CHKERRQ(ierr);
934c4ad791aSXuan Zhou   } else {
935c4ad791aSXuan Zhou     *B = Bmpi;
936c4ad791aSXuan Zhou   }
937fa9e26c8SHong Zhang   ierr = ISDestroy(&isrows);CHKERRQ(ierr);
938fa9e26c8SHong Zhang   ierr = ISDestroy(&iscols);CHKERRQ(ierr);
939af295397SXuan Zhou   PetscFunctionReturn(0);
940af295397SXuan Zhou }
941af295397SXuan Zhou 
942cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
943af8000cdSHong Zhang {
944af8000cdSHong Zhang   Mat               mat_elemental;
945af8000cdSHong Zhang   PetscErrorCode    ierr;
946af8000cdSHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols;
947af8000cdSHong Zhang   const PetscInt    *cols;
948af8000cdSHong Zhang   const PetscScalar *vals;
949af8000cdSHong Zhang 
950af8000cdSHong Zhang   PetscFunctionBegin;
951bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
952bdeae278SStefano Zampini     mat_elemental = *newmat;
953bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
954bdeae278SStefano Zampini   } else {
955af8000cdSHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
956af8000cdSHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
957af8000cdSHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
958af8000cdSHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
959bdeae278SStefano Zampini   }
960af8000cdSHong Zhang   for (row=0; row<M; row++) {
961af8000cdSHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
962bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
963af8000cdSHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
964af8000cdSHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
965af8000cdSHong Zhang   }
966af8000cdSHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
967af8000cdSHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
968af8000cdSHong Zhang 
969511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
97028be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
971af8000cdSHong Zhang   } else {
972af8000cdSHong Zhang     *newmat = mat_elemental;
973af8000cdSHong Zhang   }
974af8000cdSHong Zhang   PetscFunctionReturn(0);
975af8000cdSHong Zhang }
976af8000cdSHong Zhang 
977cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
9785d7652ecSHong Zhang {
9795d7652ecSHong Zhang   Mat               mat_elemental;
9805d7652ecSHong Zhang   PetscErrorCode    ierr;
9815d7652ecSHong Zhang   PetscInt          row,ncols,rstart=A->rmap->rstart,rend=A->rmap->rend,j;
9825d7652ecSHong Zhang   const PetscInt    *cols;
9835d7652ecSHong Zhang   const PetscScalar *vals;
9845d7652ecSHong Zhang 
9855d7652ecSHong Zhang   PetscFunctionBegin;
986bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
987bdeae278SStefano Zampini     mat_elemental = *newmat;
988bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
989bdeae278SStefano Zampini   } else {
9905d7652ecSHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
9915d7652ecSHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
9925d7652ecSHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
9935d7652ecSHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
994bdeae278SStefano Zampini   }
9955d7652ecSHong Zhang   for (row=rstart; row<rend; row++) {
9965d7652ecSHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
9975d7652ecSHong Zhang     for (j=0; j<ncols; j++) {
998bdeae278SStefano Zampini       /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
9995d7652ecSHong Zhang       ierr = MatSetValues(mat_elemental,1,&row,1,&cols[j],&vals[j],ADD_VALUES);CHKERRQ(ierr);
10005d7652ecSHong Zhang     }
10015d7652ecSHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
10025d7652ecSHong Zhang   }
10035d7652ecSHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10045d7652ecSHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10055d7652ecSHong Zhang 
1006511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
100728be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
10085d7652ecSHong Zhang   } else {
10095d7652ecSHong Zhang     *newmat = mat_elemental;
10105d7652ecSHong Zhang   }
10115d7652ecSHong Zhang   PetscFunctionReturn(0);
10125d7652ecSHong Zhang }
10135d7652ecSHong Zhang 
1014cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
10156214f412SHong Zhang {
10166214f412SHong Zhang   Mat               mat_elemental;
10176214f412SHong Zhang   PetscErrorCode    ierr;
10186214f412SHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols,j;
10196214f412SHong Zhang   const PetscInt    *cols;
10206214f412SHong Zhang   const PetscScalar *vals;
10216214f412SHong Zhang 
10226214f412SHong Zhang   PetscFunctionBegin;
1023bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1024bdeae278SStefano Zampini     mat_elemental = *newmat;
1025bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
1026bdeae278SStefano Zampini   } else {
10276214f412SHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
10286214f412SHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
10296214f412SHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
10306214f412SHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
1031bdeae278SStefano Zampini   }
10326214f412SHong Zhang   ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr);
10336214f412SHong Zhang   for (row=0; row<M; row++) {
10346214f412SHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
1035bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
10366214f412SHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
10376214f412SHong Zhang     for (j=0; j<ncols; j++) { /* lower triangular part */
1038eb1ec7c1SStefano Zampini       PetscScalar v;
10396214f412SHong Zhang       if (cols[j] == row) continue;
1040eb1ec7c1SStefano Zampini       v    = A->hermitian ? PetscConj(vals[j]) : vals[j];
1041eb1ec7c1SStefano Zampini       ierr = MatSetValues(mat_elemental,1,&cols[j],1,&row,&v,ADD_VALUES);CHKERRQ(ierr);
10426214f412SHong Zhang     }
10436214f412SHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
10446214f412SHong Zhang   }
10456214f412SHong Zhang   ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr);
10466214f412SHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10476214f412SHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10486214f412SHong Zhang 
1049511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
105028be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
10516214f412SHong Zhang   } else {
10526214f412SHong Zhang     *newmat = mat_elemental;
10536214f412SHong Zhang   }
10546214f412SHong Zhang   PetscFunctionReturn(0);
10556214f412SHong Zhang }
10566214f412SHong Zhang 
1057cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
10586214f412SHong Zhang {
10596214f412SHong Zhang   Mat               mat_elemental;
10606214f412SHong Zhang   PetscErrorCode    ierr;
10616214f412SHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols,j,rstart=A->rmap->rstart,rend=A->rmap->rend;
10626214f412SHong Zhang   const PetscInt    *cols;
10636214f412SHong Zhang   const PetscScalar *vals;
10646214f412SHong Zhang 
10656214f412SHong Zhang   PetscFunctionBegin;
1066bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1067bdeae278SStefano Zampini     mat_elemental = *newmat;
1068bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
1069bdeae278SStefano Zampini   } else {
10706214f412SHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
10716214f412SHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
10726214f412SHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
10736214f412SHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
1074bdeae278SStefano Zampini   }
10756214f412SHong Zhang   ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr);
10766214f412SHong Zhang   for (row=rstart; row<rend; row++) {
10776214f412SHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
1078bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
10796214f412SHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
10806214f412SHong Zhang     for (j=0; j<ncols; j++) { /* lower triangular part */
1081eb1ec7c1SStefano Zampini       PetscScalar v;
10826214f412SHong Zhang       if (cols[j] == row) continue;
1083eb1ec7c1SStefano Zampini       v    = A->hermitian ? PetscConj(vals[j]) : vals[j];
1084eb1ec7c1SStefano Zampini       ierr = MatSetValues(mat_elemental,1,&cols[j],1,&row,&v,ADD_VALUES);CHKERRQ(ierr);
10856214f412SHong Zhang     }
10866214f412SHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
10876214f412SHong Zhang   }
10886214f412SHong Zhang   ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr);
10896214f412SHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10906214f412SHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10916214f412SHong Zhang 
1092511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
109328be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
10946214f412SHong Zhang   } else {
10956214f412SHong Zhang     *newmat = mat_elemental;
10966214f412SHong Zhang   }
10976214f412SHong Zhang   PetscFunctionReturn(0);
10986214f412SHong Zhang }
10996214f412SHong Zhang 
1100db31f6deSJed Brown static PetscErrorCode MatDestroy_Elemental(Mat A)
1101db31f6deSJed Brown {
1102db31f6deSJed Brown   Mat_Elemental      *a = (Mat_Elemental*)A->data;
1103db31f6deSJed Brown   PetscErrorCode     ierr;
11045e9f5b67SHong Zhang   Mat_Elemental_Grid *commgrid;
11055e9f5b67SHong Zhang   PetscBool          flg;
11065e9f5b67SHong Zhang   MPI_Comm           icomm;
1107db31f6deSJed Brown 
1108db31f6deSJed Brown   PetscFunctionBegin;
1109db31f6deSJed Brown   delete a->emat;
1110ea394475SSatish Balay   delete a->P;
1111ea394475SSatish Balay   delete a->Q;
11125e9f5b67SHong Zhang 
1113e8146892SSatish Balay   El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A));
11140c18141cSBarry Smith   ierr = PetscCommDuplicate(cxxcomm.comm,&icomm,NULL);CHKERRQ(ierr);
111547435625SJed Brown   ierr = MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr);
11165e9f5b67SHong Zhang   if (--commgrid->grid_refct == 0) {
11175e9f5b67SHong Zhang     delete commgrid->grid;
11185e9f5b67SHong Zhang     ierr = PetscFree(commgrid);CHKERRQ(ierr);
111947435625SJed Brown     ierr = MPI_Comm_free_keyval(&Petsc_Elemental_keyval);CHKERRQ(ierr);
11205e9f5b67SHong Zhang   }
11215e9f5b67SHong Zhang   ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr);
1122bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",NULL);CHKERRQ(ierr);
11233ca39a21SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverType_C",NULL);CHKERRQ(ierr);
1124f6e5db1bSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_elemental_mpidense_C",NULL);CHKERRQ(ierr);
1125db31f6deSJed Brown   ierr = PetscFree(A->data);CHKERRQ(ierr);
1126db31f6deSJed Brown   PetscFunctionReturn(0);
1127db31f6deSJed Brown }
1128db31f6deSJed Brown 
1129db31f6deSJed Brown PetscErrorCode MatSetUp_Elemental(Mat A)
1130db31f6deSJed Brown {
1131db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
1132db31f6deSJed Brown   PetscErrorCode ierr;
1133f19600a0SHong Zhang   MPI_Comm       comm;
1134db31f6deSJed Brown   PetscMPIInt    rsize,csize;
1135f19600a0SHong Zhang   PetscInt       n;
1136db31f6deSJed Brown 
1137db31f6deSJed Brown   PetscFunctionBegin;
1138db31f6deSJed Brown   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1139db31f6deSJed Brown   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1140db31f6deSJed Brown 
1141d8304050SJose E. Roman   /* Check if local row and column sizes are equally distributed.
1142f19600a0SHong Zhang      Jed: Elemental uses "element" cyclic ordering so the sizes need to match that
1143f19600a0SHong Zhang      exactly.  The strategy in MatElemental is for PETSc to implicitly permute to block ordering (like would be returned by
1144d8304050SJose E. Roman      PetscSplitOwnership(comm,&n,&N), at which point Elemental matrices can act on PETSc vectors without redistributing the vectors. */
1145f19600a0SHong Zhang   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1146f19600a0SHong Zhang   n = PETSC_DECIDE;
1147f19600a0SHong Zhang   ierr = PetscSplitOwnership(comm,&n,&A->rmap->N);CHKERRQ(ierr);
1148f19600a0SHong 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);
1149f19600a0SHong Zhang 
1150f19600a0SHong Zhang   n = PETSC_DECIDE;
1151f19600a0SHong Zhang   ierr = PetscSplitOwnership(comm,&n,&A->cmap->N);CHKERRQ(ierr);
1152f19600a0SHong 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);
1153f19600a0SHong Zhang 
1154efb79153SJack Poulson   a->emat->Resize(A->rmap->N,A->cmap->N);CHKERRQ(ierr);
1155e8146892SSatish Balay   El::Zero(*a->emat);
1156db31f6deSJed Brown 
1157db31f6deSJed Brown   ierr = MPI_Comm_size(A->rmap->comm,&rsize);CHKERRQ(ierr);
1158db31f6deSJed Brown   ierr = MPI_Comm_size(A->cmap->comm,&csize);CHKERRQ(ierr);
1159ce94432eSBarry Smith   if (csize != rsize) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Cannot use row and column communicators of different sizes");
1160db31f6deSJed Brown   a->commsize = rsize;
1161db31f6deSJed Brown   a->mr[0] = A->rmap->N % rsize; if (!a->mr[0]) a->mr[0] = rsize;
1162db31f6deSJed Brown   a->mr[1] = A->cmap->N % csize; if (!a->mr[1]) a->mr[1] = csize;
1163db31f6deSJed Brown   a->m[0]  = A->rmap->N / rsize + (a->mr[0] != rsize);
1164db31f6deSJed Brown   a->m[1]  = A->cmap->N / csize + (a->mr[1] != csize);
1165db31f6deSJed Brown   PetscFunctionReturn(0);
1166db31f6deSJed Brown }
1167db31f6deSJed Brown 
1168aae2c449SHong Zhang PetscErrorCode MatAssemblyBegin_Elemental(Mat A, MatAssemblyType type)
1169aae2c449SHong Zhang {
1170aae2c449SHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data;
1171aae2c449SHong Zhang 
1172aae2c449SHong Zhang   PetscFunctionBegin;
1173fbbcb730SJack Poulson   /* printf("Calling ProcessQueues\n"); */
1174fbbcb730SJack Poulson   a->emat->ProcessQueues();
1175fbbcb730SJack Poulson   /* printf("Finished ProcessQueues\n"); */
1176aae2c449SHong Zhang   PetscFunctionReturn(0);
1177aae2c449SHong Zhang }
1178aae2c449SHong Zhang 
1179aae2c449SHong Zhang PetscErrorCode MatAssemblyEnd_Elemental(Mat A, MatAssemblyType type)
1180aae2c449SHong Zhang {
1181aae2c449SHong Zhang   PetscFunctionBegin;
1182aae2c449SHong Zhang   /* Currently does nothing */
1183aae2c449SHong Zhang   PetscFunctionReturn(0);
1184aae2c449SHong Zhang }
1185aae2c449SHong Zhang 
11867b30e0f1SHong Zhang PetscErrorCode MatLoad_Elemental(Mat newMat, PetscViewer viewer)
11877b30e0f1SHong Zhang {
11887b30e0f1SHong Zhang   PetscErrorCode ierr;
11897b30e0f1SHong Zhang   Mat            Adense,Ae;
11907b30e0f1SHong Zhang   MPI_Comm       comm;
11917b30e0f1SHong Zhang 
11927b30e0f1SHong Zhang   PetscFunctionBegin;
11937b30e0f1SHong Zhang   ierr = PetscObjectGetComm((PetscObject)newMat,&comm);CHKERRQ(ierr);
11947b30e0f1SHong Zhang   ierr = MatCreate(comm,&Adense);CHKERRQ(ierr);
11957b30e0f1SHong Zhang   ierr = MatSetType(Adense,MATDENSE);CHKERRQ(ierr);
11967b30e0f1SHong Zhang   ierr = MatLoad(Adense,viewer);CHKERRQ(ierr);
11977b30e0f1SHong Zhang   ierr = MatConvert(Adense, MATELEMENTAL, MAT_INITIAL_MATRIX,&Ae);CHKERRQ(ierr);
11987b30e0f1SHong Zhang   ierr = MatDestroy(&Adense);CHKERRQ(ierr);
119928be2f97SBarry Smith   ierr = MatHeaderReplace(newMat,&Ae);CHKERRQ(ierr);
12007b30e0f1SHong Zhang   PetscFunctionReturn(0);
12017b30e0f1SHong Zhang }
12027b30e0f1SHong Zhang 
120340d92e34SHong Zhang /* -------------------------------------------------------------------*/
120440d92e34SHong Zhang static struct _MatOps MatOps_Values = {
120540d92e34SHong Zhang        MatSetValues_Elemental,
120640d92e34SHong Zhang        0,
120740d92e34SHong Zhang        0,
120840d92e34SHong Zhang        MatMult_Elemental,
120940d92e34SHong Zhang /* 4*/ MatMultAdd_Elemental,
12109426833fSXuan Zhou        MatMultTranspose_Elemental,
1211e883f9d5SXuan Zhou        MatMultTransposeAdd_Elemental,
121240d92e34SHong Zhang        MatSolve_Elemental,
1213df311e6cSXuan Zhou        MatSolveAdd_Elemental,
12142ef15aa2SHong Zhang        0,
12152ef15aa2SHong Zhang /*10*/ 0,
121640d92e34SHong Zhang        MatLUFactor_Elemental,
121740d92e34SHong Zhang        MatCholeskyFactor_Elemental,
121840d92e34SHong Zhang        0,
121940d92e34SHong Zhang        MatTranspose_Elemental,
122040d92e34SHong Zhang /*15*/ MatGetInfo_Elemental,
122140d92e34SHong Zhang        0,
122261119200SXuan Zhou        MatGetDiagonal_Elemental,
1223ade3cc5eSXuan Zhou        MatDiagonalScale_Elemental,
122440d92e34SHong Zhang        MatNorm_Elemental,
122540d92e34SHong Zhang /*20*/ MatAssemblyBegin_Elemental,
122640d92e34SHong Zhang        MatAssemblyEnd_Elemental,
122732d7a744SHong Zhang        MatSetOption_Elemental,
122840d92e34SHong Zhang        MatZeroEntries_Elemental,
122940d92e34SHong Zhang /*24*/ 0,
123040d92e34SHong Zhang        MatLUFactorSymbolic_Elemental,
123140d92e34SHong Zhang        MatLUFactorNumeric_Elemental,
123240d92e34SHong Zhang        MatCholeskyFactorSymbolic_Elemental,
123340d92e34SHong Zhang        MatCholeskyFactorNumeric_Elemental,
123440d92e34SHong Zhang /*29*/ MatSetUp_Elemental,
123540d92e34SHong Zhang        0,
123640d92e34SHong Zhang        0,
123740d92e34SHong Zhang        0,
123840d92e34SHong Zhang        0,
1239df311e6cSXuan Zhou /*34*/ MatDuplicate_Elemental,
124040d92e34SHong Zhang        0,
124140d92e34SHong Zhang        0,
124240d92e34SHong Zhang        0,
124340d92e34SHong Zhang        0,
124440d92e34SHong Zhang /*39*/ MatAXPY_Elemental,
124540d92e34SHong Zhang        0,
124640d92e34SHong Zhang        0,
124740d92e34SHong Zhang        0,
124840d92e34SHong Zhang        MatCopy_Elemental,
124940d92e34SHong Zhang /*44*/ 0,
125040d92e34SHong Zhang        MatScale_Elemental,
12517d68702bSBarry Smith        MatShift_Basic,
125240d92e34SHong Zhang        0,
125340d92e34SHong Zhang        0,
125440d92e34SHong Zhang /*49*/ 0,
125540d92e34SHong Zhang        0,
125640d92e34SHong Zhang        0,
125740d92e34SHong Zhang        0,
125840d92e34SHong Zhang        0,
125940d92e34SHong Zhang /*54*/ 0,
126040d92e34SHong Zhang        0,
126140d92e34SHong Zhang        0,
126240d92e34SHong Zhang        0,
126340d92e34SHong Zhang        0,
126440d92e34SHong Zhang /*59*/ 0,
126540d92e34SHong Zhang        MatDestroy_Elemental,
126640d92e34SHong Zhang        MatView_Elemental,
126740d92e34SHong Zhang        0,
126840d92e34SHong Zhang        0,
126940d92e34SHong Zhang /*64*/ 0,
127040d92e34SHong Zhang        0,
127140d92e34SHong Zhang        0,
127240d92e34SHong Zhang        0,
127340d92e34SHong Zhang        0,
127440d92e34SHong Zhang /*69*/ 0,
127540d92e34SHong Zhang        0,
12762ef0cf24SXuan Zhou        MatConvert_Elemental_Dense,
127740d92e34SHong Zhang        0,
127840d92e34SHong Zhang        0,
127940d92e34SHong Zhang /*74*/ 0,
128040d92e34SHong Zhang        0,
128140d92e34SHong Zhang        0,
128240d92e34SHong Zhang        0,
128340d92e34SHong Zhang        0,
128440d92e34SHong Zhang /*79*/ 0,
128540d92e34SHong Zhang        0,
128640d92e34SHong Zhang        0,
128740d92e34SHong Zhang        0,
12887b30e0f1SHong Zhang        MatLoad_Elemental,
128940d92e34SHong Zhang /*84*/ 0,
129040d92e34SHong Zhang        0,
129140d92e34SHong Zhang        0,
129240d92e34SHong Zhang        0,
129340d92e34SHong Zhang        0,
12944222ddf1SHong Zhang /*89*/ 0,
12954222ddf1SHong Zhang        0,
129640d92e34SHong Zhang        MatMatMultNumeric_Elemental,
129740d92e34SHong Zhang        0,
129840d92e34SHong Zhang        0,
129940d92e34SHong Zhang /*94*/ 0,
13004222ddf1SHong Zhang        0,
13014222ddf1SHong Zhang        0,
1302df311e6cSXuan Zhou        MatMatTransposeMultNumeric_Elemental,
130340d92e34SHong Zhang        0,
13044222ddf1SHong Zhang /*99*/ MatProductSetFromOptions_Elemental,
130540d92e34SHong Zhang        0,
130640d92e34SHong Zhang        0,
1307dfcb0403SXuan Zhou        MatConjugate_Elemental,
130840d92e34SHong Zhang        0,
130940d92e34SHong Zhang /*104*/0,
131040d92e34SHong Zhang        0,
131140d92e34SHong Zhang        0,
131240d92e34SHong Zhang        0,
131340d92e34SHong Zhang        0,
131440d92e34SHong Zhang /*109*/MatMatSolve_Elemental,
131540d92e34SHong Zhang        0,
131640d92e34SHong Zhang        0,
131740d92e34SHong Zhang        0,
131834fa46e1SFrancesco Ballarin        MatMissingDiagonal_Elemental,
131940d92e34SHong Zhang /*114*/0,
132040d92e34SHong Zhang        0,
132140d92e34SHong Zhang        0,
132240d92e34SHong Zhang        0,
132340d92e34SHong Zhang        0,
132440d92e34SHong Zhang /*119*/0,
13254a29722dSXuan Zhou        MatHermitianTranspose_Elemental,
132640d92e34SHong Zhang        0,
132740d92e34SHong Zhang        0,
132840d92e34SHong Zhang        0,
132940d92e34SHong Zhang /*124*/0,
133040d92e34SHong Zhang        0,
133140d92e34SHong Zhang        0,
133240d92e34SHong Zhang        0,
133340d92e34SHong Zhang        0,
133440d92e34SHong Zhang /*129*/0,
133540d92e34SHong Zhang        0,
133640d92e34SHong Zhang        0,
133740d92e34SHong Zhang        0,
133840d92e34SHong Zhang        0,
133940d92e34SHong Zhang /*134*/0,
134040d92e34SHong Zhang        0,
134140d92e34SHong Zhang        0,
134240d92e34SHong Zhang        0,
13434222ddf1SHong Zhang        0,
13444222ddf1SHong Zhang        0,
13454222ddf1SHong Zhang /*140*/0,
13464222ddf1SHong Zhang        0,
13474222ddf1SHong Zhang        0,
13484222ddf1SHong Zhang        0,
13494222ddf1SHong Zhang        0,
13504222ddf1SHong Zhang /*145*/0,
13514222ddf1SHong Zhang        0,
135240d92e34SHong Zhang        0
135340d92e34SHong Zhang };
135440d92e34SHong Zhang 
1355ed36708cSHong Zhang /*MC
1356ed36708cSHong Zhang    MATELEMENTAL = "elemental" - A matrix type for dense matrices using the Elemental package
1357ed36708cSHong Zhang 
1358c2b89b5dSBarry Smith   Use ./configure --download-elemental to install PETSc to use Elemental
1359c2b89b5dSBarry Smith 
13603ca39a21SBarry Smith   Use -pc_type lu -pc_factor_mat_solver_type elemental to use this direct solver
1361c2b89b5dSBarry Smith 
1362ed36708cSHong Zhang    Options Database Keys:
13635cc86fc1SJed Brown + -mat_type elemental - sets the matrix type to "elemental" during a call to MatSetFromOptions()
13645cc86fc1SJed Brown - -mat_elemental_grid_height - sets Grid Height for 2D cyclic ordering of internal matrix
1365ed36708cSHong Zhang 
1366ed36708cSHong Zhang   Level: beginner
1367ed36708cSHong Zhang 
13685cb544a0SHong Zhang .seealso: MATDENSE
1369ed36708cSHong Zhang M*/
13704a29722dSXuan Zhou 
13718cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Elemental(Mat A)
1372db31f6deSJed Brown {
1373db31f6deSJed Brown   Mat_Elemental      *a;
1374db31f6deSJed Brown   PetscErrorCode     ierr;
13755682a260SJack Poulson   PetscBool          flg,flg1;
13765e9f5b67SHong Zhang   Mat_Elemental_Grid *commgrid;
13775e9f5b67SHong Zhang   MPI_Comm           icomm;
13785682a260SJack Poulson   PetscInt           optv1;
1379db31f6deSJed Brown 
1380db31f6deSJed Brown   PetscFunctionBegin;
138140d92e34SHong Zhang   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
138240d92e34SHong Zhang   A->insertmode = NOT_SET_VALUES;
1383db31f6deSJed Brown 
1384b00a9115SJed Brown   ierr = PetscNewLog(A,&a);CHKERRQ(ierr);
1385db31f6deSJed Brown   A->data = (void*)a;
1386db31f6deSJed Brown 
1387db31f6deSJed Brown   /* Set up the elemental matrix */
1388e8146892SSatish Balay   El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A));
13895e9f5b67SHong Zhang 
13905e9f5b67SHong Zhang   /* Grid needs to be shared between multiple Mats on the same communicator, implement by attribute caching on the MPI_Comm */
13915e9f5b67SHong Zhang   if (Petsc_Elemental_keyval == MPI_KEYVAL_INVALID) {
139212801b39SBarry Smith     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Elemental_keyval,(void*)0);CHKERRQ(ierr);
13935e9f5b67SHong Zhang   }
13940c18141cSBarry Smith   ierr = PetscCommDuplicate(cxxcomm.comm,&icomm,NULL);CHKERRQ(ierr);
139547435625SJed Brown   ierr = MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr);
13965e9f5b67SHong Zhang   if (!flg) {
1397b00a9115SJed Brown     ierr = PetscNewLog(A,&commgrid);CHKERRQ(ierr);
13985cb544a0SHong Zhang 
1399ce94432eSBarry Smith     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"Elemental Options","Mat");CHKERRQ(ierr);
1400e8146892SSatish Balay     /* displayed default grid sizes (CommSize,1) are set by us arbitrarily until El::Grid() is called */
1401e8146892SSatish Balay     ierr = PetscOptionsInt("-mat_elemental_grid_height","Grid Height","None",El::mpi::Size(cxxcomm),&optv1,&flg1);CHKERRQ(ierr);
14025682a260SJack Poulson     if (flg1) {
1403d8304050SJose 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));
1404e8146892SSatish Balay       commgrid->grid = new El::Grid(cxxcomm,optv1); /* use user-provided grid height */
14052ef0cf24SXuan Zhou     } else {
1406e8146892SSatish Balay       commgrid->grid = new El::Grid(cxxcomm); /* use Elemental default grid sizes */
1407da0640a4SHong Zhang       /* printf("new commgrid->grid = %p\n",commgrid->grid);  -- memory leak revealed by valgrind? */
1408ed667823SXuan Zhou     }
14095e9f5b67SHong Zhang     commgrid->grid_refct = 1;
141047435625SJed Brown     ierr = MPI_Comm_set_attr(icomm,Petsc_Elemental_keyval,(void*)commgrid);CHKERRQ(ierr);
1411ea394475SSatish Balay 
1412ea394475SSatish Balay     a->pivoting    = 1;
1413ea394475SSatish Balay     ierr = PetscOptionsInt("-mat_elemental_pivoting","Pivoting","None",a->pivoting,&a->pivoting,NULL);CHKERRQ(ierr);
1414ea394475SSatish Balay 
14152a808120SBarry Smith     ierr = PetscOptionsEnd();CHKERRQ(ierr);
14165e9f5b67SHong Zhang   } else {
14175e9f5b67SHong Zhang     commgrid->grid_refct++;
14185e9f5b67SHong Zhang   }
14195e9f5b67SHong Zhang   ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr);
14205e9f5b67SHong Zhang   a->grid        = commgrid->grid;
1421e8146892SSatish Balay   a->emat        = new El::DistMatrix<PetscElemScalar>(*a->grid);
142232d7a744SHong Zhang   a->roworiented = PETSC_TRUE;
1423db31f6deSJed Brown 
1424bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",MatGetOwnershipIS_Elemental);CHKERRQ(ierr);
1425f6e5db1bSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_elemental_mpidense_C",MatProductSetFromOptions_Elemental_MPIDense);CHKERRQ(ierr);
1426db31f6deSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)A,MATELEMENTAL);CHKERRQ(ierr);
1427db31f6deSJed Brown   PetscFunctionReturn(0);
1428db31f6deSJed Brown }
1429