xref: /petsc/src/mat/impls/elemental/matelem.cxx (revision 071fcb05f2a6aea8aef2c2090580530b9e9df77e)
1db31f6deSJed Brown #include <../src/mat/impls/elemental/matelemimpl.h> /*I "petscmat.h" I*/
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 /*@C
10db31f6deSJed Brown    PetscElementalInitializePackage - Initialize Elemental package
11db31f6deSJed Brown 
12db31f6deSJed Brown    Logically Collective
13db31f6deSJed Brown 
14db31f6deSJed Brown    Level: developer
15db31f6deSJed Brown 
16db31f6deSJed Brown .seealso: MATELEMENTAL, PetscElementalFinalizePackage()
17db31f6deSJed Brown @*/
18607a6623SBarry Smith PetscErrorCode PetscElementalInitializePackage(void)
19db31f6deSJed Brown {
20db31f6deSJed Brown   PetscErrorCode ierr;
21db31f6deSJed Brown 
22db31f6deSJed Brown   PetscFunctionBegin;
23e8146892SSatish Balay   if (El::Initialized()) PetscFunctionReturn(0);
24e05a9d59SSatish Balay   El::Initialize();   /* called by the 1st call of MatCreate_Elemental */
25db31f6deSJed Brown   ierr = PetscRegisterFinalize(PetscElementalFinalizePackage);CHKERRQ(ierr);
26db31f6deSJed Brown   PetscFunctionReturn(0);
27db31f6deSJed Brown }
28db31f6deSJed Brown 
29db31f6deSJed Brown /*@C
30db31f6deSJed Brown    PetscElementalFinalizePackage - Finalize Elemental package
31db31f6deSJed Brown 
32db31f6deSJed Brown    Logically Collective
33db31f6deSJed Brown 
34db31f6deSJed Brown    Level: developer
35db31f6deSJed Brown 
36db31f6deSJed Brown .seealso: MATELEMENTAL, PetscElementalInitializePackage()
37db31f6deSJed Brown @*/
38db31f6deSJed Brown PetscErrorCode PetscElementalFinalizePackage(void)
39db31f6deSJed Brown {
40db31f6deSJed Brown   PetscFunctionBegin;
41e8146892SSatish Balay   El::Finalize();  /* called by PetscFinalize() */
42db31f6deSJed Brown   PetscFunctionReturn(0);
43db31f6deSJed Brown }
44db31f6deSJed Brown 
45db31f6deSJed Brown static PetscErrorCode MatView_Elemental(Mat A,PetscViewer viewer)
46db31f6deSJed Brown {
47db31f6deSJed Brown   PetscErrorCode ierr;
48db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
49db31f6deSJed Brown   PetscBool      iascii;
50db31f6deSJed Brown 
51db31f6deSJed Brown   PetscFunctionBegin;
52db31f6deSJed Brown   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
53db31f6deSJed Brown   if (iascii) {
54db31f6deSJed Brown     PetscViewerFormat format;
55db31f6deSJed Brown     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
56db31f6deSJed Brown     if (format == PETSC_VIEWER_ASCII_INFO) {
5779673f7bSHong Zhang       /* call elemental viewing function */
582d8adcc7SHong Zhang       ierr = PetscViewerASCIIPrintf(viewer,"Elemental run parameters:\n");CHKERRQ(ierr);
59ed667823SXuan Zhou       ierr = PetscViewerASCIIPrintf(viewer,"  allocated entries=%d\n",(*a->emat).AllocatedMemory());CHKERRQ(ierr);
60ed667823SXuan Zhou       ierr = PetscViewerASCIIPrintf(viewer,"  grid height=%d, grid width=%d\n",(*a->emat).Grid().Height(),(*a->emat).Grid().Width());CHKERRQ(ierr);
614fe7bbcaSHong Zhang       if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
6279673f7bSHong Zhang         /* call elemental viewing function */
63ce94432eSBarry Smith         ierr = PetscPrintf(PetscObjectComm((PetscObject)viewer),"test matview_elemental 2\n");CHKERRQ(ierr);
644fe7bbcaSHong Zhang       }
6579673f7bSHong Zhang 
66db31f6deSJed Brown     } else if (format == PETSC_VIEWER_DEFAULT) {
67db31f6deSJed Brown       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
68e8146892SSatish Balay       El::Print( *a->emat, "Elemental matrix (cyclic ordering)" );
69db31f6deSJed Brown       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
70834d3fecSHong Zhang       if (A->factortype == MAT_FACTOR_NONE){
7161119200SXuan Zhou         Mat Adense;
72ce94432eSBarry Smith         ierr = PetscPrintf(PetscObjectComm((PetscObject)viewer),"Elemental matrix (explicit ordering)\n");CHKERRQ(ierr);
7361119200SXuan Zhou         ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense);CHKERRQ(ierr);
7461119200SXuan Zhou         ierr = MatView(Adense,viewer);CHKERRQ(ierr);
7561119200SXuan Zhou         ierr = MatDestroy(&Adense);CHKERRQ(ierr);
76834d3fecSHong Zhang       }
77ce94432eSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Format");
78d2daa67eSHong Zhang   } else {
795cb544a0SHong Zhang     /* convert to dense format and call MatView() */
8061119200SXuan Zhou     Mat Adense;
81ce94432eSBarry Smith     ierr = PetscPrintf(PetscObjectComm((PetscObject)viewer),"Elemental matrix (explicit ordering)\n");CHKERRQ(ierr);
8261119200SXuan Zhou     ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense);CHKERRQ(ierr);
8361119200SXuan Zhou     ierr = MatView(Adense,viewer);CHKERRQ(ierr);
8461119200SXuan Zhou     ierr = MatDestroy(&Adense);CHKERRQ(ierr);
85d2daa67eSHong Zhang   }
86db31f6deSJed Brown   PetscFunctionReturn(0);
87db31f6deSJed Brown }
88db31f6deSJed Brown 
8915767789SHong Zhang static PetscErrorCode MatGetInfo_Elemental(Mat A,MatInfoType flag,MatInfo *info)
90180a43e4SHong Zhang {
9115767789SHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data;
9215767789SHong Zhang 
93180a43e4SHong Zhang   PetscFunctionBegin;
945cb544a0SHong Zhang   info->block_size = 1.0;
9515767789SHong Zhang 
9615767789SHong Zhang   if (flag == MAT_LOCAL) {
9715767789SHong Zhang     info->nz_allocated   = (double)(*a->emat).AllocatedMemory(); /* locally allocated */
9815767789SHong Zhang     info->nz_used        = info->nz_allocated;
9915767789SHong Zhang   } else if (flag == MAT_GLOBAL_MAX) {
100b2566f29SBarry Smith     //ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)matin));CHKERRQ(ierr);
10115767789SHong Zhang     /* see MatGetInfo_MPIAIJ() for getting global info->nz_allocated! */
10215767789SHong Zhang     //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_MAX not written yet");
10315767789SHong Zhang   } else if (flag == MAT_GLOBAL_SUM) {
10415767789SHong Zhang     //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_SUM not written yet");
10515767789SHong Zhang     info->nz_allocated   = (double)(*a->emat).AllocatedMemory(); /* locally allocated */
10615767789SHong Zhang     info->nz_used        = info->nz_allocated; /* assume Elemental does accurate allocation */
107b2566f29SBarry Smith     //ierr = MPIU_Allreduce(isend,irecv,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
10815767789SHong Zhang     //PetscPrintf(PETSC_COMM_SELF,"    ... [%d] locally allocated %g\n",rank,info->nz_allocated);
10915767789SHong Zhang   }
11015767789SHong Zhang 
11115767789SHong Zhang   info->nz_unneeded       = 0.0;
11215767789SHong Zhang   info->assemblies        = (double)A->num_ass;
11315767789SHong Zhang   info->mallocs           = 0;
11415767789SHong Zhang   info->memory            = ((PetscObject)A)->mem;
11515767789SHong Zhang   info->fill_ratio_given  = 0; /* determined by Elemental */
11615767789SHong Zhang   info->fill_ratio_needed = 0;
11715767789SHong Zhang   info->factor_mallocs    = 0;
118180a43e4SHong Zhang   PetscFunctionReturn(0);
119180a43e4SHong Zhang }
120180a43e4SHong Zhang 
12132d7a744SHong Zhang PetscErrorCode MatSetOption_Elemental(Mat A,MatOption op,PetscBool flg)
12232d7a744SHong Zhang {
12332d7a744SHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data;
12432d7a744SHong Zhang 
12532d7a744SHong Zhang   PetscFunctionBegin;
12632d7a744SHong Zhang   switch (op) {
12732d7a744SHong Zhang   case MAT_NEW_NONZERO_LOCATIONS:
12832d7a744SHong Zhang   case MAT_NEW_NONZERO_LOCATION_ERR:
12932d7a744SHong Zhang   case MAT_NEW_NONZERO_ALLOCATION_ERR:
130891a0571SHong Zhang   case MAT_SYMMETRIC:
131*071fcb05SBarry Smith   case MAT_SORTED_FULL:
132891a0571SHong Zhang     break;
13332d7a744SHong Zhang   case MAT_ROW_ORIENTED:
13432d7a744SHong Zhang     a->roworiented = flg;
13532d7a744SHong Zhang     break;
13632d7a744SHong Zhang   default:
13732d7a744SHong Zhang     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %s",MatOptions[op]);
13832d7a744SHong Zhang   }
13932d7a744SHong Zhang   PetscFunctionReturn(0);
14032d7a744SHong Zhang }
14132d7a744SHong Zhang 
142e6dea9dbSXuan Zhou static PetscErrorCode MatSetValues_Elemental(Mat A,PetscInt nr,const PetscInt *rows,PetscInt nc,const PetscInt *cols,const PetscScalar *vals,InsertMode imode)
143db31f6deSJed Brown {
144db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
145fbbcb730SJack Poulson   PetscInt       i,j,rrank,ridx,crank,cidx,erow,ecol,numQueues=0;
146db31f6deSJed Brown 
147db31f6deSJed Brown   PetscFunctionBegin;
148fbbcb730SJack Poulson   // TODO: Initialize matrix to all zeros?
149fbbcb730SJack Poulson 
150fbbcb730SJack Poulson   // Count the number of queues from this process
15132d7a744SHong Zhang   if (a->roworiented) {
152db31f6deSJed Brown     for (i=0; i<nr; i++) {
153db31f6deSJed Brown       if (rows[i] < 0) continue;
154db31f6deSJed Brown       P2RO(A,0,rows[i],&rrank,&ridx);
155db31f6deSJed Brown       RO2E(A,0,rrank,ridx,&erow);
156ce94432eSBarry Smith       if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect row translation");
157db31f6deSJed Brown       for (j=0; j<nc; j++) {
158db31f6deSJed Brown         if (cols[j] < 0) continue;
159db31f6deSJed Brown         P2RO(A,1,cols[j],&crank,&cidx);
160db31f6deSJed Brown         RO2E(A,1,crank,cidx,&ecol);
161ce94432eSBarry Smith         if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect col translation");
162fbbcb730SJack Poulson         if (!a->emat->IsLocal(erow,ecol) ){ /* off-proc entry */
163fbbcb730SJack Poulson           /* printf("Will later remotely update (%d,%d)\n",erow,ecol); */
164aae2c449SHong Zhang           if (imode != ADD_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported");
165fbbcb730SJack Poulson           ++numQueues;
166aae2c449SHong Zhang           continue;
167ed36708cSHong Zhang         }
168fbbcb730SJack Poulson         /* printf("Locally updating (%d,%d)\n",erow,ecol); */
169db31f6deSJed Brown         switch (imode) {
170fbbcb730SJack Poulson         case INSERT_VALUES: a->emat->Set(erow,ecol,(PetscElemScalar)vals[i*nc+j]); break;
171fbbcb730SJack Poulson         case ADD_VALUES: a->emat->Update(erow,ecol,(PetscElemScalar)vals[i*nc+j]); break;
172ce94432eSBarry Smith         default: SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode);
173db31f6deSJed Brown         }
174db31f6deSJed Brown       }
175db31f6deSJed Brown     }
176fbbcb730SJack Poulson 
177fbbcb730SJack Poulson     /* printf("numQueues=%d\n",numQueues); */
178fbbcb730SJack Poulson     a->emat->Reserve( numQueues );
179fbbcb730SJack Poulson     for (i=0; i<nr; i++) {
180fbbcb730SJack Poulson       if (rows[i] < 0) continue;
181fbbcb730SJack Poulson       P2RO(A,0,rows[i],&rrank,&ridx);
182fbbcb730SJack Poulson       RO2E(A,0,rrank,ridx,&erow);
183fbbcb730SJack Poulson       for (j=0; j<nc; j++) {
184fbbcb730SJack Poulson         if (cols[j] < 0) continue;
185fbbcb730SJack Poulson         P2RO(A,1,cols[j],&crank,&cidx);
186fbbcb730SJack Poulson         RO2E(A,1,crank,cidx,&ecol);
187fbbcb730SJack Poulson         if ( !a->emat->IsLocal(erow,ecol) ) { /*off-proc entry*/
188fbbcb730SJack Poulson           /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */
189fbbcb730SJack Poulson           a->emat->QueueUpdate( erow, ecol, vals[i*nc+j] );
190fbbcb730SJack Poulson         }
191fbbcb730SJack Poulson       }
192fbbcb730SJack Poulson     }
19332d7a744SHong Zhang   } else { /* columnoriented */
19432d7a744SHong Zhang     for (j=0; j<nc; j++) {
19532d7a744SHong Zhang       if (cols[j] < 0) continue;
19632d7a744SHong Zhang       P2RO(A,1,cols[j],&crank,&cidx);
19732d7a744SHong Zhang       RO2E(A,1,crank,cidx,&ecol);
19832d7a744SHong Zhang       if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect col translation");
19932d7a744SHong Zhang       for (i=0; i<nr; i++) {
20032d7a744SHong Zhang         if (rows[i] < 0) continue;
20132d7a744SHong Zhang         P2RO(A,0,rows[i],&rrank,&ridx);
20232d7a744SHong Zhang         RO2E(A,0,rrank,ridx,&erow);
20332d7a744SHong Zhang         if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect row translation");
20432d7a744SHong Zhang         if (!a->emat->IsLocal(erow,ecol) ){ /* off-proc entry */
20532d7a744SHong Zhang           /* printf("Will later remotely update (%d,%d)\n",erow,ecol); */
20632d7a744SHong Zhang           if (imode != ADD_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported");
20732d7a744SHong Zhang           ++numQueues;
20832d7a744SHong Zhang           continue;
20932d7a744SHong Zhang         }
21032d7a744SHong Zhang         /* printf("Locally updating (%d,%d)\n",erow,ecol); */
21132d7a744SHong Zhang         switch (imode) {
21232d7a744SHong Zhang         case INSERT_VALUES: a->emat->Set(erow,ecol,(PetscElemScalar)vals[i+j*nr]); break;
21332d7a744SHong Zhang         case ADD_VALUES: a->emat->Update(erow,ecol,(PetscElemScalar)vals[i+j*nr]); break;
21432d7a744SHong Zhang         default: SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode);
21532d7a744SHong Zhang         }
21632d7a744SHong Zhang       }
21732d7a744SHong Zhang     }
21832d7a744SHong Zhang 
21932d7a744SHong Zhang     /* printf("numQueues=%d\n",numQueues); */
22032d7a744SHong Zhang     a->emat->Reserve( numQueues );
22132d7a744SHong Zhang     for (j=0; j<nc; j++) {
22232d7a744SHong Zhang       if (cols[j] < 0) continue;
22332d7a744SHong Zhang       P2RO(A,1,cols[j],&crank,&cidx);
22432d7a744SHong Zhang       RO2E(A,1,crank,cidx,&ecol);
22532d7a744SHong Zhang 
22632d7a744SHong Zhang       for (i=0; i<nr; i++) {
22732d7a744SHong Zhang         if (rows[i] < 0) continue;
22832d7a744SHong Zhang         P2RO(A,0,rows[i],&rrank,&ridx);
22932d7a744SHong Zhang         RO2E(A,0,rrank,ridx,&erow);
23032d7a744SHong Zhang         if ( !a->emat->IsLocal(erow,ecol) ) { /*off-proc entry*/
23132d7a744SHong Zhang           /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */
23232d7a744SHong Zhang           a->emat->QueueUpdate( erow, ecol, vals[i+j*nr] );
23332d7a744SHong Zhang         }
23432d7a744SHong Zhang       }
23532d7a744SHong Zhang     }
23632d7a744SHong Zhang   }
237db31f6deSJed Brown   PetscFunctionReturn(0);
238db31f6deSJed Brown }
239db31f6deSJed Brown 
240db31f6deSJed Brown static PetscErrorCode MatMult_Elemental(Mat A,Vec X,Vec Y)
241db31f6deSJed Brown {
242db31f6deSJed Brown   Mat_Elemental         *a = (Mat_Elemental*)A->data;
243db31f6deSJed Brown   PetscErrorCode        ierr;
244e6dea9dbSXuan Zhou   const PetscElemScalar *x;
245e6dea9dbSXuan Zhou   PetscElemScalar       *y;
246df311e6cSXuan Zhou   PetscElemScalar       one = 1,zero = 0;
247db31f6deSJed Brown 
248db31f6deSJed Brown   PetscFunctionBegin;
249e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
250e6dea9dbSXuan Zhou   ierr = VecGetArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
251db31f6deSJed Brown   { /* Scoping so that constructor is called before pointer is returned */
252e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ye;
2530c18141cSBarry Smith     xe.LockedAttach(A->cmap->N,1,*a->grid,0,0,x,A->cmap->n);
2540c18141cSBarry Smith     ye.Attach(A->rmap->N,1,*a->grid,0,0,y,A->rmap->n);
255e8146892SSatish Balay     El::Gemv(El::NORMAL,one,*a->emat,xe,zero,ye);
256db31f6deSJed Brown   }
257e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
258e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
259db31f6deSJed Brown   PetscFunctionReturn(0);
260db31f6deSJed Brown }
261db31f6deSJed Brown 
2629426833fSXuan Zhou static PetscErrorCode MatMultTranspose_Elemental(Mat A,Vec X,Vec Y)
2639426833fSXuan Zhou {
2649426833fSXuan Zhou   Mat_Elemental         *a = (Mat_Elemental*)A->data;
2659426833fSXuan Zhou   PetscErrorCode        ierr;
266df311e6cSXuan Zhou   const PetscElemScalar *x;
267df311e6cSXuan Zhou   PetscElemScalar       *y;
268e6dea9dbSXuan Zhou   PetscElemScalar       one = 1,zero = 0;
2699426833fSXuan Zhou 
2709426833fSXuan Zhou   PetscFunctionBegin;
271e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
272e6dea9dbSXuan Zhou   ierr = VecGetArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
2739426833fSXuan Zhou   { /* Scoping so that constructor is called before pointer is returned */
274e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ye;
2750c18141cSBarry Smith     xe.LockedAttach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n);
2760c18141cSBarry Smith     ye.Attach(A->cmap->N,1,*a->grid,0,0,y,A->cmap->n);
277e8146892SSatish Balay     El::Gemv(El::TRANSPOSE,one,*a->emat,xe,zero,ye);
2789426833fSXuan Zhou   }
279e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
280e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
2819426833fSXuan Zhou   PetscFunctionReturn(0);
2829426833fSXuan Zhou }
2839426833fSXuan Zhou 
284db31f6deSJed Brown static PetscErrorCode MatMultAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z)
285db31f6deSJed Brown {
286db31f6deSJed Brown   Mat_Elemental         *a = (Mat_Elemental*)A->data;
287db31f6deSJed Brown   PetscErrorCode        ierr;
288df311e6cSXuan Zhou   const PetscElemScalar *x;
289df311e6cSXuan Zhou   PetscElemScalar       *z;
290e6dea9dbSXuan Zhou   PetscElemScalar       one = 1;
291db31f6deSJed Brown 
292db31f6deSJed Brown   PetscFunctionBegin;
293db31f6deSJed Brown   if (Y != Z) {ierr = VecCopy(Y,Z);CHKERRQ(ierr);}
294e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
295e6dea9dbSXuan Zhou   ierr = VecGetArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
296db31f6deSJed Brown   { /* Scoping so that constructor is called before pointer is returned */
297e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ze;
2980c18141cSBarry Smith     xe.LockedAttach(A->cmap->N,1,*a->grid,0,0,x,A->cmap->n);
2990c18141cSBarry Smith     ze.Attach(A->rmap->N,1,*a->grid,0,0,z,A->rmap->n);
300e8146892SSatish Balay     El::Gemv(El::NORMAL,one,*a->emat,xe,one,ze);
301db31f6deSJed Brown   }
302e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
303e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
304db31f6deSJed Brown   PetscFunctionReturn(0);
305db31f6deSJed Brown }
306db31f6deSJed Brown 
307e883f9d5SXuan Zhou static PetscErrorCode MatMultTransposeAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z)
308e883f9d5SXuan Zhou {
309e883f9d5SXuan Zhou   Mat_Elemental         *a = (Mat_Elemental*)A->data;
310e883f9d5SXuan Zhou   PetscErrorCode        ierr;
311df311e6cSXuan Zhou   const PetscElemScalar *x;
312df311e6cSXuan Zhou   PetscElemScalar       *z;
313e6dea9dbSXuan Zhou   PetscElemScalar       one = 1;
314e883f9d5SXuan Zhou 
315e883f9d5SXuan Zhou   PetscFunctionBegin;
316e883f9d5SXuan Zhou   if (Y != Z) {ierr = VecCopy(Y,Z);CHKERRQ(ierr);}
317e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
318e6dea9dbSXuan Zhou   ierr = VecGetArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
319e883f9d5SXuan Zhou   { /* Scoping so that constructor is called before pointer is returned */
320e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ze;
3210c18141cSBarry Smith     xe.LockedAttach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n);
3220c18141cSBarry Smith     ze.Attach(A->cmap->N,1,*a->grid,0,0,z,A->cmap->n);
323e8146892SSatish Balay     El::Gemv(El::TRANSPOSE,one,*a->emat,xe,one,ze);
324e883f9d5SXuan Zhou   }
325e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
326e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
327e883f9d5SXuan Zhou   PetscFunctionReturn(0);
328e883f9d5SXuan Zhou }
329e883f9d5SXuan Zhou 
3309a9e8502SHong Zhang static PetscErrorCode MatMatMultNumeric_Elemental(Mat A,Mat B,Mat C)
331c1d1b975SXuan Zhou {
332c1d1b975SXuan Zhou   Mat_Elemental    *a = (Mat_Elemental*)A->data;
333c1d1b975SXuan Zhou   Mat_Elemental    *b = (Mat_Elemental*)B->data;
3349a9e8502SHong Zhang   Mat_Elemental    *c = (Mat_Elemental*)C->data;
335e6dea9dbSXuan Zhou   PetscElemScalar  one = 1,zero = 0;
336c1d1b975SXuan Zhou 
337c1d1b975SXuan Zhou   PetscFunctionBegin;
338aae2c449SHong Zhang   { /* Scoping so that constructor is called before pointer is returned */
339e8146892SSatish Balay     El::Gemm(El::NORMAL,El::NORMAL,one,*a->emat,*b->emat,zero,*c->emat);
340aae2c449SHong Zhang   }
3419a9e8502SHong Zhang   C->assembled = PETSC_TRUE;
3429a9e8502SHong Zhang   PetscFunctionReturn(0);
3439a9e8502SHong Zhang }
3449a9e8502SHong Zhang 
3459a9e8502SHong Zhang static PetscErrorCode MatMatMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat *C)
3469a9e8502SHong Zhang {
3479a9e8502SHong Zhang   PetscErrorCode ierr;
3489a9e8502SHong Zhang   Mat            Ce;
349ce94432eSBarry Smith   MPI_Comm       comm;
3509a9e8502SHong Zhang 
3519a9e8502SHong Zhang   PetscFunctionBegin;
352ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
3539a9e8502SHong Zhang   ierr = MatCreate(comm,&Ce);CHKERRQ(ierr);
3549a9e8502SHong Zhang   ierr = MatSetSizes(Ce,A->rmap->n,B->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
3559a9e8502SHong Zhang   ierr = MatSetType(Ce,MATELEMENTAL);CHKERRQ(ierr);
3569a9e8502SHong Zhang   ierr = MatSetUp(Ce);CHKERRQ(ierr);
3579a9e8502SHong Zhang   *C = Ce;
3589a9e8502SHong Zhang   PetscFunctionReturn(0);
3599a9e8502SHong Zhang }
3609a9e8502SHong Zhang 
3619a9e8502SHong Zhang static PetscErrorCode MatMatMult_Elemental(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
3629a9e8502SHong Zhang {
3639a9e8502SHong Zhang   PetscErrorCode ierr;
3649a9e8502SHong Zhang 
3659a9e8502SHong Zhang   PetscFunctionBegin;
3669a9e8502SHong Zhang   if (scall == MAT_INITIAL_MATRIX){
3673ff4c91cSHong Zhang     ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
3689a9e8502SHong Zhang     ierr = MatMatMultSymbolic_Elemental(A,B,1.0,C);CHKERRQ(ierr);
3693ff4c91cSHong Zhang     ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
3709a9e8502SHong Zhang   }
3713ff4c91cSHong Zhang   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
3729a9e8502SHong Zhang   ierr = MatMatMultNumeric_Elemental(A,B,*C);CHKERRQ(ierr);
3733ff4c91cSHong Zhang   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
374c1d1b975SXuan Zhou   PetscFunctionReturn(0);
375c1d1b975SXuan Zhou }
376c1d1b975SXuan Zhou 
377df311e6cSXuan Zhou static PetscErrorCode MatMatTransposeMultNumeric_Elemental(Mat A,Mat B,Mat C)
378df311e6cSXuan Zhou {
379df311e6cSXuan Zhou   Mat_Elemental      *a = (Mat_Elemental*)A->data;
380df311e6cSXuan Zhou   Mat_Elemental      *b = (Mat_Elemental*)B->data;
381df311e6cSXuan Zhou   Mat_Elemental      *c = (Mat_Elemental*)C->data;
382e6dea9dbSXuan Zhou   PetscElemScalar    one = 1,zero = 0;
383df311e6cSXuan Zhou 
384df311e6cSXuan Zhou   PetscFunctionBegin;
385df311e6cSXuan Zhou   { /* Scoping so that constructor is called before pointer is returned */
386e8146892SSatish Balay     El::Gemm(El::NORMAL,El::TRANSPOSE,one,*a->emat,*b->emat,zero,*c->emat);
387df311e6cSXuan Zhou   }
388df311e6cSXuan Zhou   C->assembled = PETSC_TRUE;
389df311e6cSXuan Zhou   PetscFunctionReturn(0);
390df311e6cSXuan Zhou }
391df311e6cSXuan Zhou 
392df311e6cSXuan Zhou static PetscErrorCode MatMatTransposeMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat *C)
393df311e6cSXuan Zhou {
394df311e6cSXuan Zhou   PetscErrorCode ierr;
395df311e6cSXuan Zhou   Mat            Ce;
396ce94432eSBarry Smith   MPI_Comm       comm;
397df311e6cSXuan Zhou 
398df311e6cSXuan Zhou   PetscFunctionBegin;
399ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
400df311e6cSXuan Zhou   ierr = MatCreate(comm,&Ce);CHKERRQ(ierr);
401df311e6cSXuan Zhou   ierr = MatSetSizes(Ce,A->rmap->n,B->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
402df311e6cSXuan Zhou   ierr = MatSetType(Ce,MATELEMENTAL);CHKERRQ(ierr);
403df311e6cSXuan Zhou   ierr = MatSetUp(Ce);CHKERRQ(ierr);
404df311e6cSXuan Zhou   *C = Ce;
405df311e6cSXuan Zhou   PetscFunctionReturn(0);
406df311e6cSXuan Zhou }
407df311e6cSXuan Zhou 
408df311e6cSXuan Zhou static PetscErrorCode MatMatTransposeMult_Elemental(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
409df311e6cSXuan Zhou {
410df311e6cSXuan Zhou   PetscErrorCode ierr;
411df311e6cSXuan Zhou 
412df311e6cSXuan Zhou   PetscFunctionBegin;
413df311e6cSXuan Zhou   if (scall == MAT_INITIAL_MATRIX){
414df311e6cSXuan Zhou     ierr = PetscLogEventBegin(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr);
415df311e6cSXuan Zhou     ierr = MatMatMultSymbolic_Elemental(A,B,1.0,C);CHKERRQ(ierr);
416df311e6cSXuan Zhou     ierr = PetscLogEventEnd(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr);
417df311e6cSXuan Zhou   }
418df311e6cSXuan Zhou   ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
419df311e6cSXuan Zhou   ierr = MatMatTransposeMultNumeric_Elemental(A,B,*C);CHKERRQ(ierr);
420df311e6cSXuan Zhou   ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
421df311e6cSXuan Zhou   PetscFunctionReturn(0);
422df311e6cSXuan Zhou }
423df311e6cSXuan Zhou 
424a9d89745SXuan Zhou static PetscErrorCode MatGetDiagonal_Elemental(Mat A,Vec D)
42561119200SXuan Zhou {
426a9d89745SXuan Zhou   PetscInt        i,nrows,ncols,nD,rrank,ridx,crank,cidx;
427a9d89745SXuan Zhou   Mat_Elemental   *a = (Mat_Elemental*)A->data;
42861119200SXuan Zhou   PetscErrorCode  ierr;
429a9d89745SXuan Zhou   PetscElemScalar v;
430ce94432eSBarry Smith   MPI_Comm        comm;
43161119200SXuan Zhou 
43261119200SXuan Zhou   PetscFunctionBegin;
433ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
434a9d89745SXuan Zhou   ierr = MatGetSize(A,&nrows,&ncols);CHKERRQ(ierr);
435a9d89745SXuan Zhou   nD = nrows>ncols ? ncols : nrows;
436a9d89745SXuan Zhou   for (i=0; i<nD; i++) {
437a9d89745SXuan Zhou     PetscInt erow,ecol;
438a9d89745SXuan Zhou     P2RO(A,0,i,&rrank,&ridx);
439a9d89745SXuan Zhou     RO2E(A,0,rrank,ridx,&erow);
440a9d89745SXuan Zhou     if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
441a9d89745SXuan Zhou     P2RO(A,1,i,&crank,&cidx);
442a9d89745SXuan Zhou     RO2E(A,1,crank,cidx,&ecol);
443a9d89745SXuan Zhou     if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
444a9d89745SXuan Zhou     v = a->emat->Get(erow,ecol);
4457c8b904fSSatish Balay     ierr = VecSetValues(D,1,&i,(PetscScalar*)&v,INSERT_VALUES);CHKERRQ(ierr);
446ade3cc5eSXuan Zhou   }
447a9d89745SXuan Zhou   ierr = VecAssemblyBegin(D);CHKERRQ(ierr);
448a9d89745SXuan Zhou   ierr = VecAssemblyEnd(D);CHKERRQ(ierr);
44961119200SXuan Zhou   PetscFunctionReturn(0);
45061119200SXuan Zhou }
45161119200SXuan Zhou 
452ade3cc5eSXuan Zhou static PetscErrorCode MatDiagonalScale_Elemental(Mat X,Vec L,Vec R)
453ade3cc5eSXuan Zhou {
454ade3cc5eSXuan Zhou   Mat_Elemental         *x = (Mat_Elemental*)X->data;
455ade3cc5eSXuan Zhou   const PetscElemScalar *d;
456ade3cc5eSXuan Zhou   PetscErrorCode        ierr;
457ade3cc5eSXuan Zhou 
458ade3cc5eSXuan Zhou   PetscFunctionBegin;
4599065cd98SJed Brown   if (R) {
460ade3cc5eSXuan Zhou     ierr = VecGetArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr);
461e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de;
4620c18141cSBarry Smith     de.LockedAttach(X->cmap->N,1,*x->grid,0,0,d,X->cmap->n);
463e8146892SSatish Balay     El::DiagonalScale(El::RIGHT,El::NORMAL,de,*x->emat);
464ade3cc5eSXuan Zhou     ierr = VecRestoreArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr);
4659065cd98SJed Brown   }
4669065cd98SJed Brown   if (L) {
467ade3cc5eSXuan Zhou     ierr = VecGetArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr);
468e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de;
4690c18141cSBarry Smith     de.LockedAttach(X->rmap->N,1,*x->grid,0,0,d,X->rmap->n);
470e8146892SSatish Balay     El::DiagonalScale(El::LEFT,El::NORMAL,de,*x->emat);
471ade3cc5eSXuan Zhou     ierr = VecRestoreArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr);
472ade3cc5eSXuan Zhou   }
473ade3cc5eSXuan Zhou   PetscFunctionReturn(0);
474ade3cc5eSXuan Zhou }
475ade3cc5eSXuan Zhou 
47634fa46e1SFrancesco Ballarin static PetscErrorCode MatMissingDiagonal_Elemental(Mat A,PetscBool *missing,PetscInt *d)
47734fa46e1SFrancesco Ballarin {
47834fa46e1SFrancesco Ballarin   PetscFunctionBegin;
47934fa46e1SFrancesco Ballarin   *missing = PETSC_FALSE;
48034fa46e1SFrancesco Ballarin   PetscFunctionReturn(0);
48134fa46e1SFrancesco Ballarin }
48234fa46e1SFrancesco Ballarin 
483e6dea9dbSXuan Zhou static PetscErrorCode MatScale_Elemental(Mat X,PetscScalar a)
48465b78793SXuan Zhou {
48565b78793SXuan Zhou   Mat_Elemental  *x = (Mat_Elemental*)X->data;
48665b78793SXuan Zhou 
48765b78793SXuan Zhou   PetscFunctionBegin;
488e8146892SSatish Balay   El::Scale((PetscElemScalar)a,*x->emat);
48965b78793SXuan Zhou   PetscFunctionReturn(0);
49065b78793SXuan Zhou }
49165b78793SXuan Zhou 
492f82baa17SHong Zhang /*
493f82baa17SHong Zhang   MatAXPY - Computes Y = a*X + Y.
494f82baa17SHong Zhang */
495e6dea9dbSXuan Zhou static PetscErrorCode MatAXPY_Elemental(Mat Y,PetscScalar a,Mat X,MatStructure str)
496e09a3074SHong Zhang {
497e09a3074SHong Zhang   Mat_Elemental  *x = (Mat_Elemental*)X->data;
498e09a3074SHong Zhang   Mat_Elemental  *y = (Mat_Elemental*)Y->data;
49968446cf8SJed Brown   PetscErrorCode ierr;
500e09a3074SHong Zhang 
501e09a3074SHong Zhang   PetscFunctionBegin;
502e8146892SSatish Balay   El::Axpy((PetscElemScalar)a,*x->emat,*y->emat);
50321f6c9c4SJed Brown   ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
504e09a3074SHong Zhang   PetscFunctionReturn(0);
505e09a3074SHong Zhang }
506e09a3074SHong Zhang 
507d6223691SXuan Zhou static PetscErrorCode MatCopy_Elemental(Mat A,Mat B,MatStructure str)
508d6223691SXuan Zhou {
509d6223691SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
510d6223691SXuan Zhou   Mat_Elemental *b=(Mat_Elemental*)B->data;
511a4ee3bb6SSatish Balay   PetscErrorCode ierr;
512d6223691SXuan Zhou 
513d6223691SXuan Zhou   PetscFunctionBegin;
514e8146892SSatish Balay   El::Copy(*a->emat,*b->emat);
515cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
516d6223691SXuan Zhou   PetscFunctionReturn(0);
517d6223691SXuan Zhou }
518d6223691SXuan Zhou 
519df311e6cSXuan Zhou static PetscErrorCode MatDuplicate_Elemental(Mat A,MatDuplicateOption op,Mat *B)
520df311e6cSXuan Zhou {
521df311e6cSXuan Zhou   Mat            Be;
522ce94432eSBarry Smith   MPI_Comm       comm;
523df311e6cSXuan Zhou   Mat_Elemental  *a=(Mat_Elemental*)A->data;
524df311e6cSXuan Zhou   PetscErrorCode ierr;
525df311e6cSXuan Zhou 
526df311e6cSXuan Zhou   PetscFunctionBegin;
527ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
528df311e6cSXuan Zhou   ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
529df311e6cSXuan Zhou   ierr = MatSetSizes(Be,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
530df311e6cSXuan Zhou   ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
531df311e6cSXuan Zhou   ierr = MatSetUp(Be);CHKERRQ(ierr);
532df311e6cSXuan Zhou   *B = Be;
533df311e6cSXuan Zhou   if (op == MAT_COPY_VALUES) {
534df311e6cSXuan Zhou     Mat_Elemental *b=(Mat_Elemental*)Be->data;
535e8146892SSatish Balay     El::Copy(*a->emat,*b->emat);
536df311e6cSXuan Zhou   }
537df311e6cSXuan Zhou   Be->assembled = PETSC_TRUE;
538df311e6cSXuan Zhou   PetscFunctionReturn(0);
539df311e6cSXuan Zhou }
540df311e6cSXuan Zhou 
541d6223691SXuan Zhou static PetscErrorCode MatTranspose_Elemental(Mat A,MatReuse reuse,Mat *B)
542d6223691SXuan Zhou {
543ec8cb81fSBarry Smith   Mat            Be = *B;
5445262d616SXuan Zhou   PetscErrorCode ierr;
545ce94432eSBarry Smith   MPI_Comm       comm;
5464fe7bbcaSHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data, *b;
547d6223691SXuan Zhou 
548d6223691SXuan Zhou   PetscFunctionBegin;
549ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
5505cb544a0SHong Zhang   /* Only out-of-place supported */
5512847e3fdSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) SETERRQ(comm,PETSC_ERR_SUP,"Only out-of-place supported");
5525262d616SXuan Zhou   if (reuse == MAT_INITIAL_MATRIX) {
5535262d616SXuan Zhou     ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
5545262d616SXuan Zhou     ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
5555262d616SXuan Zhou     ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
5565262d616SXuan Zhou     ierr = MatSetUp(Be);CHKERRQ(ierr);
5575262d616SXuan Zhou     *B = Be;
5585262d616SXuan Zhou   }
5594fe7bbcaSHong Zhang   b = (Mat_Elemental*)Be->data;
560e8146892SSatish Balay   El::Transpose(*a->emat,*b->emat);
5615262d616SXuan Zhou   Be->assembled = PETSC_TRUE;
562d6223691SXuan Zhou   PetscFunctionReturn(0);
563d6223691SXuan Zhou }
564d6223691SXuan Zhou 
565dfcb0403SXuan Zhou static PetscErrorCode MatConjugate_Elemental(Mat A)
566dfcb0403SXuan Zhou {
567dfcb0403SXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
568dfcb0403SXuan Zhou 
569dfcb0403SXuan Zhou   PetscFunctionBegin;
570e8146892SSatish Balay   El::Conjugate(*a->emat);
571dfcb0403SXuan Zhou   PetscFunctionReturn(0);
572dfcb0403SXuan Zhou }
573dfcb0403SXuan Zhou 
5744a29722dSXuan Zhou static PetscErrorCode MatHermitianTranspose_Elemental(Mat A,MatReuse reuse,Mat *B)
5754a29722dSXuan Zhou {
576ec8cb81fSBarry Smith   Mat            Be = *B;
5774a29722dSXuan Zhou   PetscErrorCode ierr;
578ce94432eSBarry Smith   MPI_Comm       comm;
5794a29722dSXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data, *b;
5804a29722dSXuan Zhou 
5814a29722dSXuan Zhou   PetscFunctionBegin;
582ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
5835cb544a0SHong Zhang   /* Only out-of-place supported */
5844a29722dSXuan Zhou   if (reuse == MAT_INITIAL_MATRIX){
5854a29722dSXuan Zhou     ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
5864a29722dSXuan Zhou     ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
5874a29722dSXuan Zhou     ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
5884a29722dSXuan Zhou     ierr = MatSetUp(Be);CHKERRQ(ierr);
5894a29722dSXuan Zhou     *B = Be;
5904a29722dSXuan Zhou   }
5914a29722dSXuan Zhou   b = (Mat_Elemental*)Be->data;
592e8146892SSatish Balay   El::Adjoint(*a->emat,*b->emat);
5934a29722dSXuan Zhou   Be->assembled = PETSC_TRUE;
5944a29722dSXuan Zhou   PetscFunctionReturn(0);
5954a29722dSXuan Zhou }
5964a29722dSXuan Zhou 
5971f881ff8SXuan Zhou static PetscErrorCode MatSolve_Elemental(Mat A,Vec B,Vec X)
5981f881ff8SXuan Zhou {
5991f881ff8SXuan Zhou   Mat_Elemental     *a = (Mat_Elemental*)A->data;
6001f881ff8SXuan Zhou   PetscErrorCode    ierr;
601df311e6cSXuan Zhou   PetscElemScalar   *x;
602ea394475SSatish Balay   PetscInt          pivoting = a->pivoting;
6031f881ff8SXuan Zhou 
6041f881ff8SXuan Zhou   PetscFunctionBegin;
60545cf121fSXuan Zhou   ierr = VecCopy(B,X);CHKERRQ(ierr);
606e6dea9dbSXuan Zhou   ierr = VecGetArray(X,(PetscScalar **)&x);CHKERRQ(ierr);
607ea394475SSatish Balay 
608e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe;
6090c18141cSBarry Smith   xe.Attach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n);
610e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::MC,El::MR> xer(xe);
611fc54b460SXuan Zhou   switch (A->factortype) {
612fc54b460SXuan Zhou   case MAT_FACTOR_LU:
613ea394475SSatish Balay     if (pivoting == 0) {
614e8146892SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,xer);
615ea394475SSatish Balay     } else if (pivoting == 1) {
616ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,xer);
617ea394475SSatish Balay     } else { /* pivoting == 2 */
618ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,xer);
6191f881ff8SXuan Zhou     }
620fc54b460SXuan Zhou     break;
621fc54b460SXuan Zhou   case MAT_FACTOR_CHOLESKY:
622e8146892SSatish Balay     El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,xer);
623fc54b460SXuan Zhou     break;
624fc54b460SXuan Zhou   default:
6254fe7bbcaSHong Zhang     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType");
626fc54b460SXuan Zhou     break;
6271f881ff8SXuan Zhou   }
628ea394475SSatish Balay   El::Copy(xer,xe);
629ea394475SSatish Balay 
630e6dea9dbSXuan Zhou   ierr = VecRestoreArray(X,(PetscScalar **)&x);CHKERRQ(ierr);
6311f881ff8SXuan Zhou   PetscFunctionReturn(0);
6321f881ff8SXuan Zhou }
6331f881ff8SXuan Zhou 
634df311e6cSXuan Zhou static PetscErrorCode MatSolveAdd_Elemental(Mat A,Vec B,Vec Y,Vec X)
635df311e6cSXuan Zhou {
636df311e6cSXuan Zhou   PetscErrorCode    ierr;
637df311e6cSXuan Zhou 
638df311e6cSXuan Zhou   PetscFunctionBegin;
639df311e6cSXuan Zhou   ierr = MatSolve_Elemental(A,B,X);CHKERRQ(ierr);
6403d7f40dbSXuan Zhou   ierr = VecAXPY(X,1,Y);CHKERRQ(ierr);
641df311e6cSXuan Zhou   PetscFunctionReturn(0);
642df311e6cSXuan Zhou }
643df311e6cSXuan Zhou 
644ae844d54SHong Zhang static PetscErrorCode MatMatSolve_Elemental(Mat A,Mat B,Mat X)
645ae844d54SHong Zhang {
6461f0e42cfSHong Zhang   Mat_Elemental *a=(Mat_Elemental*)A->data;
647d6223691SXuan Zhou   Mat_Elemental *b=(Mat_Elemental*)B->data;
6481f0e42cfSHong Zhang   Mat_Elemental *x=(Mat_Elemental*)X->data;
649ea394475SSatish Balay   PetscInt      pivoting = a->pivoting;
6501f0e42cfSHong Zhang 
651ae844d54SHong Zhang   PetscFunctionBegin;
652e8146892SSatish Balay   El::Copy(*b->emat,*x->emat);
653fc54b460SXuan Zhou   switch (A->factortype) {
654fc54b460SXuan Zhou   case MAT_FACTOR_LU:
655ea394475SSatish Balay     if (pivoting == 0) {
656e8146892SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*x->emat);
657ea394475SSatish Balay     } else if (pivoting == 1) {
658ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*x->emat);
659ea394475SSatish Balay     } else {
660ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,*x->emat);
661d6223691SXuan Zhou     }
662fc54b460SXuan Zhou     break;
663fc54b460SXuan Zhou   case MAT_FACTOR_CHOLESKY:
664e8146892SSatish Balay     El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,*x->emat);
665fc54b460SXuan Zhou     break;
666fc54b460SXuan Zhou   default:
6674fe7bbcaSHong Zhang     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType");
668fc54b460SXuan Zhou     break;
669fc54b460SXuan Zhou   }
670ae844d54SHong Zhang   PetscFunctionReturn(0);
671ae844d54SHong Zhang }
672ae844d54SHong Zhang 
673ae844d54SHong Zhang static PetscErrorCode MatLUFactor_Elemental(Mat A,IS row,IS col,const MatFactorInfo *info)
674ae844d54SHong Zhang {
6757c920d81SXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
676124af5d2SSatish Balay   PetscErrorCode ierr;
677ea394475SSatish Balay   PetscInt       pivoting = a->pivoting;
6787c920d81SXuan Zhou 
679ae844d54SHong Zhang   PetscFunctionBegin;
680ea394475SSatish Balay   if (pivoting == 0) {
681e8146892SSatish Balay     El::LU(*a->emat);
682ea394475SSatish Balay   } else if (pivoting == 1) {
683ea394475SSatish Balay     El::LU(*a->emat,*a->P);
684ea394475SSatish Balay   } else {
685ea394475SSatish Balay     El::LU(*a->emat,*a->P,*a->Q);
686d6223691SXuan Zhou   }
6871293973dSHong Zhang   A->factortype = MAT_FACTOR_LU;
688834d3fecSHong Zhang   A->assembled  = PETSC_TRUE;
689f6224b95SHong Zhang 
690f6224b95SHong Zhang   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
691f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype);CHKERRQ(ierr);
692ae844d54SHong Zhang   PetscFunctionReturn(0);
693ae844d54SHong Zhang }
694ae844d54SHong Zhang 
695d7c3f9d8SHong Zhang static PetscErrorCode  MatLUFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info)
696d7c3f9d8SHong Zhang {
697d7c3f9d8SHong Zhang   PetscErrorCode ierr;
698d7c3f9d8SHong Zhang 
699d7c3f9d8SHong Zhang   PetscFunctionBegin;
700d7c3f9d8SHong Zhang   ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
701d7c3f9d8SHong Zhang   ierr = MatLUFactor_Elemental(F,0,0,info);CHKERRQ(ierr);
702d7c3f9d8SHong Zhang   PetscFunctionReturn(0);
703d7c3f9d8SHong Zhang }
704d7c3f9d8SHong Zhang 
705d7c3f9d8SHong Zhang static PetscErrorCode  MatLUFactorSymbolic_Elemental(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
706d7c3f9d8SHong Zhang {
707d7c3f9d8SHong Zhang   PetscFunctionBegin;
708d7c3f9d8SHong Zhang   /* F is create and allocated by MatGetFactor_elemental_petsc(), skip this routine. */
709d7c3f9d8SHong Zhang   PetscFunctionReturn(0);
710d7c3f9d8SHong Zhang }
711d7c3f9d8SHong Zhang 
71245cf121fSXuan Zhou static PetscErrorCode MatCholeskyFactor_Elemental(Mat A,IS perm,const MatFactorInfo *info)
71345cf121fSXuan Zhou {
71445cf121fSXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
715e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::MC,El::STAR> d;
716124af5d2SSatish Balay   PetscErrorCode ierr;
71745cf121fSXuan Zhou 
71845cf121fSXuan Zhou   PetscFunctionBegin;
719e8146892SSatish Balay   El::Cholesky(El::UPPER,*a->emat);
720fc54b460SXuan Zhou   A->factortype = MAT_FACTOR_CHOLESKY;
721834d3fecSHong Zhang   A->assembled  = PETSC_TRUE;
722f6224b95SHong Zhang 
723f6224b95SHong Zhang   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
724f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype);CHKERRQ(ierr);
72545cf121fSXuan Zhou   PetscFunctionReturn(0);
72645cf121fSXuan Zhou }
72745cf121fSXuan Zhou 
72879673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info)
72979673f7bSHong Zhang {
730cb76c1d8SXuan Zhou   PetscErrorCode ierr;
731cb76c1d8SXuan Zhou 
732cb76c1d8SXuan Zhou   PetscFunctionBegin;
733cb76c1d8SXuan Zhou   ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
734cb76c1d8SXuan Zhou   ierr = MatCholeskyFactor_Elemental(F,0,info);CHKERRQ(ierr);
735cb76c1d8SXuan Zhou   PetscFunctionReturn(0);
73679673f7bSHong Zhang }
737cb76c1d8SXuan Zhou 
73879673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorSymbolic_Elemental(Mat F,Mat A,IS perm,const MatFactorInfo *info)
73979673f7bSHong Zhang {
74079673f7bSHong Zhang   PetscFunctionBegin;
74179673f7bSHong Zhang   /* F is create and allocated by MatGetFactor_elemental_petsc(), skip this routine. */
74279673f7bSHong Zhang   PetscFunctionReturn(0);
74379673f7bSHong Zhang }
74479673f7bSHong Zhang 
745ea799195SBarry Smith PetscErrorCode MatFactorGetSolverType_elemental_elemental(Mat A,MatSolverType *type)
74615767789SHong Zhang {
74715767789SHong Zhang   PetscFunctionBegin;
74815767789SHong Zhang   *type = MATSOLVERELEMENTAL;
74915767789SHong Zhang   PetscFunctionReturn(0);
75015767789SHong Zhang }
75115767789SHong Zhang 
75215767789SHong Zhang static PetscErrorCode MatGetFactor_elemental_elemental(Mat A,MatFactorType ftype,Mat *F)
7531293973dSHong Zhang {
7541293973dSHong Zhang   Mat            B;
7551293973dSHong Zhang   PetscErrorCode ierr;
7561293973dSHong Zhang 
7571293973dSHong Zhang   PetscFunctionBegin;
7581293973dSHong Zhang   /* Create the factorization matrix */
759ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
7601293973dSHong Zhang   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
7611293973dSHong Zhang   ierr = MatSetType(B,MATELEMENTAL);CHKERRQ(ierr);
7621293973dSHong Zhang   ierr = MatSetUp(B);CHKERRQ(ierr);
7631293973dSHong Zhang   B->factortype = ftype;
76400c67f3bSHong Zhang   ierr = PetscFree(B->solvertype);CHKERRQ(ierr);
76500c67f3bSHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&B->solvertype);CHKERRQ(ierr);
76600c67f3bSHong Zhang 
7673ca39a21SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_elemental_elemental);CHKERRQ(ierr);
7681293973dSHong Zhang   *F            = B;
7691293973dSHong Zhang   PetscFunctionReturn(0);
7701293973dSHong Zhang }
7711293973dSHong Zhang 
7723ca39a21SBarry Smith PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Elemental(void)
77342c9c57cSBarry Smith {
77418713533SBarry Smith   PetscErrorCode ierr;
77518713533SBarry Smith 
77642c9c57cSBarry Smith   PetscFunctionBegin;
7773ca39a21SBarry Smith   ierr = MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL,        MAT_FACTOR_LU,MatGetFactor_elemental_elemental);CHKERRQ(ierr);
7783ca39a21SBarry Smith   ierr = MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL,        MAT_FACTOR_CHOLESKY,MatGetFactor_elemental_elemental);CHKERRQ(ierr);
77942c9c57cSBarry Smith   PetscFunctionReturn(0);
78042c9c57cSBarry Smith }
78142c9c57cSBarry Smith 
7821f881ff8SXuan Zhou static PetscErrorCode MatNorm_Elemental(Mat A,NormType type,PetscReal *nrm)
7831f881ff8SXuan Zhou {
7841f881ff8SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
7851f881ff8SXuan Zhou 
7861f881ff8SXuan Zhou   PetscFunctionBegin;
7871f881ff8SXuan Zhou   switch (type){
7881f881ff8SXuan Zhou   case NORM_1:
789e8146892SSatish Balay     *nrm = El::OneNorm(*a->emat);
7901f881ff8SXuan Zhou     break;
7911f881ff8SXuan Zhou   case NORM_FROBENIUS:
792e8146892SSatish Balay     *nrm = El::FrobeniusNorm(*a->emat);
7931f881ff8SXuan Zhou     break;
7941f881ff8SXuan Zhou   case NORM_INFINITY:
795e8146892SSatish Balay     *nrm = El::InfinityNorm(*a->emat);
7961f881ff8SXuan Zhou     break;
7971f881ff8SXuan Zhou   default:
7981f881ff8SXuan Zhou     printf("Error: unsupported norm type!\n");
7991f881ff8SXuan Zhou   }
8001f881ff8SXuan Zhou   PetscFunctionReturn(0);
8011f881ff8SXuan Zhou }
8021f881ff8SXuan Zhou 
8035262d616SXuan Zhou static PetscErrorCode MatZeroEntries_Elemental(Mat A)
8045262d616SXuan Zhou {
8055262d616SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
8065262d616SXuan Zhou 
8075262d616SXuan Zhou   PetscFunctionBegin;
808e8146892SSatish Balay   El::Zero(*a->emat);
8095262d616SXuan Zhou   PetscFunctionReturn(0);
8105262d616SXuan Zhou }
8115262d616SXuan Zhou 
812db31f6deSJed Brown static PetscErrorCode MatGetOwnershipIS_Elemental(Mat A,IS *rows,IS *cols)
813db31f6deSJed Brown {
814db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
815db31f6deSJed Brown   PetscErrorCode ierr;
816db31f6deSJed Brown   PetscInt       i,m,shift,stride,*idx;
817db31f6deSJed Brown 
818db31f6deSJed Brown   PetscFunctionBegin;
819db31f6deSJed Brown   if (rows) {
820db31f6deSJed Brown     m = a->emat->LocalHeight();
821db31f6deSJed Brown     shift = a->emat->ColShift();
822db31f6deSJed Brown     stride = a->emat->ColStride();
823785e854fSJed Brown     ierr = PetscMalloc1(m,&idx);CHKERRQ(ierr);
824db31f6deSJed Brown     for (i=0; i<m; i++) {
825db31f6deSJed Brown       PetscInt rank,offset;
826db31f6deSJed Brown       E2RO(A,0,shift+i*stride,&rank,&offset);
827db31f6deSJed Brown       RO2P(A,0,rank,offset,&idx[i]);
828db31f6deSJed Brown     }
829db31f6deSJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,rows);CHKERRQ(ierr);
830db31f6deSJed Brown   }
831db31f6deSJed Brown   if (cols) {
832db31f6deSJed Brown     m = a->emat->LocalWidth();
833db31f6deSJed Brown     shift = a->emat->RowShift();
834db31f6deSJed Brown     stride = a->emat->RowStride();
835785e854fSJed Brown     ierr = PetscMalloc1(m,&idx);CHKERRQ(ierr);
836db31f6deSJed Brown     for (i=0; i<m; i++) {
837db31f6deSJed Brown       PetscInt rank,offset;
838db31f6deSJed Brown       E2RO(A,1,shift+i*stride,&rank,&offset);
839db31f6deSJed Brown       RO2P(A,1,rank,offset,&idx[i]);
840db31f6deSJed Brown     }
841db31f6deSJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,cols);CHKERRQ(ierr);
842db31f6deSJed Brown   }
843db31f6deSJed Brown   PetscFunctionReturn(0);
844db31f6deSJed Brown }
845db31f6deSJed Brown 
84619fd82e9SBarry Smith static PetscErrorCode MatConvert_Elemental_Dense(Mat A,MatType newtype,MatReuse reuse,Mat *B)
847af295397SXuan Zhou {
8482ef0cf24SXuan Zhou   Mat                Bmpi;
849af295397SXuan Zhou   Mat_Elemental      *a = (Mat_Elemental*)A->data;
850ce94432eSBarry Smith   MPI_Comm           comm;
8512ef0cf24SXuan Zhou   PetscErrorCode     ierr;
852fa9e26c8SHong Zhang   IS                 isrows,iscols;
853fa9e26c8SHong Zhang   PetscInt           rrank,ridx,crank,cidx,nrows,ncols,i,j,erow,ecol,elrow,elcol;
854fa9e26c8SHong Zhang   const PetscInt     *rows,*cols;
855df311e6cSXuan Zhou   PetscElemScalar    v;
856fa9e26c8SHong Zhang   const El::Grid     &grid = a->emat->Grid();
857af295397SXuan Zhou 
858af295397SXuan Zhou   PetscFunctionBegin;
859ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
860a000e53bSHong Zhang 
861de0a22f0SHong Zhang   if (reuse == MAT_REUSE_MATRIX) {
862de0a22f0SHong Zhang     Bmpi = *B;
863de0a22f0SHong Zhang   } else {
864af295397SXuan Zhou     ierr = MatCreate(comm,&Bmpi);CHKERRQ(ierr);
865af295397SXuan Zhou     ierr = MatSetSizes(Bmpi,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
8662ef0cf24SXuan Zhou     ierr = MatSetType(Bmpi,MATDENSE);CHKERRQ(ierr);
867af295397SXuan Zhou     ierr = MatSetUp(Bmpi);CHKERRQ(ierr);
868de0a22f0SHong Zhang   }
869fa9e26c8SHong Zhang 
870fa9e26c8SHong Zhang   /* Get local entries of A */
871fa9e26c8SHong Zhang   ierr = MatGetOwnershipIS(A,&isrows,&iscols);CHKERRQ(ierr);
872fa9e26c8SHong Zhang   ierr = ISGetLocalSize(isrows,&nrows);CHKERRQ(ierr);
873fa9e26c8SHong Zhang   ierr = ISGetIndices(isrows,&rows);CHKERRQ(ierr);
874fa9e26c8SHong Zhang   ierr = ISGetLocalSize(iscols,&ncols);CHKERRQ(ierr);
875fa9e26c8SHong Zhang   ierr = ISGetIndices(iscols,&cols);CHKERRQ(ierr);
876fa9e26c8SHong Zhang 
87757299f2fSHong Zhang   if (a->roworiented) {
8782ef0cf24SXuan Zhou     for (i=0; i<nrows; i++) {
879fa9e26c8SHong Zhang       P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */
8802ef0cf24SXuan Zhou       RO2E(A,0,rrank,ridx,&erow);
8812ef0cf24SXuan Zhou       if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
8822ef0cf24SXuan Zhou       for (j=0; j<ncols; j++) {
883fa9e26c8SHong Zhang         P2RO(A,1,cols[j],&crank,&cidx);
8842ef0cf24SXuan Zhou         RO2E(A,1,crank,cidx,&ecol);
8852ef0cf24SXuan Zhou         if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
886fa9e26c8SHong Zhang 
887fa9e26c8SHong Zhang         elrow = erow / grid.MCSize(); /* Elemental local row index */
888fa9e26c8SHong Zhang         elcol = ecol / grid.MRSize(); /* Elemental local column index */
889fa9e26c8SHong Zhang         v = a->emat->GetLocal(elrow,elcol);
890fa9e26c8SHong Zhang         ierr = MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr);
8912ef0cf24SXuan Zhou       }
8922ef0cf24SXuan Zhou     }
89357299f2fSHong Zhang   } else { /* column-oriented */
89457299f2fSHong Zhang     for (j=0; j<ncols; j++) {
89557299f2fSHong Zhang       P2RO(A,1,cols[j],&crank,&cidx);
89657299f2fSHong Zhang       RO2E(A,1,crank,cidx,&ecol);
89757299f2fSHong Zhang       if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
89857299f2fSHong Zhang       for (i=0; i<nrows; i++) {
89957299f2fSHong Zhang         P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */
90057299f2fSHong Zhang         RO2E(A,0,rrank,ridx,&erow);
90157299f2fSHong Zhang         if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
90257299f2fSHong Zhang 
90357299f2fSHong Zhang         elrow = erow / grid.MCSize(); /* Elemental local row index */
90457299f2fSHong Zhang         elcol = ecol / grid.MRSize(); /* Elemental local column index */
90557299f2fSHong Zhang         v = a->emat->GetLocal(elrow,elcol);
90657299f2fSHong Zhang         ierr = MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr);
90757299f2fSHong Zhang       }
90857299f2fSHong Zhang     }
90957299f2fSHong Zhang   }
910af295397SXuan Zhou   ierr = MatAssemblyBegin(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
911af295397SXuan Zhou   ierr = MatAssemblyEnd(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
912511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
91328be2f97SBarry Smith     ierr = MatHeaderReplace(A,&Bmpi);CHKERRQ(ierr);
914c4ad791aSXuan Zhou   } else {
915c4ad791aSXuan Zhou     *B = Bmpi;
916c4ad791aSXuan Zhou   }
917fa9e26c8SHong Zhang   ierr = ISDestroy(&isrows);CHKERRQ(ierr);
918fa9e26c8SHong Zhang   ierr = ISDestroy(&iscols);CHKERRQ(ierr);
919af295397SXuan Zhou   PetscFunctionReturn(0);
920af295397SXuan Zhou }
921af295397SXuan Zhou 
922cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
923af8000cdSHong Zhang {
924af8000cdSHong Zhang   Mat               mat_elemental;
925af8000cdSHong Zhang   PetscErrorCode    ierr;
926af8000cdSHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols;
927af8000cdSHong Zhang   const PetscInt    *cols;
928af8000cdSHong Zhang   const PetscScalar *vals;
929af8000cdSHong Zhang 
930af8000cdSHong Zhang   PetscFunctionBegin;
931bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
932bdeae278SStefano Zampini     mat_elemental = *newmat;
933bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
934bdeae278SStefano Zampini   } else {
935af8000cdSHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
936af8000cdSHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
937af8000cdSHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
938af8000cdSHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
939bdeae278SStefano Zampini   }
940af8000cdSHong Zhang   for (row=0; row<M; row++) {
941af8000cdSHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
942bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
943af8000cdSHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
944af8000cdSHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
945af8000cdSHong Zhang   }
946af8000cdSHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
947af8000cdSHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
948af8000cdSHong Zhang 
949511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
95028be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
951af8000cdSHong Zhang   } else {
952af8000cdSHong Zhang     *newmat = mat_elemental;
953af8000cdSHong Zhang   }
954af8000cdSHong Zhang   PetscFunctionReturn(0);
955af8000cdSHong Zhang }
956af8000cdSHong Zhang 
957cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
9585d7652ecSHong Zhang {
9595d7652ecSHong Zhang   Mat               mat_elemental;
9605d7652ecSHong Zhang   PetscErrorCode    ierr;
9615d7652ecSHong Zhang   PetscInt          row,ncols,rstart=A->rmap->rstart,rend=A->rmap->rend,j;
9625d7652ecSHong Zhang   const PetscInt    *cols;
9635d7652ecSHong Zhang   const PetscScalar *vals;
9645d7652ecSHong Zhang 
9655d7652ecSHong Zhang   PetscFunctionBegin;
966bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
967bdeae278SStefano Zampini     mat_elemental = *newmat;
968bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
969bdeae278SStefano Zampini   } else {
9705d7652ecSHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
9715d7652ecSHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
9725d7652ecSHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
9735d7652ecSHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
974bdeae278SStefano Zampini   }
9755d7652ecSHong Zhang   for (row=rstart; row<rend; row++) {
9765d7652ecSHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
9775d7652ecSHong Zhang     for (j=0; j<ncols; j++) {
978bdeae278SStefano Zampini       /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
9795d7652ecSHong Zhang       ierr = MatSetValues(mat_elemental,1,&row,1,&cols[j],&vals[j],ADD_VALUES);CHKERRQ(ierr);
9805d7652ecSHong Zhang     }
9815d7652ecSHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
9825d7652ecSHong Zhang   }
9835d7652ecSHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9845d7652ecSHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9855d7652ecSHong Zhang 
986511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
98728be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
9885d7652ecSHong Zhang   } else {
9895d7652ecSHong Zhang     *newmat = mat_elemental;
9905d7652ecSHong Zhang   }
9915d7652ecSHong Zhang   PetscFunctionReturn(0);
9925d7652ecSHong Zhang }
9935d7652ecSHong Zhang 
994cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
9956214f412SHong Zhang {
9966214f412SHong Zhang   Mat               mat_elemental;
9976214f412SHong Zhang   PetscErrorCode    ierr;
9986214f412SHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols,j;
9996214f412SHong Zhang   const PetscInt    *cols;
10006214f412SHong Zhang   const PetscScalar *vals;
10016214f412SHong Zhang 
10026214f412SHong Zhang   PetscFunctionBegin;
1003bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1004bdeae278SStefano Zampini     mat_elemental = *newmat;
1005bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
1006bdeae278SStefano Zampini   } else {
10076214f412SHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
10086214f412SHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
10096214f412SHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
10106214f412SHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
1011bdeae278SStefano Zampini   }
10126214f412SHong Zhang   ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr);
10136214f412SHong Zhang   for (row=0; row<M; row++) {
10146214f412SHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
1015bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
10166214f412SHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
10176214f412SHong Zhang     for (j=0; j<ncols; j++) { /* lower triangular part */
10186214f412SHong Zhang       if (cols[j] == row) continue;
10196214f412SHong Zhang       ierr = MatSetValues(mat_elemental,1,&cols[j],1,&row,&vals[j],ADD_VALUES);CHKERRQ(ierr);
10206214f412SHong Zhang     }
10216214f412SHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
10226214f412SHong Zhang   }
10236214f412SHong Zhang   ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr);
10246214f412SHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10256214f412SHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10266214f412SHong Zhang 
1027511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
102828be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
10296214f412SHong Zhang   } else {
10306214f412SHong Zhang     *newmat = mat_elemental;
10316214f412SHong Zhang   }
10326214f412SHong Zhang   PetscFunctionReturn(0);
10336214f412SHong Zhang }
10346214f412SHong Zhang 
1035cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
10366214f412SHong Zhang {
10376214f412SHong Zhang   Mat               mat_elemental;
10386214f412SHong Zhang   PetscErrorCode    ierr;
10396214f412SHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols,j,rstart=A->rmap->rstart,rend=A->rmap->rend;
10406214f412SHong Zhang   const PetscInt    *cols;
10416214f412SHong Zhang   const PetscScalar *vals;
10426214f412SHong Zhang 
10436214f412SHong Zhang   PetscFunctionBegin;
1044bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1045bdeae278SStefano Zampini     mat_elemental = *newmat;
1046bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
1047bdeae278SStefano Zampini   } else {
10486214f412SHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
10496214f412SHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
10506214f412SHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
10516214f412SHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
1052bdeae278SStefano Zampini   }
10536214f412SHong Zhang   ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr);
10546214f412SHong Zhang   for (row=rstart; row<rend; row++) {
10556214f412SHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
1056bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
10576214f412SHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
10586214f412SHong Zhang     for (j=0; j<ncols; j++) { /* lower triangular part */
10596214f412SHong Zhang       if (cols[j] == row) continue;
10606214f412SHong Zhang       ierr = MatSetValues(mat_elemental,1,&cols[j],1,&row,&vals[j],ADD_VALUES);CHKERRQ(ierr);
10616214f412SHong Zhang     }
10626214f412SHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
10636214f412SHong Zhang   }
10646214f412SHong Zhang   ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr);
10656214f412SHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10666214f412SHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10676214f412SHong Zhang 
1068511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
106928be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
10706214f412SHong Zhang   } else {
10716214f412SHong Zhang     *newmat = mat_elemental;
10726214f412SHong Zhang   }
10736214f412SHong Zhang   PetscFunctionReturn(0);
10746214f412SHong Zhang }
10756214f412SHong Zhang 
1076db31f6deSJed Brown static PetscErrorCode MatDestroy_Elemental(Mat A)
1077db31f6deSJed Brown {
1078db31f6deSJed Brown   Mat_Elemental      *a = (Mat_Elemental*)A->data;
1079db31f6deSJed Brown   PetscErrorCode     ierr;
10805e9f5b67SHong Zhang   Mat_Elemental_Grid *commgrid;
10815e9f5b67SHong Zhang   PetscBool          flg;
10825e9f5b67SHong Zhang   MPI_Comm           icomm;
1083db31f6deSJed Brown 
1084db31f6deSJed Brown   PetscFunctionBegin;
1085db31f6deSJed Brown   delete a->emat;
1086ea394475SSatish Balay   delete a->P;
1087ea394475SSatish Balay   delete a->Q;
10885e9f5b67SHong Zhang 
1089e8146892SSatish Balay   El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A));
10900c18141cSBarry Smith   ierr = PetscCommDuplicate(cxxcomm.comm,&icomm,NULL);CHKERRQ(ierr);
109147435625SJed Brown   ierr = MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr);
10925e9f5b67SHong Zhang   if (--commgrid->grid_refct == 0) {
10935e9f5b67SHong Zhang     delete commgrid->grid;
10945e9f5b67SHong Zhang     ierr = PetscFree(commgrid);CHKERRQ(ierr);
109547435625SJed Brown     ierr = MPI_Comm_free_keyval(&Petsc_Elemental_keyval);CHKERRQ(ierr);
10965e9f5b67SHong Zhang   }
10975e9f5b67SHong Zhang   ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr);
1098bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",NULL);CHKERRQ(ierr);
10993ca39a21SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverType_C",NULL);CHKERRQ(ierr);
1100db31f6deSJed Brown   ierr = PetscFree(A->data);CHKERRQ(ierr);
1101db31f6deSJed Brown   PetscFunctionReturn(0);
1102db31f6deSJed Brown }
1103db31f6deSJed Brown 
1104db31f6deSJed Brown PetscErrorCode MatSetUp_Elemental(Mat A)
1105db31f6deSJed Brown {
1106db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
1107db31f6deSJed Brown   PetscErrorCode ierr;
1108f19600a0SHong Zhang   MPI_Comm       comm;
1109db31f6deSJed Brown   PetscMPIInt    rsize,csize;
1110f19600a0SHong Zhang   PetscInt       n;
1111db31f6deSJed Brown 
1112db31f6deSJed Brown   PetscFunctionBegin;
1113db31f6deSJed Brown   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1114db31f6deSJed Brown   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1115db31f6deSJed Brown 
1116f19600a0SHong Zhang   /* Check if local row and clomun sizes are equally distributed.
1117f19600a0SHong Zhang      Jed: Elemental uses "element" cyclic ordering so the sizes need to match that
1118f19600a0SHong Zhang      exactly.  The strategy in MatElemental is for PETSc to implicitly permute to block ordering (like would be returned by
1119f19600a0SHong Zhang      PetscSplitOwnership(comm,&n,&N)), at which point Elemental matrices can act on PETSc vectors without redistributing the vectors. */
1120f19600a0SHong Zhang   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1121f19600a0SHong Zhang   n = PETSC_DECIDE;
1122f19600a0SHong Zhang   ierr = PetscSplitOwnership(comm,&n,&A->rmap->N);CHKERRQ(ierr);
1123f19600a0SHong 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);
1124f19600a0SHong Zhang 
1125f19600a0SHong Zhang   n = PETSC_DECIDE;
1126f19600a0SHong Zhang   ierr = PetscSplitOwnership(comm,&n,&A->cmap->N);CHKERRQ(ierr);
1127f19600a0SHong 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);
1128f19600a0SHong Zhang 
1129efb79153SJack Poulson   a->emat->Resize(A->rmap->N,A->cmap->N);CHKERRQ(ierr);
1130e8146892SSatish Balay   El::Zero(*a->emat);
1131db31f6deSJed Brown 
1132db31f6deSJed Brown   ierr = MPI_Comm_size(A->rmap->comm,&rsize);CHKERRQ(ierr);
1133db31f6deSJed Brown   ierr = MPI_Comm_size(A->cmap->comm,&csize);CHKERRQ(ierr);
1134ce94432eSBarry Smith   if (csize != rsize) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Cannot use row and column communicators of different sizes");
1135db31f6deSJed Brown   a->commsize = rsize;
1136db31f6deSJed Brown   a->mr[0] = A->rmap->N % rsize; if (!a->mr[0]) a->mr[0] = rsize;
1137db31f6deSJed Brown   a->mr[1] = A->cmap->N % csize; if (!a->mr[1]) a->mr[1] = csize;
1138db31f6deSJed Brown   a->m[0]  = A->rmap->N / rsize + (a->mr[0] != rsize);
1139db31f6deSJed Brown   a->m[1]  = A->cmap->N / csize + (a->mr[1] != csize);
1140db31f6deSJed Brown   PetscFunctionReturn(0);
1141db31f6deSJed Brown }
1142db31f6deSJed Brown 
1143aae2c449SHong Zhang PetscErrorCode MatAssemblyBegin_Elemental(Mat A, MatAssemblyType type)
1144aae2c449SHong Zhang {
1145aae2c449SHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data;
1146aae2c449SHong Zhang 
1147aae2c449SHong Zhang   PetscFunctionBegin;
1148fbbcb730SJack Poulson   /* printf("Calling ProcessQueues\n"); */
1149fbbcb730SJack Poulson   a->emat->ProcessQueues();
1150fbbcb730SJack Poulson   /* printf("Finished ProcessQueues\n"); */
1151aae2c449SHong Zhang   PetscFunctionReturn(0);
1152aae2c449SHong Zhang }
1153aae2c449SHong Zhang 
1154aae2c449SHong Zhang PetscErrorCode MatAssemblyEnd_Elemental(Mat A, MatAssemblyType type)
1155aae2c449SHong Zhang {
1156aae2c449SHong Zhang   PetscFunctionBegin;
1157aae2c449SHong Zhang   /* Currently does nothing */
1158aae2c449SHong Zhang   PetscFunctionReturn(0);
1159aae2c449SHong Zhang }
1160aae2c449SHong Zhang 
11617b30e0f1SHong Zhang PetscErrorCode MatLoad_Elemental(Mat newMat, PetscViewer viewer)
11627b30e0f1SHong Zhang {
11637b30e0f1SHong Zhang   PetscErrorCode ierr;
11647b30e0f1SHong Zhang   Mat            Adense,Ae;
11657b30e0f1SHong Zhang   MPI_Comm       comm;
11667b30e0f1SHong Zhang 
11677b30e0f1SHong Zhang   PetscFunctionBegin;
11687b30e0f1SHong Zhang   ierr = PetscObjectGetComm((PetscObject)newMat,&comm);CHKERRQ(ierr);
11697b30e0f1SHong Zhang   ierr = MatCreate(comm,&Adense);CHKERRQ(ierr);
11707b30e0f1SHong Zhang   ierr = MatSetType(Adense,MATDENSE);CHKERRQ(ierr);
11717b30e0f1SHong Zhang   ierr = MatLoad(Adense,viewer);CHKERRQ(ierr);
11727b30e0f1SHong Zhang   ierr = MatConvert(Adense, MATELEMENTAL, MAT_INITIAL_MATRIX,&Ae);CHKERRQ(ierr);
11737b30e0f1SHong Zhang   ierr = MatDestroy(&Adense);CHKERRQ(ierr);
117428be2f97SBarry Smith   ierr = MatHeaderReplace(newMat,&Ae);CHKERRQ(ierr);
11757b30e0f1SHong Zhang   PetscFunctionReturn(0);
11767b30e0f1SHong Zhang }
11777b30e0f1SHong Zhang 
117840d92e34SHong Zhang /* -------------------------------------------------------------------*/
117940d92e34SHong Zhang static struct _MatOps MatOps_Values = {
118040d92e34SHong Zhang        MatSetValues_Elemental,
118140d92e34SHong Zhang        0,
118240d92e34SHong Zhang        0,
118340d92e34SHong Zhang        MatMult_Elemental,
118440d92e34SHong Zhang /* 4*/ MatMultAdd_Elemental,
11859426833fSXuan Zhou        MatMultTranspose_Elemental,
1186e883f9d5SXuan Zhou        MatMultTransposeAdd_Elemental,
118740d92e34SHong Zhang        MatSolve_Elemental,
1188df311e6cSXuan Zhou        MatSolveAdd_Elemental,
11892ef15aa2SHong Zhang        0,
11902ef15aa2SHong Zhang /*10*/ 0,
119140d92e34SHong Zhang        MatLUFactor_Elemental,
119240d92e34SHong Zhang        MatCholeskyFactor_Elemental,
119340d92e34SHong Zhang        0,
119440d92e34SHong Zhang        MatTranspose_Elemental,
119540d92e34SHong Zhang /*15*/ MatGetInfo_Elemental,
119640d92e34SHong Zhang        0,
119761119200SXuan Zhou        MatGetDiagonal_Elemental,
1198ade3cc5eSXuan Zhou        MatDiagonalScale_Elemental,
119940d92e34SHong Zhang        MatNorm_Elemental,
120040d92e34SHong Zhang /*20*/ MatAssemblyBegin_Elemental,
120140d92e34SHong Zhang        MatAssemblyEnd_Elemental,
120232d7a744SHong Zhang        MatSetOption_Elemental,
120340d92e34SHong Zhang        MatZeroEntries_Elemental,
120440d92e34SHong Zhang /*24*/ 0,
120540d92e34SHong Zhang        MatLUFactorSymbolic_Elemental,
120640d92e34SHong Zhang        MatLUFactorNumeric_Elemental,
120740d92e34SHong Zhang        MatCholeskyFactorSymbolic_Elemental,
120840d92e34SHong Zhang        MatCholeskyFactorNumeric_Elemental,
120940d92e34SHong Zhang /*29*/ MatSetUp_Elemental,
121040d92e34SHong Zhang        0,
121140d92e34SHong Zhang        0,
121240d92e34SHong Zhang        0,
121340d92e34SHong Zhang        0,
1214df311e6cSXuan Zhou /*34*/ MatDuplicate_Elemental,
121540d92e34SHong Zhang        0,
121640d92e34SHong Zhang        0,
121740d92e34SHong Zhang        0,
121840d92e34SHong Zhang        0,
121940d92e34SHong Zhang /*39*/ MatAXPY_Elemental,
122040d92e34SHong Zhang        0,
122140d92e34SHong Zhang        0,
122240d92e34SHong Zhang        0,
122340d92e34SHong Zhang        MatCopy_Elemental,
122440d92e34SHong Zhang /*44*/ 0,
122540d92e34SHong Zhang        MatScale_Elemental,
12267d68702bSBarry Smith        MatShift_Basic,
122740d92e34SHong Zhang        0,
122840d92e34SHong Zhang        0,
122940d92e34SHong Zhang /*49*/ 0,
123040d92e34SHong Zhang        0,
123140d92e34SHong Zhang        0,
123240d92e34SHong Zhang        0,
123340d92e34SHong Zhang        0,
123440d92e34SHong Zhang /*54*/ 0,
123540d92e34SHong Zhang        0,
123640d92e34SHong Zhang        0,
123740d92e34SHong Zhang        0,
123840d92e34SHong Zhang        0,
123940d92e34SHong Zhang /*59*/ 0,
124040d92e34SHong Zhang        MatDestroy_Elemental,
124140d92e34SHong Zhang        MatView_Elemental,
124240d92e34SHong Zhang        0,
124340d92e34SHong Zhang        0,
124440d92e34SHong Zhang /*64*/ 0,
124540d92e34SHong Zhang        0,
124640d92e34SHong Zhang        0,
124740d92e34SHong Zhang        0,
124840d92e34SHong Zhang        0,
124940d92e34SHong Zhang /*69*/ 0,
125040d92e34SHong Zhang        0,
12512ef0cf24SXuan Zhou        MatConvert_Elemental_Dense,
125240d92e34SHong Zhang        0,
125340d92e34SHong Zhang        0,
125440d92e34SHong Zhang /*74*/ 0,
125540d92e34SHong Zhang        0,
125640d92e34SHong Zhang        0,
125740d92e34SHong Zhang        0,
125840d92e34SHong Zhang        0,
125940d92e34SHong Zhang /*79*/ 0,
126040d92e34SHong Zhang        0,
126140d92e34SHong Zhang        0,
126240d92e34SHong Zhang        0,
12637b30e0f1SHong Zhang        MatLoad_Elemental,
126440d92e34SHong Zhang /*84*/ 0,
126540d92e34SHong Zhang        0,
126640d92e34SHong Zhang        0,
126740d92e34SHong Zhang        0,
126840d92e34SHong Zhang        0,
126940d92e34SHong Zhang /*89*/ MatMatMult_Elemental,
127040d92e34SHong Zhang        MatMatMultSymbolic_Elemental,
127140d92e34SHong Zhang        MatMatMultNumeric_Elemental,
127240d92e34SHong Zhang        0,
127340d92e34SHong Zhang        0,
127440d92e34SHong Zhang /*94*/ 0,
1275df311e6cSXuan Zhou        MatMatTransposeMult_Elemental,
1276df311e6cSXuan Zhou        MatMatTransposeMultSymbolic_Elemental,
1277df311e6cSXuan Zhou        MatMatTransposeMultNumeric_Elemental,
127840d92e34SHong Zhang        0,
127940d92e34SHong Zhang /*99*/ 0,
128040d92e34SHong Zhang        0,
128140d92e34SHong Zhang        0,
1282dfcb0403SXuan Zhou        MatConjugate_Elemental,
128340d92e34SHong Zhang        0,
128440d92e34SHong Zhang /*104*/0,
128540d92e34SHong Zhang        0,
128640d92e34SHong Zhang        0,
128740d92e34SHong Zhang        0,
128840d92e34SHong Zhang        0,
128940d92e34SHong Zhang /*109*/MatMatSolve_Elemental,
129040d92e34SHong Zhang        0,
129140d92e34SHong Zhang        0,
129240d92e34SHong Zhang        0,
129334fa46e1SFrancesco Ballarin        MatMissingDiagonal_Elemental,
129440d92e34SHong Zhang /*114*/0,
129540d92e34SHong Zhang        0,
129640d92e34SHong Zhang        0,
129740d92e34SHong Zhang        0,
129840d92e34SHong Zhang        0,
129940d92e34SHong Zhang /*119*/0,
13004a29722dSXuan Zhou        MatHermitianTranspose_Elemental,
130140d92e34SHong Zhang        0,
130240d92e34SHong Zhang        0,
130340d92e34SHong Zhang        0,
130440d92e34SHong Zhang /*124*/0,
130540d92e34SHong Zhang        0,
130640d92e34SHong Zhang        0,
130740d92e34SHong Zhang        0,
130840d92e34SHong Zhang        0,
130940d92e34SHong Zhang /*129*/0,
131040d92e34SHong Zhang        0,
131140d92e34SHong Zhang        0,
131240d92e34SHong Zhang        0,
131340d92e34SHong Zhang        0,
131440d92e34SHong Zhang /*134*/0,
131540d92e34SHong Zhang        0,
131640d92e34SHong Zhang        0,
131740d92e34SHong Zhang        0,
131840d92e34SHong Zhang        0
131940d92e34SHong Zhang };
132040d92e34SHong Zhang 
1321ed36708cSHong Zhang /*MC
1322ed36708cSHong Zhang    MATELEMENTAL = "elemental" - A matrix type for dense matrices using the Elemental package
1323ed36708cSHong Zhang 
1324c2b89b5dSBarry Smith   Use ./configure --download-elemental to install PETSc to use Elemental
1325c2b89b5dSBarry Smith 
13263ca39a21SBarry Smith   Use -pc_type lu -pc_factor_mat_solver_type elemental to use this direct solver
1327c2b89b5dSBarry Smith 
1328ed36708cSHong Zhang    Options Database Keys:
13295cc86fc1SJed Brown + -mat_type elemental - sets the matrix type to "elemental" during a call to MatSetFromOptions()
13305cc86fc1SJed Brown - -mat_elemental_grid_height - sets Grid Height for 2D cyclic ordering of internal matrix
1331ed36708cSHong Zhang 
1332ed36708cSHong Zhang   Level: beginner
1333ed36708cSHong Zhang 
13345cb544a0SHong Zhang .seealso: MATDENSE
1335ed36708cSHong Zhang M*/
13364a29722dSXuan Zhou 
13378cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Elemental(Mat A)
1338db31f6deSJed Brown {
1339db31f6deSJed Brown   Mat_Elemental      *a;
1340db31f6deSJed Brown   PetscErrorCode     ierr;
13415682a260SJack Poulson   PetscBool          flg,flg1;
13425e9f5b67SHong Zhang   Mat_Elemental_Grid *commgrid;
13435e9f5b67SHong Zhang   MPI_Comm           icomm;
13445682a260SJack Poulson   PetscInt           optv1;
1345db31f6deSJed Brown 
1346db31f6deSJed Brown   PetscFunctionBegin;
1347607a6623SBarry Smith   ierr = PetscElementalInitializePackage();CHKERRQ(ierr);
134840d92e34SHong Zhang   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
134940d92e34SHong Zhang   A->insertmode = NOT_SET_VALUES;
1350db31f6deSJed Brown 
1351b00a9115SJed Brown   ierr = PetscNewLog(A,&a);CHKERRQ(ierr);
1352db31f6deSJed Brown   A->data = (void*)a;
1353db31f6deSJed Brown 
1354db31f6deSJed Brown   /* Set up the elemental matrix */
1355e8146892SSatish Balay   El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A));
13565e9f5b67SHong Zhang 
13575e9f5b67SHong Zhang   /* Grid needs to be shared between multiple Mats on the same communicator, implement by attribute caching on the MPI_Comm */
13585e9f5b67SHong Zhang   if (Petsc_Elemental_keyval == MPI_KEYVAL_INVALID) {
135912801b39SBarry Smith     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Elemental_keyval,(void*)0);CHKERRQ(ierr);
13605e9f5b67SHong Zhang   }
13610c18141cSBarry Smith   ierr = PetscCommDuplicate(cxxcomm.comm,&icomm,NULL);CHKERRQ(ierr);
136247435625SJed Brown   ierr = MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr);
13635e9f5b67SHong Zhang   if (!flg) {
1364b00a9115SJed Brown     ierr = PetscNewLog(A,&commgrid);CHKERRQ(ierr);
13655cb544a0SHong Zhang 
1366ce94432eSBarry Smith     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"Elemental Options","Mat");CHKERRQ(ierr);
1367e8146892SSatish Balay     /* displayed default grid sizes (CommSize,1) are set by us arbitrarily until El::Grid() is called */
1368e8146892SSatish Balay     ierr = PetscOptionsInt("-mat_elemental_grid_height","Grid Height","None",El::mpi::Size(cxxcomm),&optv1,&flg1);CHKERRQ(ierr);
13695682a260SJack Poulson     if (flg1) {
1370e8146892SSatish Balay       if (El::mpi::Size(cxxcomm) % optv1 != 0) {
1371e8146892SSatish Balay         SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Grid Height %D must evenly divide CommSize %D",optv1,(PetscInt)El::mpi::Size(cxxcomm));
1372ed667823SXuan Zhou       }
1373e8146892SSatish Balay       commgrid->grid = new El::Grid(cxxcomm,optv1); /* use user-provided grid height */
13742ef0cf24SXuan Zhou     } else {
1375e8146892SSatish Balay       commgrid->grid = new El::Grid(cxxcomm); /* use Elemental default grid sizes */
1376da0640a4SHong Zhang       /* printf("new commgrid->grid = %p\n",commgrid->grid);  -- memory leak revealed by valgrind? */
1377ed667823SXuan Zhou     }
13785e9f5b67SHong Zhang     commgrid->grid_refct = 1;
137947435625SJed Brown     ierr = MPI_Comm_set_attr(icomm,Petsc_Elemental_keyval,(void*)commgrid);CHKERRQ(ierr);
1380ea394475SSatish Balay 
1381ea394475SSatish Balay     a->pivoting    = 1;
1382ea394475SSatish Balay     ierr = PetscOptionsInt("-mat_elemental_pivoting","Pivoting","None",a->pivoting,&a->pivoting,NULL);CHKERRQ(ierr);
1383ea394475SSatish Balay 
13842a808120SBarry Smith     ierr = PetscOptionsEnd();CHKERRQ(ierr);
13855e9f5b67SHong Zhang   } else {
13865e9f5b67SHong Zhang     commgrid->grid_refct++;
13875e9f5b67SHong Zhang   }
13885e9f5b67SHong Zhang   ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr);
13895e9f5b67SHong Zhang   a->grid        = commgrid->grid;
1390e8146892SSatish Balay   a->emat        = new El::DistMatrix<PetscElemScalar>(*a->grid);
139132d7a744SHong Zhang   a->roworiented = PETSC_TRUE;
1392db31f6deSJed Brown 
1393bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",MatGetOwnershipIS_Elemental);CHKERRQ(ierr);
1394db31f6deSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)A,MATELEMENTAL);CHKERRQ(ierr);
1395db31f6deSJed Brown   PetscFunctionReturn(0);
1396db31f6deSJed Brown }
1397