xref: /petsc/src/mat/impls/elemental/matelem.cxx (revision d83040500b51b5e5c40ec8b07fc03313501dab55)
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 }
3814222ddf1SHong Zhang /* --------------------------------------- */
3824222ddf1SHong Zhang 
383a9d89745SXuan Zhou static PetscErrorCode MatGetDiagonal_Elemental(Mat A,Vec D)
38461119200SXuan Zhou {
385a9d89745SXuan Zhou   PetscInt        i,nrows,ncols,nD,rrank,ridx,crank,cidx;
386a9d89745SXuan Zhou   Mat_Elemental   *a = (Mat_Elemental*)A->data;
38761119200SXuan Zhou   PetscErrorCode  ierr;
388a9d89745SXuan Zhou   PetscElemScalar v;
389ce94432eSBarry Smith   MPI_Comm        comm;
39061119200SXuan Zhou 
39161119200SXuan Zhou   PetscFunctionBegin;
392ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
393a9d89745SXuan Zhou   ierr = MatGetSize(A,&nrows,&ncols);CHKERRQ(ierr);
394a9d89745SXuan Zhou   nD = nrows>ncols ? ncols : nrows;
395a9d89745SXuan Zhou   for (i=0; i<nD; i++) {
396a9d89745SXuan Zhou     PetscInt erow,ecol;
397a9d89745SXuan Zhou     P2RO(A,0,i,&rrank,&ridx);
398a9d89745SXuan Zhou     RO2E(A,0,rrank,ridx,&erow);
399a9d89745SXuan Zhou     if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
400a9d89745SXuan Zhou     P2RO(A,1,i,&crank,&cidx);
401a9d89745SXuan Zhou     RO2E(A,1,crank,cidx,&ecol);
402a9d89745SXuan Zhou     if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
403a9d89745SXuan Zhou     v = a->emat->Get(erow,ecol);
4047c8b904fSSatish Balay     ierr = VecSetValues(D,1,&i,(PetscScalar*)&v,INSERT_VALUES);CHKERRQ(ierr);
405ade3cc5eSXuan Zhou   }
406a9d89745SXuan Zhou   ierr = VecAssemblyBegin(D);CHKERRQ(ierr);
407a9d89745SXuan Zhou   ierr = VecAssemblyEnd(D);CHKERRQ(ierr);
40861119200SXuan Zhou   PetscFunctionReturn(0);
40961119200SXuan Zhou }
41061119200SXuan Zhou 
411ade3cc5eSXuan Zhou static PetscErrorCode MatDiagonalScale_Elemental(Mat X,Vec L,Vec R)
412ade3cc5eSXuan Zhou {
413ade3cc5eSXuan Zhou   Mat_Elemental         *x = (Mat_Elemental*)X->data;
414ade3cc5eSXuan Zhou   const PetscElemScalar *d;
415ade3cc5eSXuan Zhou   PetscErrorCode        ierr;
416ade3cc5eSXuan Zhou 
417ade3cc5eSXuan Zhou   PetscFunctionBegin;
4189065cd98SJed Brown   if (R) {
419ade3cc5eSXuan Zhou     ierr = VecGetArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr);
420e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de;
4210c18141cSBarry Smith     de.LockedAttach(X->cmap->N,1,*x->grid,0,0,d,X->cmap->n);
422e8146892SSatish Balay     El::DiagonalScale(El::RIGHT,El::NORMAL,de,*x->emat);
423ade3cc5eSXuan Zhou     ierr = VecRestoreArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr);
4249065cd98SJed Brown   }
4259065cd98SJed Brown   if (L) {
426ade3cc5eSXuan Zhou     ierr = VecGetArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr);
427e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de;
4280c18141cSBarry Smith     de.LockedAttach(X->rmap->N,1,*x->grid,0,0,d,X->rmap->n);
429e8146892SSatish Balay     El::DiagonalScale(El::LEFT,El::NORMAL,de,*x->emat);
430ade3cc5eSXuan Zhou     ierr = VecRestoreArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr);
431ade3cc5eSXuan Zhou   }
432ade3cc5eSXuan Zhou   PetscFunctionReturn(0);
433ade3cc5eSXuan Zhou }
434ade3cc5eSXuan Zhou 
43534fa46e1SFrancesco Ballarin static PetscErrorCode MatMissingDiagonal_Elemental(Mat A,PetscBool *missing,PetscInt *d)
43634fa46e1SFrancesco Ballarin {
43734fa46e1SFrancesco Ballarin   PetscFunctionBegin;
43834fa46e1SFrancesco Ballarin   *missing = PETSC_FALSE;
43934fa46e1SFrancesco Ballarin   PetscFunctionReturn(0);
44034fa46e1SFrancesco Ballarin }
44134fa46e1SFrancesco Ballarin 
442e6dea9dbSXuan Zhou static PetscErrorCode MatScale_Elemental(Mat X,PetscScalar a)
44365b78793SXuan Zhou {
44465b78793SXuan Zhou   Mat_Elemental  *x = (Mat_Elemental*)X->data;
44565b78793SXuan Zhou 
44665b78793SXuan Zhou   PetscFunctionBegin;
447e8146892SSatish Balay   El::Scale((PetscElemScalar)a,*x->emat);
44865b78793SXuan Zhou   PetscFunctionReturn(0);
44965b78793SXuan Zhou }
45065b78793SXuan Zhou 
451f82baa17SHong Zhang /*
452f82baa17SHong Zhang   MatAXPY - Computes Y = a*X + Y.
453f82baa17SHong Zhang */
454e6dea9dbSXuan Zhou static PetscErrorCode MatAXPY_Elemental(Mat Y,PetscScalar a,Mat X,MatStructure str)
455e09a3074SHong Zhang {
456e09a3074SHong Zhang   Mat_Elemental  *x = (Mat_Elemental*)X->data;
457e09a3074SHong Zhang   Mat_Elemental  *y = (Mat_Elemental*)Y->data;
45868446cf8SJed Brown   PetscErrorCode ierr;
459e09a3074SHong Zhang 
460e09a3074SHong Zhang   PetscFunctionBegin;
461e8146892SSatish Balay   El::Axpy((PetscElemScalar)a,*x->emat,*y->emat);
46221f6c9c4SJed Brown   ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
463e09a3074SHong Zhang   PetscFunctionReturn(0);
464e09a3074SHong Zhang }
465e09a3074SHong Zhang 
466d6223691SXuan Zhou static PetscErrorCode MatCopy_Elemental(Mat A,Mat B,MatStructure str)
467d6223691SXuan Zhou {
468d6223691SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
469d6223691SXuan Zhou   Mat_Elemental *b=(Mat_Elemental*)B->data;
470a4ee3bb6SSatish Balay   PetscErrorCode ierr;
471d6223691SXuan Zhou 
472d6223691SXuan Zhou   PetscFunctionBegin;
473e8146892SSatish Balay   El::Copy(*a->emat,*b->emat);
474cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
475d6223691SXuan Zhou   PetscFunctionReturn(0);
476d6223691SXuan Zhou }
477d6223691SXuan Zhou 
478df311e6cSXuan Zhou static PetscErrorCode MatDuplicate_Elemental(Mat A,MatDuplicateOption op,Mat *B)
479df311e6cSXuan Zhou {
480df311e6cSXuan Zhou   Mat            Be;
481ce94432eSBarry Smith   MPI_Comm       comm;
482df311e6cSXuan Zhou   Mat_Elemental  *a=(Mat_Elemental*)A->data;
483df311e6cSXuan Zhou   PetscErrorCode ierr;
484df311e6cSXuan Zhou 
485df311e6cSXuan Zhou   PetscFunctionBegin;
486ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
487df311e6cSXuan Zhou   ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
488df311e6cSXuan Zhou   ierr = MatSetSizes(Be,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
489df311e6cSXuan Zhou   ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
490df311e6cSXuan Zhou   ierr = MatSetUp(Be);CHKERRQ(ierr);
491df311e6cSXuan Zhou   *B = Be;
492df311e6cSXuan Zhou   if (op == MAT_COPY_VALUES) {
493df311e6cSXuan Zhou     Mat_Elemental *b=(Mat_Elemental*)Be->data;
494e8146892SSatish Balay     El::Copy(*a->emat,*b->emat);
495df311e6cSXuan Zhou   }
496df311e6cSXuan Zhou   Be->assembled = PETSC_TRUE;
497df311e6cSXuan Zhou   PetscFunctionReturn(0);
498df311e6cSXuan Zhou }
499df311e6cSXuan Zhou 
500d6223691SXuan Zhou static PetscErrorCode MatTranspose_Elemental(Mat A,MatReuse reuse,Mat *B)
501d6223691SXuan Zhou {
502ec8cb81fSBarry Smith   Mat            Be = *B;
5035262d616SXuan Zhou   PetscErrorCode ierr;
504ce94432eSBarry Smith   MPI_Comm       comm;
5054fe7bbcaSHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data, *b;
506d6223691SXuan Zhou 
507d6223691SXuan Zhou   PetscFunctionBegin;
508ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
5095cb544a0SHong Zhang   /* Only out-of-place supported */
5102847e3fdSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) SETERRQ(comm,PETSC_ERR_SUP,"Only out-of-place supported");
5115262d616SXuan Zhou   if (reuse == MAT_INITIAL_MATRIX) {
5125262d616SXuan Zhou     ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
5135262d616SXuan Zhou     ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
5145262d616SXuan Zhou     ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
5155262d616SXuan Zhou     ierr = MatSetUp(Be);CHKERRQ(ierr);
5165262d616SXuan Zhou     *B = Be;
5175262d616SXuan Zhou   }
5184fe7bbcaSHong Zhang   b = (Mat_Elemental*)Be->data;
519e8146892SSatish Balay   El::Transpose(*a->emat,*b->emat);
5205262d616SXuan Zhou   Be->assembled = PETSC_TRUE;
521d6223691SXuan Zhou   PetscFunctionReturn(0);
522d6223691SXuan Zhou }
523d6223691SXuan Zhou 
524dfcb0403SXuan Zhou static PetscErrorCode MatConjugate_Elemental(Mat A)
525dfcb0403SXuan Zhou {
526dfcb0403SXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
527dfcb0403SXuan Zhou 
528dfcb0403SXuan Zhou   PetscFunctionBegin;
529e8146892SSatish Balay   El::Conjugate(*a->emat);
530dfcb0403SXuan Zhou   PetscFunctionReturn(0);
531dfcb0403SXuan Zhou }
532dfcb0403SXuan Zhou 
5334a29722dSXuan Zhou static PetscErrorCode MatHermitianTranspose_Elemental(Mat A,MatReuse reuse,Mat *B)
5344a29722dSXuan Zhou {
535ec8cb81fSBarry Smith   Mat            Be = *B;
5364a29722dSXuan Zhou   PetscErrorCode ierr;
537ce94432eSBarry Smith   MPI_Comm       comm;
5384a29722dSXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data, *b;
5394a29722dSXuan Zhou 
5404a29722dSXuan Zhou   PetscFunctionBegin;
541ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
5425cb544a0SHong Zhang   /* Only out-of-place supported */
5434a29722dSXuan Zhou   if (reuse == MAT_INITIAL_MATRIX){
5444a29722dSXuan Zhou     ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
5454a29722dSXuan Zhou     ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
5464a29722dSXuan Zhou     ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
5474a29722dSXuan Zhou     ierr = MatSetUp(Be);CHKERRQ(ierr);
5484a29722dSXuan Zhou     *B = Be;
5494a29722dSXuan Zhou   }
5504a29722dSXuan Zhou   b = (Mat_Elemental*)Be->data;
551e8146892SSatish Balay   El::Adjoint(*a->emat,*b->emat);
5524a29722dSXuan Zhou   Be->assembled = PETSC_TRUE;
5534a29722dSXuan Zhou   PetscFunctionReturn(0);
5544a29722dSXuan Zhou }
5554a29722dSXuan Zhou 
5561f881ff8SXuan Zhou static PetscErrorCode MatSolve_Elemental(Mat A,Vec B,Vec X)
5571f881ff8SXuan Zhou {
5581f881ff8SXuan Zhou   Mat_Elemental     *a = (Mat_Elemental*)A->data;
5591f881ff8SXuan Zhou   PetscErrorCode    ierr;
560df311e6cSXuan Zhou   PetscElemScalar   *x;
561ea394475SSatish Balay   PetscInt          pivoting = a->pivoting;
5621f881ff8SXuan Zhou 
5631f881ff8SXuan Zhou   PetscFunctionBegin;
56445cf121fSXuan Zhou   ierr = VecCopy(B,X);CHKERRQ(ierr);
565e6dea9dbSXuan Zhou   ierr = VecGetArray(X,(PetscScalar **)&x);CHKERRQ(ierr);
566ea394475SSatish Balay 
567e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe;
5680c18141cSBarry Smith   xe.Attach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n);
569e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::MC,El::MR> xer(xe);
570fc54b460SXuan Zhou   switch (A->factortype) {
571fc54b460SXuan Zhou   case MAT_FACTOR_LU:
572ea394475SSatish Balay     if (pivoting == 0) {
573e8146892SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,xer);
574ea394475SSatish Balay     } else if (pivoting == 1) {
575ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,xer);
576ea394475SSatish Balay     } else { /* pivoting == 2 */
577ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,xer);
5781f881ff8SXuan Zhou     }
579fc54b460SXuan Zhou     break;
580fc54b460SXuan Zhou   case MAT_FACTOR_CHOLESKY:
581e8146892SSatish Balay     El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,xer);
582fc54b460SXuan Zhou     break;
583fc54b460SXuan Zhou   default:
5844fe7bbcaSHong Zhang     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType");
585fc54b460SXuan Zhou     break;
5861f881ff8SXuan Zhou   }
587ea394475SSatish Balay   El::Copy(xer,xe);
588ea394475SSatish Balay 
589e6dea9dbSXuan Zhou   ierr = VecRestoreArray(X,(PetscScalar **)&x);CHKERRQ(ierr);
5901f881ff8SXuan Zhou   PetscFunctionReturn(0);
5911f881ff8SXuan Zhou }
5921f881ff8SXuan Zhou 
593df311e6cSXuan Zhou static PetscErrorCode MatSolveAdd_Elemental(Mat A,Vec B,Vec Y,Vec X)
594df311e6cSXuan Zhou {
595df311e6cSXuan Zhou   PetscErrorCode    ierr;
596df311e6cSXuan Zhou 
597df311e6cSXuan Zhou   PetscFunctionBegin;
598df311e6cSXuan Zhou   ierr = MatSolve_Elemental(A,B,X);CHKERRQ(ierr);
5993d7f40dbSXuan Zhou   ierr = VecAXPY(X,1,Y);CHKERRQ(ierr);
600df311e6cSXuan Zhou   PetscFunctionReturn(0);
601df311e6cSXuan Zhou }
602df311e6cSXuan Zhou 
603ae844d54SHong Zhang static PetscErrorCode MatMatSolve_Elemental(Mat A,Mat B,Mat X)
604ae844d54SHong Zhang {
6051f0e42cfSHong Zhang   Mat_Elemental *a=(Mat_Elemental*)A->data;
606d6223691SXuan Zhou   Mat_Elemental *b=(Mat_Elemental*)B->data;
6071f0e42cfSHong Zhang   Mat_Elemental *x=(Mat_Elemental*)X->data;
608ea394475SSatish Balay   PetscInt      pivoting = a->pivoting;
6091f0e42cfSHong Zhang 
610ae844d54SHong Zhang   PetscFunctionBegin;
611e8146892SSatish Balay   El::Copy(*b->emat,*x->emat);
612fc54b460SXuan Zhou   switch (A->factortype) {
613fc54b460SXuan Zhou   case MAT_FACTOR_LU:
614ea394475SSatish Balay     if (pivoting == 0) {
615e8146892SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*x->emat);
616ea394475SSatish Balay     } else if (pivoting == 1) {
617ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*x->emat);
618ea394475SSatish Balay     } else {
619ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,*x->emat);
620d6223691SXuan Zhou     }
621fc54b460SXuan Zhou     break;
622fc54b460SXuan Zhou   case MAT_FACTOR_CHOLESKY:
623e8146892SSatish Balay     El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,*x->emat);
624fc54b460SXuan Zhou     break;
625fc54b460SXuan Zhou   default:
6264fe7bbcaSHong Zhang     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType");
627fc54b460SXuan Zhou     break;
628fc54b460SXuan Zhou   }
629ae844d54SHong Zhang   PetscFunctionReturn(0);
630ae844d54SHong Zhang }
631ae844d54SHong Zhang 
632ae844d54SHong Zhang static PetscErrorCode MatLUFactor_Elemental(Mat A,IS row,IS col,const MatFactorInfo *info)
633ae844d54SHong Zhang {
6347c920d81SXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
635124af5d2SSatish Balay   PetscErrorCode ierr;
636ea394475SSatish Balay   PetscInt       pivoting = a->pivoting;
6377c920d81SXuan Zhou 
638ae844d54SHong Zhang   PetscFunctionBegin;
639ea394475SSatish Balay   if (pivoting == 0) {
640e8146892SSatish Balay     El::LU(*a->emat);
641ea394475SSatish Balay   } else if (pivoting == 1) {
642ea394475SSatish Balay     El::LU(*a->emat,*a->P);
643ea394475SSatish Balay   } else {
644ea394475SSatish Balay     El::LU(*a->emat,*a->P,*a->Q);
645d6223691SXuan Zhou   }
6461293973dSHong Zhang   A->factortype = MAT_FACTOR_LU;
647834d3fecSHong Zhang   A->assembled  = PETSC_TRUE;
648f6224b95SHong Zhang 
649f6224b95SHong Zhang   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
650f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype);CHKERRQ(ierr);
651ae844d54SHong Zhang   PetscFunctionReturn(0);
652ae844d54SHong Zhang }
653ae844d54SHong Zhang 
654d7c3f9d8SHong Zhang static PetscErrorCode  MatLUFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info)
655d7c3f9d8SHong Zhang {
656d7c3f9d8SHong Zhang   PetscErrorCode ierr;
657d7c3f9d8SHong Zhang 
658d7c3f9d8SHong Zhang   PetscFunctionBegin;
659d7c3f9d8SHong Zhang   ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
660d7c3f9d8SHong Zhang   ierr = MatLUFactor_Elemental(F,0,0,info);CHKERRQ(ierr);
661d7c3f9d8SHong Zhang   PetscFunctionReturn(0);
662d7c3f9d8SHong Zhang }
663d7c3f9d8SHong Zhang 
664d7c3f9d8SHong Zhang static PetscErrorCode  MatLUFactorSymbolic_Elemental(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
665d7c3f9d8SHong Zhang {
666d7c3f9d8SHong Zhang   PetscFunctionBegin;
667*d8304050SJose E. Roman   /* F is created and allocated by MatGetFactor_elemental_petsc(), skip this routine. */
668d7c3f9d8SHong Zhang   PetscFunctionReturn(0);
669d7c3f9d8SHong Zhang }
670d7c3f9d8SHong Zhang 
67145cf121fSXuan Zhou static PetscErrorCode MatCholeskyFactor_Elemental(Mat A,IS perm,const MatFactorInfo *info)
67245cf121fSXuan Zhou {
67345cf121fSXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
674e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::MC,El::STAR> d;
675124af5d2SSatish Balay   PetscErrorCode ierr;
67645cf121fSXuan Zhou 
67745cf121fSXuan Zhou   PetscFunctionBegin;
678e8146892SSatish Balay   El::Cholesky(El::UPPER,*a->emat);
679fc54b460SXuan Zhou   A->factortype = MAT_FACTOR_CHOLESKY;
680834d3fecSHong Zhang   A->assembled  = PETSC_TRUE;
681f6224b95SHong Zhang 
682f6224b95SHong Zhang   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
683f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype);CHKERRQ(ierr);
68445cf121fSXuan Zhou   PetscFunctionReturn(0);
68545cf121fSXuan Zhou }
68645cf121fSXuan Zhou 
68779673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info)
68879673f7bSHong Zhang {
689cb76c1d8SXuan Zhou   PetscErrorCode ierr;
690cb76c1d8SXuan Zhou 
691cb76c1d8SXuan Zhou   PetscFunctionBegin;
692cb76c1d8SXuan Zhou   ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
693cb76c1d8SXuan Zhou   ierr = MatCholeskyFactor_Elemental(F,0,info);CHKERRQ(ierr);
694cb76c1d8SXuan Zhou   PetscFunctionReturn(0);
69579673f7bSHong Zhang }
696cb76c1d8SXuan Zhou 
69779673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorSymbolic_Elemental(Mat F,Mat A,IS perm,const MatFactorInfo *info)
69879673f7bSHong Zhang {
69979673f7bSHong Zhang   PetscFunctionBegin;
700*d8304050SJose E. Roman   /* F is created and allocated by MatGetFactor_elemental_petsc(), skip this routine. */
70179673f7bSHong Zhang   PetscFunctionReturn(0);
70279673f7bSHong Zhang }
70379673f7bSHong Zhang 
704ea799195SBarry Smith PetscErrorCode MatFactorGetSolverType_elemental_elemental(Mat A,MatSolverType *type)
70515767789SHong Zhang {
70615767789SHong Zhang   PetscFunctionBegin;
70715767789SHong Zhang   *type = MATSOLVERELEMENTAL;
70815767789SHong Zhang   PetscFunctionReturn(0);
70915767789SHong Zhang }
71015767789SHong Zhang 
71115767789SHong Zhang static PetscErrorCode MatGetFactor_elemental_elemental(Mat A,MatFactorType ftype,Mat *F)
7121293973dSHong Zhang {
7131293973dSHong Zhang   Mat            B;
7141293973dSHong Zhang   PetscErrorCode ierr;
7151293973dSHong Zhang 
7161293973dSHong Zhang   PetscFunctionBegin;
7171293973dSHong Zhang   /* Create the factorization matrix */
718ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
7191293973dSHong Zhang   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
7201293973dSHong Zhang   ierr = MatSetType(B,MATELEMENTAL);CHKERRQ(ierr);
7211293973dSHong Zhang   ierr = MatSetUp(B);CHKERRQ(ierr);
7221293973dSHong Zhang   B->factortype = ftype;
72300c67f3bSHong Zhang   ierr = PetscFree(B->solvertype);CHKERRQ(ierr);
72400c67f3bSHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&B->solvertype);CHKERRQ(ierr);
72500c67f3bSHong Zhang 
7263ca39a21SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_elemental_elemental);CHKERRQ(ierr);
7271293973dSHong Zhang   *F            = B;
7281293973dSHong Zhang   PetscFunctionReturn(0);
7291293973dSHong Zhang }
7301293973dSHong Zhang 
7313ca39a21SBarry Smith PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Elemental(void)
73242c9c57cSBarry Smith {
73318713533SBarry Smith   PetscErrorCode ierr;
73418713533SBarry Smith 
73542c9c57cSBarry Smith   PetscFunctionBegin;
7363ca39a21SBarry Smith   ierr = MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL,        MAT_FACTOR_LU,MatGetFactor_elemental_elemental);CHKERRQ(ierr);
7373ca39a21SBarry Smith   ierr = MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL,        MAT_FACTOR_CHOLESKY,MatGetFactor_elemental_elemental);CHKERRQ(ierr);
73842c9c57cSBarry Smith   PetscFunctionReturn(0);
73942c9c57cSBarry Smith }
74042c9c57cSBarry Smith 
7411f881ff8SXuan Zhou static PetscErrorCode MatNorm_Elemental(Mat A,NormType type,PetscReal *nrm)
7421f881ff8SXuan Zhou {
7431f881ff8SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
7441f881ff8SXuan Zhou 
7451f881ff8SXuan Zhou   PetscFunctionBegin;
7461f881ff8SXuan Zhou   switch (type){
7471f881ff8SXuan Zhou   case NORM_1:
748e8146892SSatish Balay     *nrm = El::OneNorm(*a->emat);
7491f881ff8SXuan Zhou     break;
7501f881ff8SXuan Zhou   case NORM_FROBENIUS:
751e8146892SSatish Balay     *nrm = El::FrobeniusNorm(*a->emat);
7521f881ff8SXuan Zhou     break;
7531f881ff8SXuan Zhou   case NORM_INFINITY:
754e8146892SSatish Balay     *nrm = El::InfinityNorm(*a->emat);
7551f881ff8SXuan Zhou     break;
7561f881ff8SXuan Zhou   default:
757*d8304050SJose E. Roman     SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unsupported norm type");
7581f881ff8SXuan Zhou   }
7591f881ff8SXuan Zhou   PetscFunctionReturn(0);
7601f881ff8SXuan Zhou }
7611f881ff8SXuan Zhou 
7625262d616SXuan Zhou static PetscErrorCode MatZeroEntries_Elemental(Mat A)
7635262d616SXuan Zhou {
7645262d616SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
7655262d616SXuan Zhou 
7665262d616SXuan Zhou   PetscFunctionBegin;
767e8146892SSatish Balay   El::Zero(*a->emat);
7685262d616SXuan Zhou   PetscFunctionReturn(0);
7695262d616SXuan Zhou }
7705262d616SXuan Zhou 
771db31f6deSJed Brown static PetscErrorCode MatGetOwnershipIS_Elemental(Mat A,IS *rows,IS *cols)
772db31f6deSJed Brown {
773db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
774db31f6deSJed Brown   PetscErrorCode ierr;
775db31f6deSJed Brown   PetscInt       i,m,shift,stride,*idx;
776db31f6deSJed Brown 
777db31f6deSJed Brown   PetscFunctionBegin;
778db31f6deSJed Brown   if (rows) {
779db31f6deSJed Brown     m = a->emat->LocalHeight();
780db31f6deSJed Brown     shift = a->emat->ColShift();
781db31f6deSJed Brown     stride = a->emat->ColStride();
782785e854fSJed Brown     ierr = PetscMalloc1(m,&idx);CHKERRQ(ierr);
783db31f6deSJed Brown     for (i=0; i<m; i++) {
784db31f6deSJed Brown       PetscInt rank,offset;
785db31f6deSJed Brown       E2RO(A,0,shift+i*stride,&rank,&offset);
786db31f6deSJed Brown       RO2P(A,0,rank,offset,&idx[i]);
787db31f6deSJed Brown     }
788db31f6deSJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,rows);CHKERRQ(ierr);
789db31f6deSJed Brown   }
790db31f6deSJed Brown   if (cols) {
791db31f6deSJed Brown     m = a->emat->LocalWidth();
792db31f6deSJed Brown     shift = a->emat->RowShift();
793db31f6deSJed Brown     stride = a->emat->RowStride();
794785e854fSJed Brown     ierr = PetscMalloc1(m,&idx);CHKERRQ(ierr);
795db31f6deSJed Brown     for (i=0; i<m; i++) {
796db31f6deSJed Brown       PetscInt rank,offset;
797db31f6deSJed Brown       E2RO(A,1,shift+i*stride,&rank,&offset);
798db31f6deSJed Brown       RO2P(A,1,rank,offset,&idx[i]);
799db31f6deSJed Brown     }
800db31f6deSJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,cols);CHKERRQ(ierr);
801db31f6deSJed Brown   }
802db31f6deSJed Brown   PetscFunctionReturn(0);
803db31f6deSJed Brown }
804db31f6deSJed Brown 
80519fd82e9SBarry Smith static PetscErrorCode MatConvert_Elemental_Dense(Mat A,MatType newtype,MatReuse reuse,Mat *B)
806af295397SXuan Zhou {
8072ef0cf24SXuan Zhou   Mat                Bmpi;
808af295397SXuan Zhou   Mat_Elemental      *a = (Mat_Elemental*)A->data;
809ce94432eSBarry Smith   MPI_Comm           comm;
8102ef0cf24SXuan Zhou   PetscErrorCode     ierr;
811fa9e26c8SHong Zhang   IS                 isrows,iscols;
812fa9e26c8SHong Zhang   PetscInt           rrank,ridx,crank,cidx,nrows,ncols,i,j,erow,ecol,elrow,elcol;
813fa9e26c8SHong Zhang   const PetscInt     *rows,*cols;
814df311e6cSXuan Zhou   PetscElemScalar    v;
815fa9e26c8SHong Zhang   const El::Grid     &grid = a->emat->Grid();
816af295397SXuan Zhou 
817af295397SXuan Zhou   PetscFunctionBegin;
818ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
819a000e53bSHong Zhang 
820de0a22f0SHong Zhang   if (reuse == MAT_REUSE_MATRIX) {
821de0a22f0SHong Zhang     Bmpi = *B;
822de0a22f0SHong Zhang   } else {
823af295397SXuan Zhou     ierr = MatCreate(comm,&Bmpi);CHKERRQ(ierr);
824af295397SXuan Zhou     ierr = MatSetSizes(Bmpi,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
8252ef0cf24SXuan Zhou     ierr = MatSetType(Bmpi,MATDENSE);CHKERRQ(ierr);
826af295397SXuan Zhou     ierr = MatSetUp(Bmpi);CHKERRQ(ierr);
827de0a22f0SHong Zhang   }
828fa9e26c8SHong Zhang 
829fa9e26c8SHong Zhang   /* Get local entries of A */
830fa9e26c8SHong Zhang   ierr = MatGetOwnershipIS(A,&isrows,&iscols);CHKERRQ(ierr);
831fa9e26c8SHong Zhang   ierr = ISGetLocalSize(isrows,&nrows);CHKERRQ(ierr);
832fa9e26c8SHong Zhang   ierr = ISGetIndices(isrows,&rows);CHKERRQ(ierr);
833fa9e26c8SHong Zhang   ierr = ISGetLocalSize(iscols,&ncols);CHKERRQ(ierr);
834fa9e26c8SHong Zhang   ierr = ISGetIndices(iscols,&cols);CHKERRQ(ierr);
835fa9e26c8SHong Zhang 
83657299f2fSHong Zhang   if (a->roworiented) {
8372ef0cf24SXuan Zhou     for (i=0; i<nrows; i++) {
838fa9e26c8SHong Zhang       P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */
8392ef0cf24SXuan Zhou       RO2E(A,0,rrank,ridx,&erow);
8402ef0cf24SXuan Zhou       if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
8412ef0cf24SXuan Zhou       for (j=0; j<ncols; j++) {
842fa9e26c8SHong Zhang         P2RO(A,1,cols[j],&crank,&cidx);
8432ef0cf24SXuan Zhou         RO2E(A,1,crank,cidx,&ecol);
8442ef0cf24SXuan Zhou         if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
845fa9e26c8SHong Zhang 
846fa9e26c8SHong Zhang         elrow = erow / grid.MCSize(); /* Elemental local row index */
847fa9e26c8SHong Zhang         elcol = ecol / grid.MRSize(); /* Elemental local column index */
848fa9e26c8SHong Zhang         v = a->emat->GetLocal(elrow,elcol);
849fa9e26c8SHong Zhang         ierr = MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr);
8502ef0cf24SXuan Zhou       }
8512ef0cf24SXuan Zhou     }
85257299f2fSHong Zhang   } else { /* column-oriented */
85357299f2fSHong Zhang     for (j=0; j<ncols; j++) {
85457299f2fSHong Zhang       P2RO(A,1,cols[j],&crank,&cidx);
85557299f2fSHong Zhang       RO2E(A,1,crank,cidx,&ecol);
85657299f2fSHong Zhang       if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
85757299f2fSHong Zhang       for (i=0; i<nrows; i++) {
85857299f2fSHong Zhang         P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */
85957299f2fSHong Zhang         RO2E(A,0,rrank,ridx,&erow);
86057299f2fSHong Zhang         if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
86157299f2fSHong Zhang 
86257299f2fSHong Zhang         elrow = erow / grid.MCSize(); /* Elemental local row index */
86357299f2fSHong Zhang         elcol = ecol / grid.MRSize(); /* Elemental local column index */
86457299f2fSHong Zhang         v = a->emat->GetLocal(elrow,elcol);
86557299f2fSHong Zhang         ierr = MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr);
86657299f2fSHong Zhang       }
86757299f2fSHong Zhang     }
86857299f2fSHong Zhang   }
869af295397SXuan Zhou   ierr = MatAssemblyBegin(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
870af295397SXuan Zhou   ierr = MatAssemblyEnd(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
871511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
87228be2f97SBarry Smith     ierr = MatHeaderReplace(A,&Bmpi);CHKERRQ(ierr);
873c4ad791aSXuan Zhou   } else {
874c4ad791aSXuan Zhou     *B = Bmpi;
875c4ad791aSXuan Zhou   }
876fa9e26c8SHong Zhang   ierr = ISDestroy(&isrows);CHKERRQ(ierr);
877fa9e26c8SHong Zhang   ierr = ISDestroy(&iscols);CHKERRQ(ierr);
878af295397SXuan Zhou   PetscFunctionReturn(0);
879af295397SXuan Zhou }
880af295397SXuan Zhou 
881cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
882af8000cdSHong Zhang {
883af8000cdSHong Zhang   Mat               mat_elemental;
884af8000cdSHong Zhang   PetscErrorCode    ierr;
885af8000cdSHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols;
886af8000cdSHong Zhang   const PetscInt    *cols;
887af8000cdSHong Zhang   const PetscScalar *vals;
888af8000cdSHong Zhang 
889af8000cdSHong Zhang   PetscFunctionBegin;
890bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
891bdeae278SStefano Zampini     mat_elemental = *newmat;
892bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
893bdeae278SStefano Zampini   } else {
894af8000cdSHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
895af8000cdSHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
896af8000cdSHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
897af8000cdSHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
898bdeae278SStefano Zampini   }
899af8000cdSHong Zhang   for (row=0; row<M; row++) {
900af8000cdSHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
901bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
902af8000cdSHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
903af8000cdSHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
904af8000cdSHong Zhang   }
905af8000cdSHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
906af8000cdSHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
907af8000cdSHong Zhang 
908511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
90928be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
910af8000cdSHong Zhang   } else {
911af8000cdSHong Zhang     *newmat = mat_elemental;
912af8000cdSHong Zhang   }
913af8000cdSHong Zhang   PetscFunctionReturn(0);
914af8000cdSHong Zhang }
915af8000cdSHong Zhang 
916cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
9175d7652ecSHong Zhang {
9185d7652ecSHong Zhang   Mat               mat_elemental;
9195d7652ecSHong Zhang   PetscErrorCode    ierr;
9205d7652ecSHong Zhang   PetscInt          row,ncols,rstart=A->rmap->rstart,rend=A->rmap->rend,j;
9215d7652ecSHong Zhang   const PetscInt    *cols;
9225d7652ecSHong Zhang   const PetscScalar *vals;
9235d7652ecSHong Zhang 
9245d7652ecSHong Zhang   PetscFunctionBegin;
925bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
926bdeae278SStefano Zampini     mat_elemental = *newmat;
927bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
928bdeae278SStefano Zampini   } else {
9295d7652ecSHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
9305d7652ecSHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
9315d7652ecSHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
9325d7652ecSHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
933bdeae278SStefano Zampini   }
9345d7652ecSHong Zhang   for (row=rstart; row<rend; row++) {
9355d7652ecSHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
9365d7652ecSHong Zhang     for (j=0; j<ncols; j++) {
937bdeae278SStefano Zampini       /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
9385d7652ecSHong Zhang       ierr = MatSetValues(mat_elemental,1,&row,1,&cols[j],&vals[j],ADD_VALUES);CHKERRQ(ierr);
9395d7652ecSHong Zhang     }
9405d7652ecSHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
9415d7652ecSHong Zhang   }
9425d7652ecSHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9435d7652ecSHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9445d7652ecSHong Zhang 
945511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
94628be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
9475d7652ecSHong Zhang   } else {
9485d7652ecSHong Zhang     *newmat = mat_elemental;
9495d7652ecSHong Zhang   }
9505d7652ecSHong Zhang   PetscFunctionReturn(0);
9515d7652ecSHong Zhang }
9525d7652ecSHong Zhang 
953cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
9546214f412SHong Zhang {
9556214f412SHong Zhang   Mat               mat_elemental;
9566214f412SHong Zhang   PetscErrorCode    ierr;
9576214f412SHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols,j;
9586214f412SHong Zhang   const PetscInt    *cols;
9596214f412SHong Zhang   const PetscScalar *vals;
9606214f412SHong Zhang 
9616214f412SHong 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 {
9666214f412SHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
9676214f412SHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
9686214f412SHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
9696214f412SHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
970bdeae278SStefano Zampini   }
9716214f412SHong Zhang   ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr);
9726214f412SHong Zhang   for (row=0; row<M; row++) {
9736214f412SHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
974bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
9756214f412SHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
9766214f412SHong Zhang     for (j=0; j<ncols; j++) { /* lower triangular part */
977eb1ec7c1SStefano Zampini       PetscScalar v;
9786214f412SHong Zhang       if (cols[j] == row) continue;
979eb1ec7c1SStefano Zampini       v    = A->hermitian ? PetscConj(vals[j]) : vals[j];
980eb1ec7c1SStefano Zampini       ierr = MatSetValues(mat_elemental,1,&cols[j],1,&row,&v,ADD_VALUES);CHKERRQ(ierr);
9816214f412SHong Zhang     }
9826214f412SHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
9836214f412SHong Zhang   }
9846214f412SHong Zhang   ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr);
9856214f412SHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9866214f412SHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9876214f412SHong Zhang 
988511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
98928be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
9906214f412SHong Zhang   } else {
9916214f412SHong Zhang     *newmat = mat_elemental;
9926214f412SHong Zhang   }
9936214f412SHong Zhang   PetscFunctionReturn(0);
9946214f412SHong Zhang }
9956214f412SHong Zhang 
996cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
9976214f412SHong Zhang {
9986214f412SHong Zhang   Mat               mat_elemental;
9996214f412SHong Zhang   PetscErrorCode    ierr;
10006214f412SHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols,j,rstart=A->rmap->rstart,rend=A->rmap->rend;
10016214f412SHong Zhang   const PetscInt    *cols;
10026214f412SHong Zhang   const PetscScalar *vals;
10036214f412SHong Zhang 
10046214f412SHong Zhang   PetscFunctionBegin;
1005bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1006bdeae278SStefano Zampini     mat_elemental = *newmat;
1007bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
1008bdeae278SStefano Zampini   } else {
10096214f412SHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
10106214f412SHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
10116214f412SHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
10126214f412SHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
1013bdeae278SStefano Zampini   }
10146214f412SHong Zhang   ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr);
10156214f412SHong Zhang   for (row=rstart; row<rend; row++) {
10166214f412SHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
1017bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
10186214f412SHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
10196214f412SHong Zhang     for (j=0; j<ncols; j++) { /* lower triangular part */
1020eb1ec7c1SStefano Zampini       PetscScalar v;
10216214f412SHong Zhang       if (cols[j] == row) continue;
1022eb1ec7c1SStefano Zampini       v    = A->hermitian ? PetscConj(vals[j]) : vals[j];
1023eb1ec7c1SStefano Zampini       ierr = MatSetValues(mat_elemental,1,&cols[j],1,&row,&v,ADD_VALUES);CHKERRQ(ierr);
10246214f412SHong Zhang     }
10256214f412SHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
10266214f412SHong Zhang   }
10276214f412SHong Zhang   ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr);
10286214f412SHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10296214f412SHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10306214f412SHong Zhang 
1031511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
103228be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
10336214f412SHong Zhang   } else {
10346214f412SHong Zhang     *newmat = mat_elemental;
10356214f412SHong Zhang   }
10366214f412SHong Zhang   PetscFunctionReturn(0);
10376214f412SHong Zhang }
10386214f412SHong Zhang 
1039db31f6deSJed Brown static PetscErrorCode MatDestroy_Elemental(Mat A)
1040db31f6deSJed Brown {
1041db31f6deSJed Brown   Mat_Elemental      *a = (Mat_Elemental*)A->data;
1042db31f6deSJed Brown   PetscErrorCode     ierr;
10435e9f5b67SHong Zhang   Mat_Elemental_Grid *commgrid;
10445e9f5b67SHong Zhang   PetscBool          flg;
10455e9f5b67SHong Zhang   MPI_Comm           icomm;
1046db31f6deSJed Brown 
1047db31f6deSJed Brown   PetscFunctionBegin;
1048db31f6deSJed Brown   delete a->emat;
1049ea394475SSatish Balay   delete a->P;
1050ea394475SSatish Balay   delete a->Q;
10515e9f5b67SHong Zhang 
1052e8146892SSatish Balay   El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A));
10530c18141cSBarry Smith   ierr = PetscCommDuplicate(cxxcomm.comm,&icomm,NULL);CHKERRQ(ierr);
105447435625SJed Brown   ierr = MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr);
10555e9f5b67SHong Zhang   if (--commgrid->grid_refct == 0) {
10565e9f5b67SHong Zhang     delete commgrid->grid;
10575e9f5b67SHong Zhang     ierr = PetscFree(commgrid);CHKERRQ(ierr);
105847435625SJed Brown     ierr = MPI_Comm_free_keyval(&Petsc_Elemental_keyval);CHKERRQ(ierr);
10595e9f5b67SHong Zhang   }
10605e9f5b67SHong Zhang   ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr);
1061bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",NULL);CHKERRQ(ierr);
10623ca39a21SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverType_C",NULL);CHKERRQ(ierr);
1063db31f6deSJed Brown   ierr = PetscFree(A->data);CHKERRQ(ierr);
1064db31f6deSJed Brown   PetscFunctionReturn(0);
1065db31f6deSJed Brown }
1066db31f6deSJed Brown 
1067db31f6deSJed Brown PetscErrorCode MatSetUp_Elemental(Mat A)
1068db31f6deSJed Brown {
1069db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
1070db31f6deSJed Brown   PetscErrorCode ierr;
1071f19600a0SHong Zhang   MPI_Comm       comm;
1072db31f6deSJed Brown   PetscMPIInt    rsize,csize;
1073f19600a0SHong Zhang   PetscInt       n;
1074db31f6deSJed Brown 
1075db31f6deSJed Brown   PetscFunctionBegin;
1076db31f6deSJed Brown   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1077db31f6deSJed Brown   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1078db31f6deSJed Brown 
1079*d8304050SJose E. Roman   /* Check if local row and column sizes are equally distributed.
1080f19600a0SHong Zhang      Jed: Elemental uses "element" cyclic ordering so the sizes need to match that
1081f19600a0SHong Zhang      exactly.  The strategy in MatElemental is for PETSc to implicitly permute to block ordering (like would be returned by
1082*d8304050SJose E. Roman      PetscSplitOwnership(comm,&n,&N), at which point Elemental matrices can act on PETSc vectors without redistributing the vectors. */
1083f19600a0SHong Zhang   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1084f19600a0SHong Zhang   n = PETSC_DECIDE;
1085f19600a0SHong Zhang   ierr = PetscSplitOwnership(comm,&n,&A->rmap->N);CHKERRQ(ierr);
1086f19600a0SHong 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);
1087f19600a0SHong Zhang 
1088f19600a0SHong Zhang   n = PETSC_DECIDE;
1089f19600a0SHong Zhang   ierr = PetscSplitOwnership(comm,&n,&A->cmap->N);CHKERRQ(ierr);
1090f19600a0SHong 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);
1091f19600a0SHong Zhang 
1092efb79153SJack Poulson   a->emat->Resize(A->rmap->N,A->cmap->N);CHKERRQ(ierr);
1093e8146892SSatish Balay   El::Zero(*a->emat);
1094db31f6deSJed Brown 
1095db31f6deSJed Brown   ierr = MPI_Comm_size(A->rmap->comm,&rsize);CHKERRQ(ierr);
1096db31f6deSJed Brown   ierr = MPI_Comm_size(A->cmap->comm,&csize);CHKERRQ(ierr);
1097ce94432eSBarry Smith   if (csize != rsize) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Cannot use row and column communicators of different sizes");
1098db31f6deSJed Brown   a->commsize = rsize;
1099db31f6deSJed Brown   a->mr[0] = A->rmap->N % rsize; if (!a->mr[0]) a->mr[0] = rsize;
1100db31f6deSJed Brown   a->mr[1] = A->cmap->N % csize; if (!a->mr[1]) a->mr[1] = csize;
1101db31f6deSJed Brown   a->m[0]  = A->rmap->N / rsize + (a->mr[0] != rsize);
1102db31f6deSJed Brown   a->m[1]  = A->cmap->N / csize + (a->mr[1] != csize);
1103db31f6deSJed Brown   PetscFunctionReturn(0);
1104db31f6deSJed Brown }
1105db31f6deSJed Brown 
1106aae2c449SHong Zhang PetscErrorCode MatAssemblyBegin_Elemental(Mat A, MatAssemblyType type)
1107aae2c449SHong Zhang {
1108aae2c449SHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data;
1109aae2c449SHong Zhang 
1110aae2c449SHong Zhang   PetscFunctionBegin;
1111fbbcb730SJack Poulson   /* printf("Calling ProcessQueues\n"); */
1112fbbcb730SJack Poulson   a->emat->ProcessQueues();
1113fbbcb730SJack Poulson   /* printf("Finished ProcessQueues\n"); */
1114aae2c449SHong Zhang   PetscFunctionReturn(0);
1115aae2c449SHong Zhang }
1116aae2c449SHong Zhang 
1117aae2c449SHong Zhang PetscErrorCode MatAssemblyEnd_Elemental(Mat A, MatAssemblyType type)
1118aae2c449SHong Zhang {
1119aae2c449SHong Zhang   PetscFunctionBegin;
1120aae2c449SHong Zhang   /* Currently does nothing */
1121aae2c449SHong Zhang   PetscFunctionReturn(0);
1122aae2c449SHong Zhang }
1123aae2c449SHong Zhang 
11247b30e0f1SHong Zhang PetscErrorCode MatLoad_Elemental(Mat newMat, PetscViewer viewer)
11257b30e0f1SHong Zhang {
11267b30e0f1SHong Zhang   PetscErrorCode ierr;
11277b30e0f1SHong Zhang   Mat            Adense,Ae;
11287b30e0f1SHong Zhang   MPI_Comm       comm;
11297b30e0f1SHong Zhang 
11307b30e0f1SHong Zhang   PetscFunctionBegin;
11317b30e0f1SHong Zhang   ierr = PetscObjectGetComm((PetscObject)newMat,&comm);CHKERRQ(ierr);
11327b30e0f1SHong Zhang   ierr = MatCreate(comm,&Adense);CHKERRQ(ierr);
11337b30e0f1SHong Zhang   ierr = MatSetType(Adense,MATDENSE);CHKERRQ(ierr);
11347b30e0f1SHong Zhang   ierr = MatLoad(Adense,viewer);CHKERRQ(ierr);
11357b30e0f1SHong Zhang   ierr = MatConvert(Adense, MATELEMENTAL, MAT_INITIAL_MATRIX,&Ae);CHKERRQ(ierr);
11367b30e0f1SHong Zhang   ierr = MatDestroy(&Adense);CHKERRQ(ierr);
113728be2f97SBarry Smith   ierr = MatHeaderReplace(newMat,&Ae);CHKERRQ(ierr);
11387b30e0f1SHong Zhang   PetscFunctionReturn(0);
11397b30e0f1SHong Zhang }
11407b30e0f1SHong Zhang 
114140d92e34SHong Zhang /* -------------------------------------------------------------------*/
114240d92e34SHong Zhang static struct _MatOps MatOps_Values = {
114340d92e34SHong Zhang        MatSetValues_Elemental,
114440d92e34SHong Zhang        0,
114540d92e34SHong Zhang        0,
114640d92e34SHong Zhang        MatMult_Elemental,
114740d92e34SHong Zhang /* 4*/ MatMultAdd_Elemental,
11489426833fSXuan Zhou        MatMultTranspose_Elemental,
1149e883f9d5SXuan Zhou        MatMultTransposeAdd_Elemental,
115040d92e34SHong Zhang        MatSolve_Elemental,
1151df311e6cSXuan Zhou        MatSolveAdd_Elemental,
11522ef15aa2SHong Zhang        0,
11532ef15aa2SHong Zhang /*10*/ 0,
115440d92e34SHong Zhang        MatLUFactor_Elemental,
115540d92e34SHong Zhang        MatCholeskyFactor_Elemental,
115640d92e34SHong Zhang        0,
115740d92e34SHong Zhang        MatTranspose_Elemental,
115840d92e34SHong Zhang /*15*/ MatGetInfo_Elemental,
115940d92e34SHong Zhang        0,
116061119200SXuan Zhou        MatGetDiagonal_Elemental,
1161ade3cc5eSXuan Zhou        MatDiagonalScale_Elemental,
116240d92e34SHong Zhang        MatNorm_Elemental,
116340d92e34SHong Zhang /*20*/ MatAssemblyBegin_Elemental,
116440d92e34SHong Zhang        MatAssemblyEnd_Elemental,
116532d7a744SHong Zhang        MatSetOption_Elemental,
116640d92e34SHong Zhang        MatZeroEntries_Elemental,
116740d92e34SHong Zhang /*24*/ 0,
116840d92e34SHong Zhang        MatLUFactorSymbolic_Elemental,
116940d92e34SHong Zhang        MatLUFactorNumeric_Elemental,
117040d92e34SHong Zhang        MatCholeskyFactorSymbolic_Elemental,
117140d92e34SHong Zhang        MatCholeskyFactorNumeric_Elemental,
117240d92e34SHong Zhang /*29*/ MatSetUp_Elemental,
117340d92e34SHong Zhang        0,
117440d92e34SHong Zhang        0,
117540d92e34SHong Zhang        0,
117640d92e34SHong Zhang        0,
1177df311e6cSXuan Zhou /*34*/ MatDuplicate_Elemental,
117840d92e34SHong Zhang        0,
117940d92e34SHong Zhang        0,
118040d92e34SHong Zhang        0,
118140d92e34SHong Zhang        0,
118240d92e34SHong Zhang /*39*/ MatAXPY_Elemental,
118340d92e34SHong Zhang        0,
118440d92e34SHong Zhang        0,
118540d92e34SHong Zhang        0,
118640d92e34SHong Zhang        MatCopy_Elemental,
118740d92e34SHong Zhang /*44*/ 0,
118840d92e34SHong Zhang        MatScale_Elemental,
11897d68702bSBarry Smith        MatShift_Basic,
119040d92e34SHong Zhang        0,
119140d92e34SHong Zhang        0,
119240d92e34SHong Zhang /*49*/ 0,
119340d92e34SHong Zhang        0,
119440d92e34SHong Zhang        0,
119540d92e34SHong Zhang        0,
119640d92e34SHong Zhang        0,
119740d92e34SHong Zhang /*54*/ 0,
119840d92e34SHong Zhang        0,
119940d92e34SHong Zhang        0,
120040d92e34SHong Zhang        0,
120140d92e34SHong Zhang        0,
120240d92e34SHong Zhang /*59*/ 0,
120340d92e34SHong Zhang        MatDestroy_Elemental,
120440d92e34SHong Zhang        MatView_Elemental,
120540d92e34SHong Zhang        0,
120640d92e34SHong Zhang        0,
120740d92e34SHong Zhang /*64*/ 0,
120840d92e34SHong Zhang        0,
120940d92e34SHong Zhang        0,
121040d92e34SHong Zhang        0,
121140d92e34SHong Zhang        0,
121240d92e34SHong Zhang /*69*/ 0,
121340d92e34SHong Zhang        0,
12142ef0cf24SXuan Zhou        MatConvert_Elemental_Dense,
121540d92e34SHong Zhang        0,
121640d92e34SHong Zhang        0,
121740d92e34SHong Zhang /*74*/ 0,
121840d92e34SHong Zhang        0,
121940d92e34SHong Zhang        0,
122040d92e34SHong Zhang        0,
122140d92e34SHong Zhang        0,
122240d92e34SHong Zhang /*79*/ 0,
122340d92e34SHong Zhang        0,
122440d92e34SHong Zhang        0,
122540d92e34SHong Zhang        0,
12267b30e0f1SHong Zhang        MatLoad_Elemental,
122740d92e34SHong Zhang /*84*/ 0,
122840d92e34SHong Zhang        0,
122940d92e34SHong Zhang        0,
123040d92e34SHong Zhang        0,
123140d92e34SHong Zhang        0,
12324222ddf1SHong Zhang /*89*/ 0,
12334222ddf1SHong Zhang        0,
123440d92e34SHong Zhang        MatMatMultNumeric_Elemental,
123540d92e34SHong Zhang        0,
123640d92e34SHong Zhang        0,
123740d92e34SHong Zhang /*94*/ 0,
12384222ddf1SHong Zhang        0,
12394222ddf1SHong Zhang        0,
1240df311e6cSXuan Zhou        MatMatTransposeMultNumeric_Elemental,
124140d92e34SHong Zhang        0,
12424222ddf1SHong Zhang /*99*/ MatProductSetFromOptions_Elemental,
124340d92e34SHong Zhang        0,
124440d92e34SHong Zhang        0,
1245dfcb0403SXuan Zhou        MatConjugate_Elemental,
124640d92e34SHong Zhang        0,
124740d92e34SHong Zhang /*104*/0,
124840d92e34SHong Zhang        0,
124940d92e34SHong Zhang        0,
125040d92e34SHong Zhang        0,
125140d92e34SHong Zhang        0,
125240d92e34SHong Zhang /*109*/MatMatSolve_Elemental,
125340d92e34SHong Zhang        0,
125440d92e34SHong Zhang        0,
125540d92e34SHong Zhang        0,
125634fa46e1SFrancesco Ballarin        MatMissingDiagonal_Elemental,
125740d92e34SHong Zhang /*114*/0,
125840d92e34SHong Zhang        0,
125940d92e34SHong Zhang        0,
126040d92e34SHong Zhang        0,
126140d92e34SHong Zhang        0,
126240d92e34SHong Zhang /*119*/0,
12634a29722dSXuan Zhou        MatHermitianTranspose_Elemental,
126440d92e34SHong Zhang        0,
126540d92e34SHong Zhang        0,
126640d92e34SHong Zhang        0,
126740d92e34SHong Zhang /*124*/0,
126840d92e34SHong Zhang        0,
126940d92e34SHong Zhang        0,
127040d92e34SHong Zhang        0,
127140d92e34SHong Zhang        0,
127240d92e34SHong Zhang /*129*/0,
127340d92e34SHong Zhang        0,
127440d92e34SHong Zhang        0,
127540d92e34SHong Zhang        0,
127640d92e34SHong Zhang        0,
127740d92e34SHong Zhang /*134*/0,
127840d92e34SHong Zhang        0,
127940d92e34SHong Zhang        0,
128040d92e34SHong Zhang        0,
12814222ddf1SHong Zhang        0,
12824222ddf1SHong Zhang        0,
12834222ddf1SHong Zhang /*140*/0,
12844222ddf1SHong Zhang        0,
12854222ddf1SHong Zhang        0,
12864222ddf1SHong Zhang        0,
12874222ddf1SHong Zhang        0,
12884222ddf1SHong Zhang /*145*/0,
12894222ddf1SHong Zhang        0,
129040d92e34SHong Zhang        0
129140d92e34SHong Zhang };
129240d92e34SHong Zhang 
1293ed36708cSHong Zhang /*MC
1294ed36708cSHong Zhang    MATELEMENTAL = "elemental" - A matrix type for dense matrices using the Elemental package
1295ed36708cSHong Zhang 
1296c2b89b5dSBarry Smith   Use ./configure --download-elemental to install PETSc to use Elemental
1297c2b89b5dSBarry Smith 
12983ca39a21SBarry Smith   Use -pc_type lu -pc_factor_mat_solver_type elemental to use this direct solver
1299c2b89b5dSBarry Smith 
1300ed36708cSHong Zhang    Options Database Keys:
13015cc86fc1SJed Brown + -mat_type elemental - sets the matrix type to "elemental" during a call to MatSetFromOptions()
13025cc86fc1SJed Brown - -mat_elemental_grid_height - sets Grid Height for 2D cyclic ordering of internal matrix
1303ed36708cSHong Zhang 
1304ed36708cSHong Zhang   Level: beginner
1305ed36708cSHong Zhang 
13065cb544a0SHong Zhang .seealso: MATDENSE
1307ed36708cSHong Zhang M*/
13084a29722dSXuan Zhou 
13098cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Elemental(Mat A)
1310db31f6deSJed Brown {
1311db31f6deSJed Brown   Mat_Elemental      *a;
1312db31f6deSJed Brown   PetscErrorCode     ierr;
13135682a260SJack Poulson   PetscBool          flg,flg1;
13145e9f5b67SHong Zhang   Mat_Elemental_Grid *commgrid;
13155e9f5b67SHong Zhang   MPI_Comm           icomm;
13165682a260SJack Poulson   PetscInt           optv1;
1317db31f6deSJed Brown 
1318db31f6deSJed Brown   PetscFunctionBegin;
131940d92e34SHong Zhang   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
132040d92e34SHong Zhang   A->insertmode = NOT_SET_VALUES;
1321db31f6deSJed Brown 
1322b00a9115SJed Brown   ierr = PetscNewLog(A,&a);CHKERRQ(ierr);
1323db31f6deSJed Brown   A->data = (void*)a;
1324db31f6deSJed Brown 
1325db31f6deSJed Brown   /* Set up the elemental matrix */
1326e8146892SSatish Balay   El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A));
13275e9f5b67SHong Zhang 
13285e9f5b67SHong Zhang   /* Grid needs to be shared between multiple Mats on the same communicator, implement by attribute caching on the MPI_Comm */
13295e9f5b67SHong Zhang   if (Petsc_Elemental_keyval == MPI_KEYVAL_INVALID) {
133012801b39SBarry Smith     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Elemental_keyval,(void*)0);CHKERRQ(ierr);
13315e9f5b67SHong Zhang   }
13320c18141cSBarry Smith   ierr = PetscCommDuplicate(cxxcomm.comm,&icomm,NULL);CHKERRQ(ierr);
133347435625SJed Brown   ierr = MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr);
13345e9f5b67SHong Zhang   if (!flg) {
1335b00a9115SJed Brown     ierr = PetscNewLog(A,&commgrid);CHKERRQ(ierr);
13365cb544a0SHong Zhang 
1337ce94432eSBarry Smith     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"Elemental Options","Mat");CHKERRQ(ierr);
1338e8146892SSatish Balay     /* displayed default grid sizes (CommSize,1) are set by us arbitrarily until El::Grid() is called */
1339e8146892SSatish Balay     ierr = PetscOptionsInt("-mat_elemental_grid_height","Grid Height","None",El::mpi::Size(cxxcomm),&optv1,&flg1);CHKERRQ(ierr);
13405682a260SJack Poulson     if (flg1) {
1341*d8304050SJose 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));
1342e8146892SSatish Balay       commgrid->grid = new El::Grid(cxxcomm,optv1); /* use user-provided grid height */
13432ef0cf24SXuan Zhou     } else {
1344e8146892SSatish Balay       commgrid->grid = new El::Grid(cxxcomm); /* use Elemental default grid sizes */
1345da0640a4SHong Zhang       /* printf("new commgrid->grid = %p\n",commgrid->grid);  -- memory leak revealed by valgrind? */
1346ed667823SXuan Zhou     }
13475e9f5b67SHong Zhang     commgrid->grid_refct = 1;
134847435625SJed Brown     ierr = MPI_Comm_set_attr(icomm,Petsc_Elemental_keyval,(void*)commgrid);CHKERRQ(ierr);
1349ea394475SSatish Balay 
1350ea394475SSatish Balay     a->pivoting    = 1;
1351ea394475SSatish Balay     ierr = PetscOptionsInt("-mat_elemental_pivoting","Pivoting","None",a->pivoting,&a->pivoting,NULL);CHKERRQ(ierr);
1352ea394475SSatish Balay 
13532a808120SBarry Smith     ierr = PetscOptionsEnd();CHKERRQ(ierr);
13545e9f5b67SHong Zhang   } else {
13555e9f5b67SHong Zhang     commgrid->grid_refct++;
13565e9f5b67SHong Zhang   }
13575e9f5b67SHong Zhang   ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr);
13585e9f5b67SHong Zhang   a->grid        = commgrid->grid;
1359e8146892SSatish Balay   a->emat        = new El::DistMatrix<PetscElemScalar>(*a->grid);
136032d7a744SHong Zhang   a->roworiented = PETSC_TRUE;
1361db31f6deSJed Brown 
1362bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",MatGetOwnershipIS_Elemental);CHKERRQ(ierr);
1363db31f6deSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)A,MATELEMENTAL);CHKERRQ(ierr);
1364db31f6deSJed Brown   PetscFunctionReturn(0);
1365db31f6deSJed Brown }
1366