xref: /petsc/src/mat/impls/elemental/matelem.cxx (revision 4222ddf1d74c63827c599361b3bb0b06ad3944a0)
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;
7261119200SXuan Zhou         ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense);CHKERRQ(ierr);
7361119200SXuan Zhou         ierr = MatView(Adense,viewer);CHKERRQ(ierr);
7461119200SXuan Zhou         ierr = MatDestroy(&Adense);CHKERRQ(ierr);
75834d3fecSHong Zhang       }
76ce94432eSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Format");
77d2daa67eSHong Zhang   } else {
785cb544a0SHong Zhang     /* convert to dense format and call MatView() */
7961119200SXuan Zhou     Mat Adense;
8061119200SXuan Zhou     ierr = MatConvert(A,MATDENSE,MAT_INITIAL_MATRIX,&Adense);CHKERRQ(ierr);
8161119200SXuan Zhou     ierr = MatView(Adense,viewer);CHKERRQ(ierr);
8261119200SXuan Zhou     ierr = MatDestroy(&Adense);CHKERRQ(ierr);
83d2daa67eSHong Zhang   }
84db31f6deSJed Brown   PetscFunctionReturn(0);
85db31f6deSJed Brown }
86db31f6deSJed Brown 
8715767789SHong Zhang static PetscErrorCode MatGetInfo_Elemental(Mat A,MatInfoType flag,MatInfo *info)
88180a43e4SHong Zhang {
8915767789SHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data;
9015767789SHong Zhang 
91180a43e4SHong Zhang   PetscFunctionBegin;
925cb544a0SHong Zhang   info->block_size = 1.0;
9315767789SHong Zhang 
9415767789SHong Zhang   if (flag == MAT_LOCAL) {
953966268fSBarry Smith     info->nz_allocated   = (*a->emat).AllocatedMemory(); /* locally allocated */
9615767789SHong Zhang     info->nz_used        = info->nz_allocated;
9715767789SHong Zhang   } else if (flag == MAT_GLOBAL_MAX) {
98b2566f29SBarry Smith     //ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)matin));CHKERRQ(ierr);
9915767789SHong Zhang     /* see MatGetInfo_MPIAIJ() for getting global info->nz_allocated! */
10015767789SHong Zhang     //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_MAX not written yet");
10115767789SHong Zhang   } else if (flag == MAT_GLOBAL_SUM) {
10215767789SHong Zhang     //SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP," MAT_GLOBAL_SUM not written yet");
1033966268fSBarry Smith     info->nz_allocated   = (*a->emat).AllocatedMemory(); /* locally allocated */
10415767789SHong Zhang     info->nz_used        = info->nz_allocated; /* assume Elemental does accurate allocation */
105b2566f29SBarry Smith     //ierr = MPIU_Allreduce(isend,irecv,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
10615767789SHong Zhang     //PetscPrintf(PETSC_COMM_SELF,"    ... [%d] locally allocated %g\n",rank,info->nz_allocated);
10715767789SHong Zhang   }
10815767789SHong Zhang 
10915767789SHong Zhang   info->nz_unneeded       = 0.0;
1103966268fSBarry Smith   info->assemblies        = A->num_ass;
11115767789SHong Zhang   info->mallocs           = 0;
11215767789SHong Zhang   info->memory            = ((PetscObject)A)->mem;
11315767789SHong Zhang   info->fill_ratio_given  = 0; /* determined by Elemental */
11415767789SHong Zhang   info->fill_ratio_needed = 0;
11515767789SHong Zhang   info->factor_mallocs    = 0;
116180a43e4SHong Zhang   PetscFunctionReturn(0);
117180a43e4SHong Zhang }
118180a43e4SHong Zhang 
11932d7a744SHong Zhang PetscErrorCode MatSetOption_Elemental(Mat A,MatOption op,PetscBool flg)
12032d7a744SHong Zhang {
12132d7a744SHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data;
12232d7a744SHong Zhang 
12332d7a744SHong Zhang   PetscFunctionBegin;
12432d7a744SHong Zhang   switch (op) {
12532d7a744SHong Zhang   case MAT_NEW_NONZERO_LOCATIONS:
12632d7a744SHong Zhang   case MAT_NEW_NONZERO_LOCATION_ERR:
12732d7a744SHong Zhang   case MAT_NEW_NONZERO_ALLOCATION_ERR:
128891a0571SHong Zhang   case MAT_SYMMETRIC:
129071fcb05SBarry Smith   case MAT_SORTED_FULL:
130eb1ec7c1SStefano Zampini   case MAT_HERMITIAN:
131891a0571SHong Zhang     break;
13232d7a744SHong Zhang   case MAT_ROW_ORIENTED:
13332d7a744SHong Zhang     a->roworiented = flg;
13432d7a744SHong Zhang     break;
13532d7a744SHong Zhang   default:
13632d7a744SHong Zhang     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %s",MatOptions[op]);
13732d7a744SHong Zhang   }
13832d7a744SHong Zhang   PetscFunctionReturn(0);
13932d7a744SHong Zhang }
14032d7a744SHong Zhang 
141e6dea9dbSXuan Zhou static PetscErrorCode MatSetValues_Elemental(Mat A,PetscInt nr,const PetscInt *rows,PetscInt nc,const PetscInt *cols,const PetscScalar *vals,InsertMode imode)
142db31f6deSJed Brown {
143db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
144fbbcb730SJack Poulson   PetscInt       i,j,rrank,ridx,crank,cidx,erow,ecol,numQueues=0;
145db31f6deSJed Brown 
146db31f6deSJed Brown   PetscFunctionBegin;
147fbbcb730SJack Poulson   // TODO: Initialize matrix to all zeros?
148fbbcb730SJack Poulson 
149fbbcb730SJack Poulson   // Count the number of queues from this process
15032d7a744SHong Zhang   if (a->roworiented) {
151db31f6deSJed Brown     for (i=0; i<nr; i++) {
152db31f6deSJed Brown       if (rows[i] < 0) continue;
153db31f6deSJed Brown       P2RO(A,0,rows[i],&rrank,&ridx);
154db31f6deSJed Brown       RO2E(A,0,rrank,ridx,&erow);
155ce94432eSBarry Smith       if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect row translation");
156db31f6deSJed Brown       for (j=0; j<nc; j++) {
157db31f6deSJed Brown         if (cols[j] < 0) continue;
158db31f6deSJed Brown         P2RO(A,1,cols[j],&crank,&cidx);
159db31f6deSJed Brown         RO2E(A,1,crank,cidx,&ecol);
160ce94432eSBarry Smith         if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect col translation");
161fbbcb730SJack Poulson         if (!a->emat->IsLocal(erow,ecol) ){ /* off-proc entry */
162fbbcb730SJack Poulson           /* printf("Will later remotely update (%d,%d)\n",erow,ecol); */
163aae2c449SHong Zhang           if (imode != ADD_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported");
164fbbcb730SJack Poulson           ++numQueues;
165aae2c449SHong Zhang           continue;
166ed36708cSHong Zhang         }
167fbbcb730SJack Poulson         /* printf("Locally updating (%d,%d)\n",erow,ecol); */
168db31f6deSJed Brown         switch (imode) {
169fbbcb730SJack Poulson         case INSERT_VALUES: a->emat->Set(erow,ecol,(PetscElemScalar)vals[i*nc+j]); break;
170fbbcb730SJack Poulson         case ADD_VALUES: a->emat->Update(erow,ecol,(PetscElemScalar)vals[i*nc+j]); break;
171ce94432eSBarry Smith         default: SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode);
172db31f6deSJed Brown         }
173db31f6deSJed Brown       }
174db31f6deSJed Brown     }
175fbbcb730SJack Poulson 
176fbbcb730SJack Poulson     /* printf("numQueues=%d\n",numQueues); */
177fbbcb730SJack Poulson     a->emat->Reserve( numQueues );
178fbbcb730SJack Poulson     for (i=0; i<nr; i++) {
179fbbcb730SJack Poulson       if (rows[i] < 0) continue;
180fbbcb730SJack Poulson       P2RO(A,0,rows[i],&rrank,&ridx);
181fbbcb730SJack Poulson       RO2E(A,0,rrank,ridx,&erow);
182fbbcb730SJack Poulson       for (j=0; j<nc; j++) {
183fbbcb730SJack Poulson         if (cols[j] < 0) continue;
184fbbcb730SJack Poulson         P2RO(A,1,cols[j],&crank,&cidx);
185fbbcb730SJack Poulson         RO2E(A,1,crank,cidx,&ecol);
186fbbcb730SJack Poulson         if ( !a->emat->IsLocal(erow,ecol) ) { /*off-proc entry*/
187fbbcb730SJack Poulson           /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */
188fbbcb730SJack Poulson           a->emat->QueueUpdate( erow, ecol, vals[i*nc+j] );
189fbbcb730SJack Poulson         }
190fbbcb730SJack Poulson       }
191fbbcb730SJack Poulson     }
19232d7a744SHong Zhang   } else { /* columnoriented */
19332d7a744SHong Zhang     for (j=0; j<nc; j++) {
19432d7a744SHong Zhang       if (cols[j] < 0) continue;
19532d7a744SHong Zhang       P2RO(A,1,cols[j],&crank,&cidx);
19632d7a744SHong Zhang       RO2E(A,1,crank,cidx,&ecol);
19732d7a744SHong Zhang       if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect col translation");
19832d7a744SHong Zhang       for (i=0; i<nr; i++) {
19932d7a744SHong Zhang         if (rows[i] < 0) continue;
20032d7a744SHong Zhang         P2RO(A,0,rows[i],&rrank,&ridx);
20132d7a744SHong Zhang         RO2E(A,0,rrank,ridx,&erow);
20232d7a744SHong Zhang         if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Incorrect row translation");
20332d7a744SHong Zhang         if (!a->emat->IsLocal(erow,ecol) ){ /* off-proc entry */
20432d7a744SHong Zhang           /* printf("Will later remotely update (%d,%d)\n",erow,ecol); */
20532d7a744SHong Zhang           if (imode != ADD_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported");
20632d7a744SHong Zhang           ++numQueues;
20732d7a744SHong Zhang           continue;
20832d7a744SHong Zhang         }
20932d7a744SHong Zhang         /* printf("Locally updating (%d,%d)\n",erow,ecol); */
21032d7a744SHong Zhang         switch (imode) {
21132d7a744SHong Zhang         case INSERT_VALUES: a->emat->Set(erow,ecol,(PetscElemScalar)vals[i+j*nr]); break;
21232d7a744SHong Zhang         case ADD_VALUES: a->emat->Update(erow,ecol,(PetscElemScalar)vals[i+j*nr]); break;
21332d7a744SHong Zhang         default: SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode);
21432d7a744SHong Zhang         }
21532d7a744SHong Zhang       }
21632d7a744SHong Zhang     }
21732d7a744SHong Zhang 
21832d7a744SHong Zhang     /* printf("numQueues=%d\n",numQueues); */
21932d7a744SHong Zhang     a->emat->Reserve( numQueues );
22032d7a744SHong Zhang     for (j=0; j<nc; j++) {
22132d7a744SHong Zhang       if (cols[j] < 0) continue;
22232d7a744SHong Zhang       P2RO(A,1,cols[j],&crank,&cidx);
22332d7a744SHong Zhang       RO2E(A,1,crank,cidx,&ecol);
22432d7a744SHong Zhang 
22532d7a744SHong Zhang       for (i=0; i<nr; i++) {
22632d7a744SHong Zhang         if (rows[i] < 0) continue;
22732d7a744SHong Zhang         P2RO(A,0,rows[i],&rrank,&ridx);
22832d7a744SHong Zhang         RO2E(A,0,rrank,ridx,&erow);
22932d7a744SHong Zhang         if ( !a->emat->IsLocal(erow,ecol) ) { /*off-proc entry*/
23032d7a744SHong Zhang           /* printf("Queueing remotely update of (%d,%d)\n",erow,ecol); */
23132d7a744SHong Zhang           a->emat->QueueUpdate( erow, ecol, vals[i+j*nr] );
23232d7a744SHong Zhang         }
23332d7a744SHong Zhang       }
23432d7a744SHong Zhang     }
23532d7a744SHong Zhang   }
236db31f6deSJed Brown   PetscFunctionReturn(0);
237db31f6deSJed Brown }
238db31f6deSJed Brown 
239db31f6deSJed Brown static PetscErrorCode MatMult_Elemental(Mat A,Vec X,Vec Y)
240db31f6deSJed Brown {
241db31f6deSJed Brown   Mat_Elemental         *a = (Mat_Elemental*)A->data;
242db31f6deSJed Brown   PetscErrorCode        ierr;
243e6dea9dbSXuan Zhou   const PetscElemScalar *x;
244e6dea9dbSXuan Zhou   PetscElemScalar       *y;
245df311e6cSXuan Zhou   PetscElemScalar       one = 1,zero = 0;
246db31f6deSJed Brown 
247db31f6deSJed Brown   PetscFunctionBegin;
248e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
249e6dea9dbSXuan Zhou   ierr = VecGetArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
250db31f6deSJed Brown   { /* Scoping so that constructor is called before pointer is returned */
251e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ye;
2520c18141cSBarry Smith     xe.LockedAttach(A->cmap->N,1,*a->grid,0,0,x,A->cmap->n);
2530c18141cSBarry Smith     ye.Attach(A->rmap->N,1,*a->grid,0,0,y,A->rmap->n);
254e8146892SSatish Balay     El::Gemv(El::NORMAL,one,*a->emat,xe,zero,ye);
255db31f6deSJed Brown   }
256e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
257e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
258db31f6deSJed Brown   PetscFunctionReturn(0);
259db31f6deSJed Brown }
260db31f6deSJed Brown 
2619426833fSXuan Zhou static PetscErrorCode MatMultTranspose_Elemental(Mat A,Vec X,Vec Y)
2629426833fSXuan Zhou {
2639426833fSXuan Zhou   Mat_Elemental         *a = (Mat_Elemental*)A->data;
2649426833fSXuan Zhou   PetscErrorCode        ierr;
265df311e6cSXuan Zhou   const PetscElemScalar *x;
266df311e6cSXuan Zhou   PetscElemScalar       *y;
267e6dea9dbSXuan Zhou   PetscElemScalar       one = 1,zero = 0;
2689426833fSXuan Zhou 
2699426833fSXuan Zhou   PetscFunctionBegin;
270e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
271e6dea9dbSXuan Zhou   ierr = VecGetArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
2729426833fSXuan Zhou   { /* Scoping so that constructor is called before pointer is returned */
273e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ye;
2740c18141cSBarry Smith     xe.LockedAttach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n);
2750c18141cSBarry Smith     ye.Attach(A->cmap->N,1,*a->grid,0,0,y,A->cmap->n);
276e8146892SSatish Balay     El::Gemv(El::TRANSPOSE,one,*a->emat,xe,zero,ye);
2779426833fSXuan Zhou   }
278e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
279e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Y,(PetscScalar **)&y);CHKERRQ(ierr);
2809426833fSXuan Zhou   PetscFunctionReturn(0);
2819426833fSXuan Zhou }
2829426833fSXuan Zhou 
283db31f6deSJed Brown static PetscErrorCode MatMultAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z)
284db31f6deSJed Brown {
285db31f6deSJed Brown   Mat_Elemental         *a = (Mat_Elemental*)A->data;
286db31f6deSJed Brown   PetscErrorCode        ierr;
287df311e6cSXuan Zhou   const PetscElemScalar *x;
288df311e6cSXuan Zhou   PetscElemScalar       *z;
289e6dea9dbSXuan Zhou   PetscElemScalar       one = 1;
290db31f6deSJed Brown 
291db31f6deSJed Brown   PetscFunctionBegin;
292db31f6deSJed Brown   if (Y != Z) {ierr = VecCopy(Y,Z);CHKERRQ(ierr);}
293e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
294e6dea9dbSXuan Zhou   ierr = VecGetArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
295db31f6deSJed Brown   { /* Scoping so that constructor is called before pointer is returned */
296e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ze;
2970c18141cSBarry Smith     xe.LockedAttach(A->cmap->N,1,*a->grid,0,0,x,A->cmap->n);
2980c18141cSBarry Smith     ze.Attach(A->rmap->N,1,*a->grid,0,0,z,A->rmap->n);
299e8146892SSatish Balay     El::Gemv(El::NORMAL,one,*a->emat,xe,one,ze);
300db31f6deSJed Brown   }
301e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
302e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
303db31f6deSJed Brown   PetscFunctionReturn(0);
304db31f6deSJed Brown }
305db31f6deSJed Brown 
306e883f9d5SXuan Zhou static PetscErrorCode MatMultTransposeAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z)
307e883f9d5SXuan Zhou {
308e883f9d5SXuan Zhou   Mat_Elemental         *a = (Mat_Elemental*)A->data;
309e883f9d5SXuan Zhou   PetscErrorCode        ierr;
310df311e6cSXuan Zhou   const PetscElemScalar *x;
311df311e6cSXuan Zhou   PetscElemScalar       *z;
312e6dea9dbSXuan Zhou   PetscElemScalar       one = 1;
313e883f9d5SXuan Zhou 
314e883f9d5SXuan Zhou   PetscFunctionBegin;
315e883f9d5SXuan Zhou   if (Y != Z) {ierr = VecCopy(Y,Z);CHKERRQ(ierr);}
316e6dea9dbSXuan Zhou   ierr = VecGetArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
317e6dea9dbSXuan Zhou   ierr = VecGetArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
318e883f9d5SXuan Zhou   { /* Scoping so that constructor is called before pointer is returned */
319e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe, ze;
3200c18141cSBarry Smith     xe.LockedAttach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n);
3210c18141cSBarry Smith     ze.Attach(A->cmap->N,1,*a->grid,0,0,z,A->cmap->n);
322e8146892SSatish Balay     El::Gemv(El::TRANSPOSE,one,*a->emat,xe,one,ze);
323e883f9d5SXuan Zhou   }
324e6dea9dbSXuan Zhou   ierr = VecRestoreArrayRead(X,(const PetscScalar **)&x);CHKERRQ(ierr);
325e6dea9dbSXuan Zhou   ierr = VecRestoreArray(Z,(PetscScalar **)&z);CHKERRQ(ierr);
326e883f9d5SXuan Zhou   PetscFunctionReturn(0);
327e883f9d5SXuan Zhou }
328e883f9d5SXuan Zhou 
329*4222ddf1SHong Zhang PetscErrorCode MatMatMultNumeric_Elemental(Mat A,Mat B,Mat C)
330c1d1b975SXuan Zhou {
331c1d1b975SXuan Zhou   Mat_Elemental    *a = (Mat_Elemental*)A->data;
332c1d1b975SXuan Zhou   Mat_Elemental    *b = (Mat_Elemental*)B->data;
3339a9e8502SHong Zhang   Mat_Elemental    *c = (Mat_Elemental*)C->data;
334e6dea9dbSXuan Zhou   PetscElemScalar  one = 1,zero = 0;
335c1d1b975SXuan Zhou 
336c1d1b975SXuan Zhou   PetscFunctionBegin;
337aae2c449SHong Zhang   { /* Scoping so that constructor is called before pointer is returned */
338e8146892SSatish Balay     El::Gemm(El::NORMAL,El::NORMAL,one,*a->emat,*b->emat,zero,*c->emat);
339aae2c449SHong Zhang   }
3409a9e8502SHong Zhang   C->assembled = PETSC_TRUE;
3419a9e8502SHong Zhang   PetscFunctionReturn(0);
3429a9e8502SHong Zhang }
3439a9e8502SHong Zhang 
344*4222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat Ce)
3459a9e8502SHong Zhang {
3469a9e8502SHong Zhang   PetscErrorCode ierr;
3479a9e8502SHong Zhang 
3489a9e8502SHong Zhang   PetscFunctionBegin;
3499a9e8502SHong Zhang   ierr = MatSetSizes(Ce,A->rmap->n,B->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
3509a9e8502SHong Zhang   ierr = MatSetType(Ce,MATELEMENTAL);CHKERRQ(ierr);
3519a9e8502SHong Zhang   ierr = MatSetUp(Ce);CHKERRQ(ierr);
352*4222ddf1SHong Zhang   Ce->ops->matmultnumeric = MatMatMultNumeric_Elemental;
353c1d1b975SXuan Zhou   PetscFunctionReturn(0);
354c1d1b975SXuan Zhou }
355c1d1b975SXuan Zhou 
356df311e6cSXuan Zhou static PetscErrorCode MatMatTransposeMultNumeric_Elemental(Mat A,Mat B,Mat C)
357df311e6cSXuan Zhou {
358df311e6cSXuan Zhou   Mat_Elemental      *a = (Mat_Elemental*)A->data;
359df311e6cSXuan Zhou   Mat_Elemental      *b = (Mat_Elemental*)B->data;
360df311e6cSXuan Zhou   Mat_Elemental      *c = (Mat_Elemental*)C->data;
361e6dea9dbSXuan Zhou   PetscElemScalar    one = 1,zero = 0;
362df311e6cSXuan Zhou 
363df311e6cSXuan Zhou   PetscFunctionBegin;
364df311e6cSXuan Zhou   { /* Scoping so that constructor is called before pointer is returned */
365e8146892SSatish Balay     El::Gemm(El::NORMAL,El::TRANSPOSE,one,*a->emat,*b->emat,zero,*c->emat);
366df311e6cSXuan Zhou   }
367df311e6cSXuan Zhou   C->assembled = PETSC_TRUE;
368df311e6cSXuan Zhou   PetscFunctionReturn(0);
369df311e6cSXuan Zhou }
370df311e6cSXuan Zhou 
371*4222ddf1SHong Zhang static PetscErrorCode MatMatTransposeMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat C)
372df311e6cSXuan Zhou {
373df311e6cSXuan Zhou   PetscErrorCode ierr;
374df311e6cSXuan Zhou 
375df311e6cSXuan Zhou   PetscFunctionBegin;
376*4222ddf1SHong Zhang   ierr = MatSetSizes(C,A->rmap->n,B->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
377*4222ddf1SHong Zhang   ierr = MatSetType(C,MATELEMENTAL);CHKERRQ(ierr);
378*4222ddf1SHong Zhang   ierr = MatSetUp(C);CHKERRQ(ierr);
379df311e6cSXuan Zhou   PetscFunctionReturn(0);
380df311e6cSXuan Zhou }
381df311e6cSXuan Zhou 
382*4222ddf1SHong Zhang /* --------------------------------------- */
383*4222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_Elemental_AB(Mat C)
384*4222ddf1SHong Zhang {
385*4222ddf1SHong Zhang   PetscFunctionBegin;
386*4222ddf1SHong Zhang   C->ops->matmultsymbolic = MatMatMultSymbolic_Elemental;
387*4222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_AB;
388*4222ddf1SHong Zhang   PetscFunctionReturn(0);
389*4222ddf1SHong Zhang }
390*4222ddf1SHong Zhang 
391*4222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_Elemental_ABt(Mat C)
392*4222ddf1SHong Zhang {
393*4222ddf1SHong Zhang   PetscFunctionBegin;
394*4222ddf1SHong Zhang   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_Elemental;
395*4222ddf1SHong Zhang   C->ops->productsymbolic          = MatProductSymbolic_ABt;
396*4222ddf1SHong Zhang   PetscFunctionReturn(0);
397*4222ddf1SHong Zhang }
398*4222ddf1SHong Zhang 
399*4222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_Elemental(Mat C)
400*4222ddf1SHong Zhang {
401*4222ddf1SHong Zhang   PetscErrorCode ierr;
402*4222ddf1SHong Zhang   Mat_Product    *product = C->product;
403*4222ddf1SHong Zhang 
404*4222ddf1SHong Zhang   PetscFunctionBegin;
405*4222ddf1SHong Zhang   switch (product->type) {
406*4222ddf1SHong Zhang   case MATPRODUCT_AB:
407*4222ddf1SHong Zhang     ierr = MatProductSetFromOptions_Elemental_AB(C);CHKERRQ(ierr);
408*4222ddf1SHong Zhang     break;
409*4222ddf1SHong Zhang   case MATPRODUCT_ABt:
410*4222ddf1SHong Zhang     ierr = MatProductSetFromOptions_Elemental_ABt(C);CHKERRQ(ierr);
411*4222ddf1SHong Zhang     break;
412*4222ddf1SHong Zhang   default: SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"MatProduct type is not supported");
413*4222ddf1SHong Zhang   }
414*4222ddf1SHong Zhang   PetscFunctionReturn(0);
415*4222ddf1SHong Zhang }
416*4222ddf1SHong Zhang /* --------------------------------------- */
417*4222ddf1SHong Zhang 
418a9d89745SXuan Zhou static PetscErrorCode MatGetDiagonal_Elemental(Mat A,Vec D)
41961119200SXuan Zhou {
420a9d89745SXuan Zhou   PetscInt        i,nrows,ncols,nD,rrank,ridx,crank,cidx;
421a9d89745SXuan Zhou   Mat_Elemental   *a = (Mat_Elemental*)A->data;
42261119200SXuan Zhou   PetscErrorCode  ierr;
423a9d89745SXuan Zhou   PetscElemScalar v;
424ce94432eSBarry Smith   MPI_Comm        comm;
42561119200SXuan Zhou 
42661119200SXuan Zhou   PetscFunctionBegin;
427ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
428a9d89745SXuan Zhou   ierr = MatGetSize(A,&nrows,&ncols);CHKERRQ(ierr);
429a9d89745SXuan Zhou   nD = nrows>ncols ? ncols : nrows;
430a9d89745SXuan Zhou   for (i=0; i<nD; i++) {
431a9d89745SXuan Zhou     PetscInt erow,ecol;
432a9d89745SXuan Zhou     P2RO(A,0,i,&rrank,&ridx);
433a9d89745SXuan Zhou     RO2E(A,0,rrank,ridx,&erow);
434a9d89745SXuan Zhou     if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
435a9d89745SXuan Zhou     P2RO(A,1,i,&crank,&cidx);
436a9d89745SXuan Zhou     RO2E(A,1,crank,cidx,&ecol);
437a9d89745SXuan Zhou     if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
438a9d89745SXuan Zhou     v = a->emat->Get(erow,ecol);
4397c8b904fSSatish Balay     ierr = VecSetValues(D,1,&i,(PetscScalar*)&v,INSERT_VALUES);CHKERRQ(ierr);
440ade3cc5eSXuan Zhou   }
441a9d89745SXuan Zhou   ierr = VecAssemblyBegin(D);CHKERRQ(ierr);
442a9d89745SXuan Zhou   ierr = VecAssemblyEnd(D);CHKERRQ(ierr);
44361119200SXuan Zhou   PetscFunctionReturn(0);
44461119200SXuan Zhou }
44561119200SXuan Zhou 
446ade3cc5eSXuan Zhou static PetscErrorCode MatDiagonalScale_Elemental(Mat X,Vec L,Vec R)
447ade3cc5eSXuan Zhou {
448ade3cc5eSXuan Zhou   Mat_Elemental         *x = (Mat_Elemental*)X->data;
449ade3cc5eSXuan Zhou   const PetscElemScalar *d;
450ade3cc5eSXuan Zhou   PetscErrorCode        ierr;
451ade3cc5eSXuan Zhou 
452ade3cc5eSXuan Zhou   PetscFunctionBegin;
4539065cd98SJed Brown   if (R) {
454ade3cc5eSXuan Zhou     ierr = VecGetArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr);
455e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de;
4560c18141cSBarry Smith     de.LockedAttach(X->cmap->N,1,*x->grid,0,0,d,X->cmap->n);
457e8146892SSatish Balay     El::DiagonalScale(El::RIGHT,El::NORMAL,de,*x->emat);
458ade3cc5eSXuan Zhou     ierr = VecRestoreArrayRead(R,(const PetscScalar **)&d);CHKERRQ(ierr);
4599065cd98SJed Brown   }
4609065cd98SJed Brown   if (L) {
461ade3cc5eSXuan Zhou     ierr = VecGetArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr);
462e8146892SSatish Balay     El::DistMatrix<PetscElemScalar,El::VC,El::STAR> de;
4630c18141cSBarry Smith     de.LockedAttach(X->rmap->N,1,*x->grid,0,0,d,X->rmap->n);
464e8146892SSatish Balay     El::DiagonalScale(El::LEFT,El::NORMAL,de,*x->emat);
465ade3cc5eSXuan Zhou     ierr = VecRestoreArrayRead(L,(const PetscScalar **)&d);CHKERRQ(ierr);
466ade3cc5eSXuan Zhou   }
467ade3cc5eSXuan Zhou   PetscFunctionReturn(0);
468ade3cc5eSXuan Zhou }
469ade3cc5eSXuan Zhou 
47034fa46e1SFrancesco Ballarin static PetscErrorCode MatMissingDiagonal_Elemental(Mat A,PetscBool *missing,PetscInt *d)
47134fa46e1SFrancesco Ballarin {
47234fa46e1SFrancesco Ballarin   PetscFunctionBegin;
47334fa46e1SFrancesco Ballarin   *missing = PETSC_FALSE;
47434fa46e1SFrancesco Ballarin   PetscFunctionReturn(0);
47534fa46e1SFrancesco Ballarin }
47634fa46e1SFrancesco Ballarin 
477e6dea9dbSXuan Zhou static PetscErrorCode MatScale_Elemental(Mat X,PetscScalar a)
47865b78793SXuan Zhou {
47965b78793SXuan Zhou   Mat_Elemental  *x = (Mat_Elemental*)X->data;
48065b78793SXuan Zhou 
48165b78793SXuan Zhou   PetscFunctionBegin;
482e8146892SSatish Balay   El::Scale((PetscElemScalar)a,*x->emat);
48365b78793SXuan Zhou   PetscFunctionReturn(0);
48465b78793SXuan Zhou }
48565b78793SXuan Zhou 
486f82baa17SHong Zhang /*
487f82baa17SHong Zhang   MatAXPY - Computes Y = a*X + Y.
488f82baa17SHong Zhang */
489e6dea9dbSXuan Zhou static PetscErrorCode MatAXPY_Elemental(Mat Y,PetscScalar a,Mat X,MatStructure str)
490e09a3074SHong Zhang {
491e09a3074SHong Zhang   Mat_Elemental  *x = (Mat_Elemental*)X->data;
492e09a3074SHong Zhang   Mat_Elemental  *y = (Mat_Elemental*)Y->data;
49368446cf8SJed Brown   PetscErrorCode ierr;
494e09a3074SHong Zhang 
495e09a3074SHong Zhang   PetscFunctionBegin;
496e8146892SSatish Balay   El::Axpy((PetscElemScalar)a,*x->emat,*y->emat);
49721f6c9c4SJed Brown   ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
498e09a3074SHong Zhang   PetscFunctionReturn(0);
499e09a3074SHong Zhang }
500e09a3074SHong Zhang 
501d6223691SXuan Zhou static PetscErrorCode MatCopy_Elemental(Mat A,Mat B,MatStructure str)
502d6223691SXuan Zhou {
503d6223691SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
504d6223691SXuan Zhou   Mat_Elemental *b=(Mat_Elemental*)B->data;
505a4ee3bb6SSatish Balay   PetscErrorCode ierr;
506d6223691SXuan Zhou 
507d6223691SXuan Zhou   PetscFunctionBegin;
508e8146892SSatish Balay   El::Copy(*a->emat,*b->emat);
509cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
510d6223691SXuan Zhou   PetscFunctionReturn(0);
511d6223691SXuan Zhou }
512d6223691SXuan Zhou 
513df311e6cSXuan Zhou static PetscErrorCode MatDuplicate_Elemental(Mat A,MatDuplicateOption op,Mat *B)
514df311e6cSXuan Zhou {
515df311e6cSXuan Zhou   Mat            Be;
516ce94432eSBarry Smith   MPI_Comm       comm;
517df311e6cSXuan Zhou   Mat_Elemental  *a=(Mat_Elemental*)A->data;
518df311e6cSXuan Zhou   PetscErrorCode ierr;
519df311e6cSXuan Zhou 
520df311e6cSXuan Zhou   PetscFunctionBegin;
521ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
522df311e6cSXuan Zhou   ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
523df311e6cSXuan Zhou   ierr = MatSetSizes(Be,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
524df311e6cSXuan Zhou   ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
525df311e6cSXuan Zhou   ierr = MatSetUp(Be);CHKERRQ(ierr);
526df311e6cSXuan Zhou   *B = Be;
527df311e6cSXuan Zhou   if (op == MAT_COPY_VALUES) {
528df311e6cSXuan Zhou     Mat_Elemental *b=(Mat_Elemental*)Be->data;
529e8146892SSatish Balay     El::Copy(*a->emat,*b->emat);
530df311e6cSXuan Zhou   }
531df311e6cSXuan Zhou   Be->assembled = PETSC_TRUE;
532df311e6cSXuan Zhou   PetscFunctionReturn(0);
533df311e6cSXuan Zhou }
534df311e6cSXuan Zhou 
535d6223691SXuan Zhou static PetscErrorCode MatTranspose_Elemental(Mat A,MatReuse reuse,Mat *B)
536d6223691SXuan Zhou {
537ec8cb81fSBarry Smith   Mat            Be = *B;
5385262d616SXuan Zhou   PetscErrorCode ierr;
539ce94432eSBarry Smith   MPI_Comm       comm;
5404fe7bbcaSHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data, *b;
541d6223691SXuan Zhou 
542d6223691SXuan Zhou   PetscFunctionBegin;
543ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
5445cb544a0SHong Zhang   /* Only out-of-place supported */
5452847e3fdSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) SETERRQ(comm,PETSC_ERR_SUP,"Only out-of-place supported");
5465262d616SXuan Zhou   if (reuse == MAT_INITIAL_MATRIX) {
5475262d616SXuan Zhou     ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
5485262d616SXuan Zhou     ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
5495262d616SXuan Zhou     ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
5505262d616SXuan Zhou     ierr = MatSetUp(Be);CHKERRQ(ierr);
5515262d616SXuan Zhou     *B = Be;
5525262d616SXuan Zhou   }
5534fe7bbcaSHong Zhang   b = (Mat_Elemental*)Be->data;
554e8146892SSatish Balay   El::Transpose(*a->emat,*b->emat);
5555262d616SXuan Zhou   Be->assembled = PETSC_TRUE;
556d6223691SXuan Zhou   PetscFunctionReturn(0);
557d6223691SXuan Zhou }
558d6223691SXuan Zhou 
559dfcb0403SXuan Zhou static PetscErrorCode MatConjugate_Elemental(Mat A)
560dfcb0403SXuan Zhou {
561dfcb0403SXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
562dfcb0403SXuan Zhou 
563dfcb0403SXuan Zhou   PetscFunctionBegin;
564e8146892SSatish Balay   El::Conjugate(*a->emat);
565dfcb0403SXuan Zhou   PetscFunctionReturn(0);
566dfcb0403SXuan Zhou }
567dfcb0403SXuan Zhou 
5684a29722dSXuan Zhou static PetscErrorCode MatHermitianTranspose_Elemental(Mat A,MatReuse reuse,Mat *B)
5694a29722dSXuan Zhou {
570ec8cb81fSBarry Smith   Mat            Be = *B;
5714a29722dSXuan Zhou   PetscErrorCode ierr;
572ce94432eSBarry Smith   MPI_Comm       comm;
5734a29722dSXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data, *b;
5744a29722dSXuan Zhou 
5754a29722dSXuan Zhou   PetscFunctionBegin;
576ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
5775cb544a0SHong Zhang   /* Only out-of-place supported */
5784a29722dSXuan Zhou   if (reuse == MAT_INITIAL_MATRIX){
5794a29722dSXuan Zhou     ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
5804a29722dSXuan Zhou     ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
5814a29722dSXuan Zhou     ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
5824a29722dSXuan Zhou     ierr = MatSetUp(Be);CHKERRQ(ierr);
5834a29722dSXuan Zhou     *B = Be;
5844a29722dSXuan Zhou   }
5854a29722dSXuan Zhou   b = (Mat_Elemental*)Be->data;
586e8146892SSatish Balay   El::Adjoint(*a->emat,*b->emat);
5874a29722dSXuan Zhou   Be->assembled = PETSC_TRUE;
5884a29722dSXuan Zhou   PetscFunctionReturn(0);
5894a29722dSXuan Zhou }
5904a29722dSXuan Zhou 
5911f881ff8SXuan Zhou static PetscErrorCode MatSolve_Elemental(Mat A,Vec B,Vec X)
5921f881ff8SXuan Zhou {
5931f881ff8SXuan Zhou   Mat_Elemental     *a = (Mat_Elemental*)A->data;
5941f881ff8SXuan Zhou   PetscErrorCode    ierr;
595df311e6cSXuan Zhou   PetscElemScalar   *x;
596ea394475SSatish Balay   PetscInt          pivoting = a->pivoting;
5971f881ff8SXuan Zhou 
5981f881ff8SXuan Zhou   PetscFunctionBegin;
59945cf121fSXuan Zhou   ierr = VecCopy(B,X);CHKERRQ(ierr);
600e6dea9dbSXuan Zhou   ierr = VecGetArray(X,(PetscScalar **)&x);CHKERRQ(ierr);
601ea394475SSatish Balay 
602e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::VC,El::STAR> xe;
6030c18141cSBarry Smith   xe.Attach(A->rmap->N,1,*a->grid,0,0,x,A->rmap->n);
604e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::MC,El::MR> xer(xe);
605fc54b460SXuan Zhou   switch (A->factortype) {
606fc54b460SXuan Zhou   case MAT_FACTOR_LU:
607ea394475SSatish Balay     if (pivoting == 0) {
608e8146892SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,xer);
609ea394475SSatish Balay     } else if (pivoting == 1) {
610ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,xer);
611ea394475SSatish Balay     } else { /* pivoting == 2 */
612ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,xer);
6131f881ff8SXuan Zhou     }
614fc54b460SXuan Zhou     break;
615fc54b460SXuan Zhou   case MAT_FACTOR_CHOLESKY:
616e8146892SSatish Balay     El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,xer);
617fc54b460SXuan Zhou     break;
618fc54b460SXuan Zhou   default:
6194fe7bbcaSHong Zhang     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType");
620fc54b460SXuan Zhou     break;
6211f881ff8SXuan Zhou   }
622ea394475SSatish Balay   El::Copy(xer,xe);
623ea394475SSatish Balay 
624e6dea9dbSXuan Zhou   ierr = VecRestoreArray(X,(PetscScalar **)&x);CHKERRQ(ierr);
6251f881ff8SXuan Zhou   PetscFunctionReturn(0);
6261f881ff8SXuan Zhou }
6271f881ff8SXuan Zhou 
628df311e6cSXuan Zhou static PetscErrorCode MatSolveAdd_Elemental(Mat A,Vec B,Vec Y,Vec X)
629df311e6cSXuan Zhou {
630df311e6cSXuan Zhou   PetscErrorCode    ierr;
631df311e6cSXuan Zhou 
632df311e6cSXuan Zhou   PetscFunctionBegin;
633df311e6cSXuan Zhou   ierr = MatSolve_Elemental(A,B,X);CHKERRQ(ierr);
6343d7f40dbSXuan Zhou   ierr = VecAXPY(X,1,Y);CHKERRQ(ierr);
635df311e6cSXuan Zhou   PetscFunctionReturn(0);
636df311e6cSXuan Zhou }
637df311e6cSXuan Zhou 
638ae844d54SHong Zhang static PetscErrorCode MatMatSolve_Elemental(Mat A,Mat B,Mat X)
639ae844d54SHong Zhang {
6401f0e42cfSHong Zhang   Mat_Elemental *a=(Mat_Elemental*)A->data;
641d6223691SXuan Zhou   Mat_Elemental *b=(Mat_Elemental*)B->data;
6421f0e42cfSHong Zhang   Mat_Elemental *x=(Mat_Elemental*)X->data;
643ea394475SSatish Balay   PetscInt      pivoting = a->pivoting;
6441f0e42cfSHong Zhang 
645ae844d54SHong Zhang   PetscFunctionBegin;
646e8146892SSatish Balay   El::Copy(*b->emat,*x->emat);
647fc54b460SXuan Zhou   switch (A->factortype) {
648fc54b460SXuan Zhou   case MAT_FACTOR_LU:
649ea394475SSatish Balay     if (pivoting == 0) {
650e8146892SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*x->emat);
651ea394475SSatish Balay     } else if (pivoting == 1) {
652ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*x->emat);
653ea394475SSatish Balay     } else {
654ea394475SSatish Balay       El::lu::SolveAfter(El::NORMAL,*a->emat,*a->P,*a->Q,*x->emat);
655d6223691SXuan Zhou     }
656fc54b460SXuan Zhou     break;
657fc54b460SXuan Zhou   case MAT_FACTOR_CHOLESKY:
658e8146892SSatish Balay     El::cholesky::SolveAfter(El::UPPER,El::NORMAL,*a->emat,*x->emat);
659fc54b460SXuan Zhou     break;
660fc54b460SXuan Zhou   default:
6614fe7bbcaSHong Zhang     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType");
662fc54b460SXuan Zhou     break;
663fc54b460SXuan Zhou   }
664ae844d54SHong Zhang   PetscFunctionReturn(0);
665ae844d54SHong Zhang }
666ae844d54SHong Zhang 
667ae844d54SHong Zhang static PetscErrorCode MatLUFactor_Elemental(Mat A,IS row,IS col,const MatFactorInfo *info)
668ae844d54SHong Zhang {
6697c920d81SXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
670124af5d2SSatish Balay   PetscErrorCode ierr;
671ea394475SSatish Balay   PetscInt       pivoting = a->pivoting;
6727c920d81SXuan Zhou 
673ae844d54SHong Zhang   PetscFunctionBegin;
674ea394475SSatish Balay   if (pivoting == 0) {
675e8146892SSatish Balay     El::LU(*a->emat);
676ea394475SSatish Balay   } else if (pivoting == 1) {
677ea394475SSatish Balay     El::LU(*a->emat,*a->P);
678ea394475SSatish Balay   } else {
679ea394475SSatish Balay     El::LU(*a->emat,*a->P,*a->Q);
680d6223691SXuan Zhou   }
6811293973dSHong Zhang   A->factortype = MAT_FACTOR_LU;
682834d3fecSHong Zhang   A->assembled  = PETSC_TRUE;
683f6224b95SHong Zhang 
684f6224b95SHong Zhang   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
685f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype);CHKERRQ(ierr);
686ae844d54SHong Zhang   PetscFunctionReturn(0);
687ae844d54SHong Zhang }
688ae844d54SHong Zhang 
689d7c3f9d8SHong Zhang static PetscErrorCode  MatLUFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info)
690d7c3f9d8SHong Zhang {
691d7c3f9d8SHong Zhang   PetscErrorCode ierr;
692d7c3f9d8SHong Zhang 
693d7c3f9d8SHong Zhang   PetscFunctionBegin;
694d7c3f9d8SHong Zhang   ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
695d7c3f9d8SHong Zhang   ierr = MatLUFactor_Elemental(F,0,0,info);CHKERRQ(ierr);
696d7c3f9d8SHong Zhang   PetscFunctionReturn(0);
697d7c3f9d8SHong Zhang }
698d7c3f9d8SHong Zhang 
699d7c3f9d8SHong Zhang static PetscErrorCode  MatLUFactorSymbolic_Elemental(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
700d7c3f9d8SHong Zhang {
701d7c3f9d8SHong Zhang   PetscFunctionBegin;
702d7c3f9d8SHong Zhang   /* F is create and allocated by MatGetFactor_elemental_petsc(), skip this routine. */
703d7c3f9d8SHong Zhang   PetscFunctionReturn(0);
704d7c3f9d8SHong Zhang }
705d7c3f9d8SHong Zhang 
70645cf121fSXuan Zhou static PetscErrorCode MatCholeskyFactor_Elemental(Mat A,IS perm,const MatFactorInfo *info)
70745cf121fSXuan Zhou {
70845cf121fSXuan Zhou   Mat_Elemental  *a = (Mat_Elemental*)A->data;
709e8146892SSatish Balay   El::DistMatrix<PetscElemScalar,El::MC,El::STAR> d;
710124af5d2SSatish Balay   PetscErrorCode ierr;
71145cf121fSXuan Zhou 
71245cf121fSXuan Zhou   PetscFunctionBegin;
713e8146892SSatish Balay   El::Cholesky(El::UPPER,*a->emat);
714fc54b460SXuan Zhou   A->factortype = MAT_FACTOR_CHOLESKY;
715834d3fecSHong Zhang   A->assembled  = PETSC_TRUE;
716f6224b95SHong Zhang 
717f6224b95SHong Zhang   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
718f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&A->solvertype);CHKERRQ(ierr);
71945cf121fSXuan Zhou   PetscFunctionReturn(0);
72045cf121fSXuan Zhou }
72145cf121fSXuan Zhou 
72279673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info)
72379673f7bSHong Zhang {
724cb76c1d8SXuan Zhou   PetscErrorCode ierr;
725cb76c1d8SXuan Zhou 
726cb76c1d8SXuan Zhou   PetscFunctionBegin;
727cb76c1d8SXuan Zhou   ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
728cb76c1d8SXuan Zhou   ierr = MatCholeskyFactor_Elemental(F,0,info);CHKERRQ(ierr);
729cb76c1d8SXuan Zhou   PetscFunctionReturn(0);
73079673f7bSHong Zhang }
731cb76c1d8SXuan Zhou 
73279673f7bSHong Zhang static PetscErrorCode MatCholeskyFactorSymbolic_Elemental(Mat F,Mat A,IS perm,const MatFactorInfo *info)
73379673f7bSHong Zhang {
73479673f7bSHong Zhang   PetscFunctionBegin;
73579673f7bSHong Zhang   /* F is create and allocated by MatGetFactor_elemental_petsc(), skip this routine. */
73679673f7bSHong Zhang   PetscFunctionReturn(0);
73779673f7bSHong Zhang }
73879673f7bSHong Zhang 
739ea799195SBarry Smith PetscErrorCode MatFactorGetSolverType_elemental_elemental(Mat A,MatSolverType *type)
74015767789SHong Zhang {
74115767789SHong Zhang   PetscFunctionBegin;
74215767789SHong Zhang   *type = MATSOLVERELEMENTAL;
74315767789SHong Zhang   PetscFunctionReturn(0);
74415767789SHong Zhang }
74515767789SHong Zhang 
74615767789SHong Zhang static PetscErrorCode MatGetFactor_elemental_elemental(Mat A,MatFactorType ftype,Mat *F)
7471293973dSHong Zhang {
7481293973dSHong Zhang   Mat            B;
7491293973dSHong Zhang   PetscErrorCode ierr;
7501293973dSHong Zhang 
7511293973dSHong Zhang   PetscFunctionBegin;
7521293973dSHong Zhang   /* Create the factorization matrix */
753ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
7541293973dSHong Zhang   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
7551293973dSHong Zhang   ierr = MatSetType(B,MATELEMENTAL);CHKERRQ(ierr);
7561293973dSHong Zhang   ierr = MatSetUp(B);CHKERRQ(ierr);
7571293973dSHong Zhang   B->factortype = ftype;
75800c67f3bSHong Zhang   ierr = PetscFree(B->solvertype);CHKERRQ(ierr);
75900c67f3bSHong Zhang   ierr = PetscStrallocpy(MATSOLVERELEMENTAL,&B->solvertype);CHKERRQ(ierr);
76000c67f3bSHong Zhang 
7613ca39a21SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatFactorGetSolverType_C",MatFactorGetSolverType_elemental_elemental);CHKERRQ(ierr);
7621293973dSHong Zhang   *F            = B;
7631293973dSHong Zhang   PetscFunctionReturn(0);
7641293973dSHong Zhang }
7651293973dSHong Zhang 
7663ca39a21SBarry Smith PETSC_EXTERN PetscErrorCode MatSolverTypeRegister_Elemental(void)
76742c9c57cSBarry Smith {
76818713533SBarry Smith   PetscErrorCode ierr;
76918713533SBarry Smith 
77042c9c57cSBarry Smith   PetscFunctionBegin;
7713ca39a21SBarry Smith   ierr = MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL,        MAT_FACTOR_LU,MatGetFactor_elemental_elemental);CHKERRQ(ierr);
7723ca39a21SBarry Smith   ierr = MatSolverTypeRegister(MATSOLVERELEMENTAL,MATELEMENTAL,        MAT_FACTOR_CHOLESKY,MatGetFactor_elemental_elemental);CHKERRQ(ierr);
77342c9c57cSBarry Smith   PetscFunctionReturn(0);
77442c9c57cSBarry Smith }
77542c9c57cSBarry Smith 
7761f881ff8SXuan Zhou static PetscErrorCode MatNorm_Elemental(Mat A,NormType type,PetscReal *nrm)
7771f881ff8SXuan Zhou {
7781f881ff8SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
7791f881ff8SXuan Zhou 
7801f881ff8SXuan Zhou   PetscFunctionBegin;
7811f881ff8SXuan Zhou   switch (type){
7821f881ff8SXuan Zhou   case NORM_1:
783e8146892SSatish Balay     *nrm = El::OneNorm(*a->emat);
7841f881ff8SXuan Zhou     break;
7851f881ff8SXuan Zhou   case NORM_FROBENIUS:
786e8146892SSatish Balay     *nrm = El::FrobeniusNorm(*a->emat);
7871f881ff8SXuan Zhou     break;
7881f881ff8SXuan Zhou   case NORM_INFINITY:
789e8146892SSatish Balay     *nrm = El::InfinityNorm(*a->emat);
7901f881ff8SXuan Zhou     break;
7911f881ff8SXuan Zhou   default:
7921f881ff8SXuan Zhou     printf("Error: unsupported norm type!\n");
7931f881ff8SXuan Zhou   }
7941f881ff8SXuan Zhou   PetscFunctionReturn(0);
7951f881ff8SXuan Zhou }
7961f881ff8SXuan Zhou 
7975262d616SXuan Zhou static PetscErrorCode MatZeroEntries_Elemental(Mat A)
7985262d616SXuan Zhou {
7995262d616SXuan Zhou   Mat_Elemental *a=(Mat_Elemental*)A->data;
8005262d616SXuan Zhou 
8015262d616SXuan Zhou   PetscFunctionBegin;
802e8146892SSatish Balay   El::Zero(*a->emat);
8035262d616SXuan Zhou   PetscFunctionReturn(0);
8045262d616SXuan Zhou }
8055262d616SXuan Zhou 
806db31f6deSJed Brown static PetscErrorCode MatGetOwnershipIS_Elemental(Mat A,IS *rows,IS *cols)
807db31f6deSJed Brown {
808db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
809db31f6deSJed Brown   PetscErrorCode ierr;
810db31f6deSJed Brown   PetscInt       i,m,shift,stride,*idx;
811db31f6deSJed Brown 
812db31f6deSJed Brown   PetscFunctionBegin;
813db31f6deSJed Brown   if (rows) {
814db31f6deSJed Brown     m = a->emat->LocalHeight();
815db31f6deSJed Brown     shift = a->emat->ColShift();
816db31f6deSJed Brown     stride = a->emat->ColStride();
817785e854fSJed Brown     ierr = PetscMalloc1(m,&idx);CHKERRQ(ierr);
818db31f6deSJed Brown     for (i=0; i<m; i++) {
819db31f6deSJed Brown       PetscInt rank,offset;
820db31f6deSJed Brown       E2RO(A,0,shift+i*stride,&rank,&offset);
821db31f6deSJed Brown       RO2P(A,0,rank,offset,&idx[i]);
822db31f6deSJed Brown     }
823db31f6deSJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,rows);CHKERRQ(ierr);
824db31f6deSJed Brown   }
825db31f6deSJed Brown   if (cols) {
826db31f6deSJed Brown     m = a->emat->LocalWidth();
827db31f6deSJed Brown     shift = a->emat->RowShift();
828db31f6deSJed Brown     stride = a->emat->RowStride();
829785e854fSJed Brown     ierr = PetscMalloc1(m,&idx);CHKERRQ(ierr);
830db31f6deSJed Brown     for (i=0; i<m; i++) {
831db31f6deSJed Brown       PetscInt rank,offset;
832db31f6deSJed Brown       E2RO(A,1,shift+i*stride,&rank,&offset);
833db31f6deSJed Brown       RO2P(A,1,rank,offset,&idx[i]);
834db31f6deSJed Brown     }
835db31f6deSJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,cols);CHKERRQ(ierr);
836db31f6deSJed Brown   }
837db31f6deSJed Brown   PetscFunctionReturn(0);
838db31f6deSJed Brown }
839db31f6deSJed Brown 
84019fd82e9SBarry Smith static PetscErrorCode MatConvert_Elemental_Dense(Mat A,MatType newtype,MatReuse reuse,Mat *B)
841af295397SXuan Zhou {
8422ef0cf24SXuan Zhou   Mat                Bmpi;
843af295397SXuan Zhou   Mat_Elemental      *a = (Mat_Elemental*)A->data;
844ce94432eSBarry Smith   MPI_Comm           comm;
8452ef0cf24SXuan Zhou   PetscErrorCode     ierr;
846fa9e26c8SHong Zhang   IS                 isrows,iscols;
847fa9e26c8SHong Zhang   PetscInt           rrank,ridx,crank,cidx,nrows,ncols,i,j,erow,ecol,elrow,elcol;
848fa9e26c8SHong Zhang   const PetscInt     *rows,*cols;
849df311e6cSXuan Zhou   PetscElemScalar    v;
850fa9e26c8SHong Zhang   const El::Grid     &grid = a->emat->Grid();
851af295397SXuan Zhou 
852af295397SXuan Zhou   PetscFunctionBegin;
853ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
854a000e53bSHong Zhang 
855de0a22f0SHong Zhang   if (reuse == MAT_REUSE_MATRIX) {
856de0a22f0SHong Zhang     Bmpi = *B;
857de0a22f0SHong Zhang   } else {
858af295397SXuan Zhou     ierr = MatCreate(comm,&Bmpi);CHKERRQ(ierr);
859af295397SXuan Zhou     ierr = MatSetSizes(Bmpi,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
8602ef0cf24SXuan Zhou     ierr = MatSetType(Bmpi,MATDENSE);CHKERRQ(ierr);
861af295397SXuan Zhou     ierr = MatSetUp(Bmpi);CHKERRQ(ierr);
862de0a22f0SHong Zhang   }
863fa9e26c8SHong Zhang 
864fa9e26c8SHong Zhang   /* Get local entries of A */
865fa9e26c8SHong Zhang   ierr = MatGetOwnershipIS(A,&isrows,&iscols);CHKERRQ(ierr);
866fa9e26c8SHong Zhang   ierr = ISGetLocalSize(isrows,&nrows);CHKERRQ(ierr);
867fa9e26c8SHong Zhang   ierr = ISGetIndices(isrows,&rows);CHKERRQ(ierr);
868fa9e26c8SHong Zhang   ierr = ISGetLocalSize(iscols,&ncols);CHKERRQ(ierr);
869fa9e26c8SHong Zhang   ierr = ISGetIndices(iscols,&cols);CHKERRQ(ierr);
870fa9e26c8SHong Zhang 
87157299f2fSHong Zhang   if (a->roworiented) {
8722ef0cf24SXuan Zhou     for (i=0; i<nrows; i++) {
873fa9e26c8SHong Zhang       P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */
8742ef0cf24SXuan Zhou       RO2E(A,0,rrank,ridx,&erow);
8752ef0cf24SXuan Zhou       if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
8762ef0cf24SXuan Zhou       for (j=0; j<ncols; j++) {
877fa9e26c8SHong Zhang         P2RO(A,1,cols[j],&crank,&cidx);
8782ef0cf24SXuan Zhou         RO2E(A,1,crank,cidx,&ecol);
8792ef0cf24SXuan Zhou         if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
880fa9e26c8SHong Zhang 
881fa9e26c8SHong Zhang         elrow = erow / grid.MCSize(); /* Elemental local row index */
882fa9e26c8SHong Zhang         elcol = ecol / grid.MRSize(); /* Elemental local column index */
883fa9e26c8SHong Zhang         v = a->emat->GetLocal(elrow,elcol);
884fa9e26c8SHong Zhang         ierr = MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr);
8852ef0cf24SXuan Zhou       }
8862ef0cf24SXuan Zhou     }
88757299f2fSHong Zhang   } else { /* column-oriented */
88857299f2fSHong Zhang     for (j=0; j<ncols; j++) {
88957299f2fSHong Zhang       P2RO(A,1,cols[j],&crank,&cidx);
89057299f2fSHong Zhang       RO2E(A,1,crank,cidx,&ecol);
89157299f2fSHong Zhang       if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
89257299f2fSHong Zhang       for (i=0; i<nrows; i++) {
89357299f2fSHong Zhang         P2RO(A,0,rows[i],&rrank,&ridx); /* convert indices between PETSc <-> (Rank,Offset) <-> Elemental */
89457299f2fSHong Zhang         RO2E(A,0,rrank,ridx,&erow);
89557299f2fSHong Zhang         if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
89657299f2fSHong Zhang 
89757299f2fSHong Zhang         elrow = erow / grid.MCSize(); /* Elemental local row index */
89857299f2fSHong Zhang         elcol = ecol / grid.MRSize(); /* Elemental local column index */
89957299f2fSHong Zhang         v = a->emat->GetLocal(elrow,elcol);
90057299f2fSHong Zhang         ierr = MatSetValues(Bmpi,1,&rows[i],1,&cols[j],(PetscScalar *)&v,INSERT_VALUES);CHKERRQ(ierr);
90157299f2fSHong Zhang       }
90257299f2fSHong Zhang     }
90357299f2fSHong Zhang   }
904af295397SXuan Zhou   ierr = MatAssemblyBegin(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
905af295397SXuan Zhou   ierr = MatAssemblyEnd(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
906511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
90728be2f97SBarry Smith     ierr = MatHeaderReplace(A,&Bmpi);CHKERRQ(ierr);
908c4ad791aSXuan Zhou   } else {
909c4ad791aSXuan Zhou     *B = Bmpi;
910c4ad791aSXuan Zhou   }
911fa9e26c8SHong Zhang   ierr = ISDestroy(&isrows);CHKERRQ(ierr);
912fa9e26c8SHong Zhang   ierr = ISDestroy(&iscols);CHKERRQ(ierr);
913af295397SXuan Zhou   PetscFunctionReturn(0);
914af295397SXuan Zhou }
915af295397SXuan Zhou 
916cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
917af8000cdSHong Zhang {
918af8000cdSHong Zhang   Mat               mat_elemental;
919af8000cdSHong Zhang   PetscErrorCode    ierr;
920af8000cdSHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols;
921af8000cdSHong Zhang   const PetscInt    *cols;
922af8000cdSHong Zhang   const PetscScalar *vals;
923af8000cdSHong Zhang 
924af8000cdSHong 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 {
929af8000cdSHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
930af8000cdSHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
931af8000cdSHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
932af8000cdSHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
933bdeae278SStefano Zampini   }
934af8000cdSHong Zhang   for (row=0; row<M; row++) {
935af8000cdSHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
936bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
937af8000cdSHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
938af8000cdSHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
939af8000cdSHong Zhang   }
940af8000cdSHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
941af8000cdSHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
942af8000cdSHong Zhang 
943511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
94428be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
945af8000cdSHong Zhang   } else {
946af8000cdSHong Zhang     *newmat = mat_elemental;
947af8000cdSHong Zhang   }
948af8000cdSHong Zhang   PetscFunctionReturn(0);
949af8000cdSHong Zhang }
950af8000cdSHong Zhang 
951cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
9525d7652ecSHong Zhang {
9535d7652ecSHong Zhang   Mat               mat_elemental;
9545d7652ecSHong Zhang   PetscErrorCode    ierr;
9555d7652ecSHong Zhang   PetscInt          row,ncols,rstart=A->rmap->rstart,rend=A->rmap->rend,j;
9565d7652ecSHong Zhang   const PetscInt    *cols;
9575d7652ecSHong Zhang   const PetscScalar *vals;
9585d7652ecSHong Zhang 
9595d7652ecSHong Zhang   PetscFunctionBegin;
960bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
961bdeae278SStefano Zampini     mat_elemental = *newmat;
962bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
963bdeae278SStefano Zampini   } else {
9645d7652ecSHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
9655d7652ecSHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
9665d7652ecSHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
9675d7652ecSHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
968bdeae278SStefano Zampini   }
9695d7652ecSHong Zhang   for (row=rstart; row<rend; row++) {
9705d7652ecSHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
9715d7652ecSHong Zhang     for (j=0; j<ncols; j++) {
972bdeae278SStefano Zampini       /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
9735d7652ecSHong Zhang       ierr = MatSetValues(mat_elemental,1,&row,1,&cols[j],&vals[j],ADD_VALUES);CHKERRQ(ierr);
9745d7652ecSHong Zhang     }
9755d7652ecSHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
9765d7652ecSHong Zhang   }
9775d7652ecSHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9785d7652ecSHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9795d7652ecSHong Zhang 
980511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
98128be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
9825d7652ecSHong Zhang   } else {
9835d7652ecSHong Zhang     *newmat = mat_elemental;
9845d7652ecSHong Zhang   }
9855d7652ecSHong Zhang   PetscFunctionReturn(0);
9865d7652ecSHong Zhang }
9875d7652ecSHong Zhang 
988cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_SeqSBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
9896214f412SHong Zhang {
9906214f412SHong Zhang   Mat               mat_elemental;
9916214f412SHong Zhang   PetscErrorCode    ierr;
9926214f412SHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols,j;
9936214f412SHong Zhang   const PetscInt    *cols;
9946214f412SHong Zhang   const PetscScalar *vals;
9956214f412SHong Zhang 
9966214f412SHong Zhang   PetscFunctionBegin;
997bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
998bdeae278SStefano Zampini     mat_elemental = *newmat;
999bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
1000bdeae278SStefano Zampini   } else {
10016214f412SHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
10026214f412SHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
10036214f412SHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
10046214f412SHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
1005bdeae278SStefano Zampini   }
10066214f412SHong Zhang   ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr);
10076214f412SHong Zhang   for (row=0; row<M; row++) {
10086214f412SHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
1009bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
10106214f412SHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
10116214f412SHong Zhang     for (j=0; j<ncols; j++) { /* lower triangular part */
1012eb1ec7c1SStefano Zampini       PetscScalar v;
10136214f412SHong Zhang       if (cols[j] == row) continue;
1014eb1ec7c1SStefano Zampini       v    = A->hermitian ? PetscConj(vals[j]) : vals[j];
1015eb1ec7c1SStefano Zampini       ierr = MatSetValues(mat_elemental,1,&cols[j],1,&row,&v,ADD_VALUES);CHKERRQ(ierr);
10166214f412SHong Zhang     }
10176214f412SHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
10186214f412SHong Zhang   }
10196214f412SHong Zhang   ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr);
10206214f412SHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10216214f412SHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10226214f412SHong Zhang 
1023511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
102428be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
10256214f412SHong Zhang   } else {
10266214f412SHong Zhang     *newmat = mat_elemental;
10276214f412SHong Zhang   }
10286214f412SHong Zhang   PetscFunctionReturn(0);
10296214f412SHong Zhang }
10306214f412SHong Zhang 
1031cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPISBAIJ_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
10326214f412SHong Zhang {
10336214f412SHong Zhang   Mat               mat_elemental;
10346214f412SHong Zhang   PetscErrorCode    ierr;
10356214f412SHong Zhang   PetscInt          M=A->rmap->N,N=A->cmap->N,row,ncols,j,rstart=A->rmap->rstart,rend=A->rmap->rend;
10366214f412SHong Zhang   const PetscInt    *cols;
10376214f412SHong Zhang   const PetscScalar *vals;
10386214f412SHong Zhang 
10396214f412SHong Zhang   PetscFunctionBegin;
1040bdeae278SStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
1041bdeae278SStefano Zampini     mat_elemental = *newmat;
1042bdeae278SStefano Zampini     ierr = MatZeroEntries(mat_elemental);CHKERRQ(ierr);
1043bdeae278SStefano Zampini   } else {
10446214f412SHong Zhang     ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
10456214f412SHong Zhang     ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
10466214f412SHong Zhang     ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
10476214f412SHong Zhang     ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
1048bdeae278SStefano Zampini   }
10496214f412SHong Zhang   ierr = MatGetRowUpperTriangular(A);CHKERRQ(ierr);
10506214f412SHong Zhang   for (row=rstart; row<rend; row++) {
10516214f412SHong Zhang     ierr = MatGetRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
1052bdeae278SStefano Zampini     /* PETSc-Elemental interface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
10536214f412SHong Zhang     ierr = MatSetValues(mat_elemental,1,&row,ncols,cols,vals,ADD_VALUES);CHKERRQ(ierr);
10546214f412SHong Zhang     for (j=0; j<ncols; j++) { /* lower triangular part */
1055eb1ec7c1SStefano Zampini       PetscScalar v;
10566214f412SHong Zhang       if (cols[j] == row) continue;
1057eb1ec7c1SStefano Zampini       v    = A->hermitian ? PetscConj(vals[j]) : vals[j];
1058eb1ec7c1SStefano Zampini       ierr = MatSetValues(mat_elemental,1,&cols[j],1,&row,&v,ADD_VALUES);CHKERRQ(ierr);
10596214f412SHong Zhang     }
10606214f412SHong Zhang     ierr = MatRestoreRow(A,row,&ncols,&cols,&vals);CHKERRQ(ierr);
10616214f412SHong Zhang   }
10626214f412SHong Zhang   ierr = MatRestoreRowUpperTriangular(A);CHKERRQ(ierr);
10636214f412SHong Zhang   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10646214f412SHong Zhang   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10656214f412SHong Zhang 
1066511c6705SHong Zhang   if (reuse == MAT_INPLACE_MATRIX) {
106728be2f97SBarry Smith     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
10686214f412SHong Zhang   } else {
10696214f412SHong Zhang     *newmat = mat_elemental;
10706214f412SHong Zhang   }
10716214f412SHong Zhang   PetscFunctionReturn(0);
10726214f412SHong Zhang }
10736214f412SHong Zhang 
1074db31f6deSJed Brown static PetscErrorCode MatDestroy_Elemental(Mat A)
1075db31f6deSJed Brown {
1076db31f6deSJed Brown   Mat_Elemental      *a = (Mat_Elemental*)A->data;
1077db31f6deSJed Brown   PetscErrorCode     ierr;
10785e9f5b67SHong Zhang   Mat_Elemental_Grid *commgrid;
10795e9f5b67SHong Zhang   PetscBool          flg;
10805e9f5b67SHong Zhang   MPI_Comm           icomm;
1081db31f6deSJed Brown 
1082db31f6deSJed Brown   PetscFunctionBegin;
1083db31f6deSJed Brown   delete a->emat;
1084ea394475SSatish Balay   delete a->P;
1085ea394475SSatish Balay   delete a->Q;
10865e9f5b67SHong Zhang 
1087e8146892SSatish Balay   El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A));
10880c18141cSBarry Smith   ierr = PetscCommDuplicate(cxxcomm.comm,&icomm,NULL);CHKERRQ(ierr);
108947435625SJed Brown   ierr = MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr);
10905e9f5b67SHong Zhang   if (--commgrid->grid_refct == 0) {
10915e9f5b67SHong Zhang     delete commgrid->grid;
10925e9f5b67SHong Zhang     ierr = PetscFree(commgrid);CHKERRQ(ierr);
109347435625SJed Brown     ierr = MPI_Comm_free_keyval(&Petsc_Elemental_keyval);CHKERRQ(ierr);
10945e9f5b67SHong Zhang   }
10955e9f5b67SHong Zhang   ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr);
1096bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",NULL);CHKERRQ(ierr);
10973ca39a21SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatFactorGetSolverType_C",NULL);CHKERRQ(ierr);
1098db31f6deSJed Brown   ierr = PetscFree(A->data);CHKERRQ(ierr);
1099db31f6deSJed Brown   PetscFunctionReturn(0);
1100db31f6deSJed Brown }
1101db31f6deSJed Brown 
1102db31f6deSJed Brown PetscErrorCode MatSetUp_Elemental(Mat A)
1103db31f6deSJed Brown {
1104db31f6deSJed Brown   Mat_Elemental  *a = (Mat_Elemental*)A->data;
1105db31f6deSJed Brown   PetscErrorCode ierr;
1106f19600a0SHong Zhang   MPI_Comm       comm;
1107db31f6deSJed Brown   PetscMPIInt    rsize,csize;
1108f19600a0SHong Zhang   PetscInt       n;
1109db31f6deSJed Brown 
1110db31f6deSJed Brown   PetscFunctionBegin;
1111db31f6deSJed Brown   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1112db31f6deSJed Brown   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1113db31f6deSJed Brown 
1114f19600a0SHong Zhang   /* Check if local row and clomun sizes are equally distributed.
1115f19600a0SHong Zhang      Jed: Elemental uses "element" cyclic ordering so the sizes need to match that
1116f19600a0SHong Zhang      exactly.  The strategy in MatElemental is for PETSc to implicitly permute to block ordering (like would be returned by
1117f19600a0SHong Zhang      PetscSplitOwnership(comm,&n,&N)), at which point Elemental matrices can act on PETSc vectors without redistributing the vectors. */
1118f19600a0SHong Zhang   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1119f19600a0SHong Zhang   n = PETSC_DECIDE;
1120f19600a0SHong Zhang   ierr = PetscSplitOwnership(comm,&n,&A->rmap->N);CHKERRQ(ierr);
1121f19600a0SHong 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);
1122f19600a0SHong Zhang 
1123f19600a0SHong Zhang   n = PETSC_DECIDE;
1124f19600a0SHong Zhang   ierr = PetscSplitOwnership(comm,&n,&A->cmap->N);CHKERRQ(ierr);
1125f19600a0SHong 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);
1126f19600a0SHong Zhang 
1127efb79153SJack Poulson   a->emat->Resize(A->rmap->N,A->cmap->N);CHKERRQ(ierr);
1128e8146892SSatish Balay   El::Zero(*a->emat);
1129db31f6deSJed Brown 
1130db31f6deSJed Brown   ierr = MPI_Comm_size(A->rmap->comm,&rsize);CHKERRQ(ierr);
1131db31f6deSJed Brown   ierr = MPI_Comm_size(A->cmap->comm,&csize);CHKERRQ(ierr);
1132ce94432eSBarry Smith   if (csize != rsize) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Cannot use row and column communicators of different sizes");
1133db31f6deSJed Brown   a->commsize = rsize;
1134db31f6deSJed Brown   a->mr[0] = A->rmap->N % rsize; if (!a->mr[0]) a->mr[0] = rsize;
1135db31f6deSJed Brown   a->mr[1] = A->cmap->N % csize; if (!a->mr[1]) a->mr[1] = csize;
1136db31f6deSJed Brown   a->m[0]  = A->rmap->N / rsize + (a->mr[0] != rsize);
1137db31f6deSJed Brown   a->m[1]  = A->cmap->N / csize + (a->mr[1] != csize);
1138db31f6deSJed Brown   PetscFunctionReturn(0);
1139db31f6deSJed Brown }
1140db31f6deSJed Brown 
1141aae2c449SHong Zhang PetscErrorCode MatAssemblyBegin_Elemental(Mat A, MatAssemblyType type)
1142aae2c449SHong Zhang {
1143aae2c449SHong Zhang   Mat_Elemental  *a = (Mat_Elemental*)A->data;
1144aae2c449SHong Zhang 
1145aae2c449SHong Zhang   PetscFunctionBegin;
1146fbbcb730SJack Poulson   /* printf("Calling ProcessQueues\n"); */
1147fbbcb730SJack Poulson   a->emat->ProcessQueues();
1148fbbcb730SJack Poulson   /* printf("Finished ProcessQueues\n"); */
1149aae2c449SHong Zhang   PetscFunctionReturn(0);
1150aae2c449SHong Zhang }
1151aae2c449SHong Zhang 
1152aae2c449SHong Zhang PetscErrorCode MatAssemblyEnd_Elemental(Mat A, MatAssemblyType type)
1153aae2c449SHong Zhang {
1154aae2c449SHong Zhang   PetscFunctionBegin;
1155aae2c449SHong Zhang   /* Currently does nothing */
1156aae2c449SHong Zhang   PetscFunctionReturn(0);
1157aae2c449SHong Zhang }
1158aae2c449SHong Zhang 
11597b30e0f1SHong Zhang PetscErrorCode MatLoad_Elemental(Mat newMat, PetscViewer viewer)
11607b30e0f1SHong Zhang {
11617b30e0f1SHong Zhang   PetscErrorCode ierr;
11627b30e0f1SHong Zhang   Mat            Adense,Ae;
11637b30e0f1SHong Zhang   MPI_Comm       comm;
11647b30e0f1SHong Zhang 
11657b30e0f1SHong Zhang   PetscFunctionBegin;
11667b30e0f1SHong Zhang   ierr = PetscObjectGetComm((PetscObject)newMat,&comm);CHKERRQ(ierr);
11677b30e0f1SHong Zhang   ierr = MatCreate(comm,&Adense);CHKERRQ(ierr);
11687b30e0f1SHong Zhang   ierr = MatSetType(Adense,MATDENSE);CHKERRQ(ierr);
11697b30e0f1SHong Zhang   ierr = MatLoad(Adense,viewer);CHKERRQ(ierr);
11707b30e0f1SHong Zhang   ierr = MatConvert(Adense, MATELEMENTAL, MAT_INITIAL_MATRIX,&Ae);CHKERRQ(ierr);
11717b30e0f1SHong Zhang   ierr = MatDestroy(&Adense);CHKERRQ(ierr);
117228be2f97SBarry Smith   ierr = MatHeaderReplace(newMat,&Ae);CHKERRQ(ierr);
11737b30e0f1SHong Zhang   PetscFunctionReturn(0);
11747b30e0f1SHong Zhang }
11757b30e0f1SHong Zhang 
117640d92e34SHong Zhang /* -------------------------------------------------------------------*/
117740d92e34SHong Zhang static struct _MatOps MatOps_Values = {
117840d92e34SHong Zhang        MatSetValues_Elemental,
117940d92e34SHong Zhang        0,
118040d92e34SHong Zhang        0,
118140d92e34SHong Zhang        MatMult_Elemental,
118240d92e34SHong Zhang /* 4*/ MatMultAdd_Elemental,
11839426833fSXuan Zhou        MatMultTranspose_Elemental,
1184e883f9d5SXuan Zhou        MatMultTransposeAdd_Elemental,
118540d92e34SHong Zhang        MatSolve_Elemental,
1186df311e6cSXuan Zhou        MatSolveAdd_Elemental,
11872ef15aa2SHong Zhang        0,
11882ef15aa2SHong Zhang /*10*/ 0,
118940d92e34SHong Zhang        MatLUFactor_Elemental,
119040d92e34SHong Zhang        MatCholeskyFactor_Elemental,
119140d92e34SHong Zhang        0,
119240d92e34SHong Zhang        MatTranspose_Elemental,
119340d92e34SHong Zhang /*15*/ MatGetInfo_Elemental,
119440d92e34SHong Zhang        0,
119561119200SXuan Zhou        MatGetDiagonal_Elemental,
1196ade3cc5eSXuan Zhou        MatDiagonalScale_Elemental,
119740d92e34SHong Zhang        MatNorm_Elemental,
119840d92e34SHong Zhang /*20*/ MatAssemblyBegin_Elemental,
119940d92e34SHong Zhang        MatAssemblyEnd_Elemental,
120032d7a744SHong Zhang        MatSetOption_Elemental,
120140d92e34SHong Zhang        MatZeroEntries_Elemental,
120240d92e34SHong Zhang /*24*/ 0,
120340d92e34SHong Zhang        MatLUFactorSymbolic_Elemental,
120440d92e34SHong Zhang        MatLUFactorNumeric_Elemental,
120540d92e34SHong Zhang        MatCholeskyFactorSymbolic_Elemental,
120640d92e34SHong Zhang        MatCholeskyFactorNumeric_Elemental,
120740d92e34SHong Zhang /*29*/ MatSetUp_Elemental,
120840d92e34SHong Zhang        0,
120940d92e34SHong Zhang        0,
121040d92e34SHong Zhang        0,
121140d92e34SHong Zhang        0,
1212df311e6cSXuan Zhou /*34*/ MatDuplicate_Elemental,
121340d92e34SHong Zhang        0,
121440d92e34SHong Zhang        0,
121540d92e34SHong Zhang        0,
121640d92e34SHong Zhang        0,
121740d92e34SHong Zhang /*39*/ MatAXPY_Elemental,
121840d92e34SHong Zhang        0,
121940d92e34SHong Zhang        0,
122040d92e34SHong Zhang        0,
122140d92e34SHong Zhang        MatCopy_Elemental,
122240d92e34SHong Zhang /*44*/ 0,
122340d92e34SHong Zhang        MatScale_Elemental,
12247d68702bSBarry Smith        MatShift_Basic,
122540d92e34SHong Zhang        0,
122640d92e34SHong Zhang        0,
122740d92e34SHong Zhang /*49*/ 0,
122840d92e34SHong Zhang        0,
122940d92e34SHong Zhang        0,
123040d92e34SHong Zhang        0,
123140d92e34SHong Zhang        0,
123240d92e34SHong Zhang /*54*/ 0,
123340d92e34SHong Zhang        0,
123440d92e34SHong Zhang        0,
123540d92e34SHong Zhang        0,
123640d92e34SHong Zhang        0,
123740d92e34SHong Zhang /*59*/ 0,
123840d92e34SHong Zhang        MatDestroy_Elemental,
123940d92e34SHong Zhang        MatView_Elemental,
124040d92e34SHong Zhang        0,
124140d92e34SHong Zhang        0,
124240d92e34SHong Zhang /*64*/ 0,
124340d92e34SHong Zhang        0,
124440d92e34SHong Zhang        0,
124540d92e34SHong Zhang        0,
124640d92e34SHong Zhang        0,
124740d92e34SHong Zhang /*69*/ 0,
124840d92e34SHong Zhang        0,
12492ef0cf24SXuan Zhou        MatConvert_Elemental_Dense,
125040d92e34SHong Zhang        0,
125140d92e34SHong Zhang        0,
125240d92e34SHong Zhang /*74*/ 0,
125340d92e34SHong Zhang        0,
125440d92e34SHong Zhang        0,
125540d92e34SHong Zhang        0,
125640d92e34SHong Zhang        0,
125740d92e34SHong Zhang /*79*/ 0,
125840d92e34SHong Zhang        0,
125940d92e34SHong Zhang        0,
126040d92e34SHong Zhang        0,
12617b30e0f1SHong Zhang        MatLoad_Elemental,
126240d92e34SHong Zhang /*84*/ 0,
126340d92e34SHong Zhang        0,
126440d92e34SHong Zhang        0,
126540d92e34SHong Zhang        0,
126640d92e34SHong Zhang        0,
1267*4222ddf1SHong Zhang /*89*/ 0,
1268*4222ddf1SHong Zhang        0,
126940d92e34SHong Zhang        MatMatMultNumeric_Elemental,
127040d92e34SHong Zhang        0,
127140d92e34SHong Zhang        0,
127240d92e34SHong Zhang /*94*/ 0,
1273*4222ddf1SHong Zhang        0,
1274*4222ddf1SHong Zhang        0,
1275df311e6cSXuan Zhou        MatMatTransposeMultNumeric_Elemental,
127640d92e34SHong Zhang        0,
1277*4222ddf1SHong Zhang /*99*/ MatProductSetFromOptions_Elemental,
127840d92e34SHong Zhang        0,
127940d92e34SHong Zhang        0,
1280dfcb0403SXuan Zhou        MatConjugate_Elemental,
128140d92e34SHong Zhang        0,
128240d92e34SHong Zhang /*104*/0,
128340d92e34SHong Zhang        0,
128440d92e34SHong Zhang        0,
128540d92e34SHong Zhang        0,
128640d92e34SHong Zhang        0,
128740d92e34SHong Zhang /*109*/MatMatSolve_Elemental,
128840d92e34SHong Zhang        0,
128940d92e34SHong Zhang        0,
129040d92e34SHong Zhang        0,
129134fa46e1SFrancesco Ballarin        MatMissingDiagonal_Elemental,
129240d92e34SHong Zhang /*114*/0,
129340d92e34SHong Zhang        0,
129440d92e34SHong Zhang        0,
129540d92e34SHong Zhang        0,
129640d92e34SHong Zhang        0,
129740d92e34SHong Zhang /*119*/0,
12984a29722dSXuan Zhou        MatHermitianTranspose_Elemental,
129940d92e34SHong Zhang        0,
130040d92e34SHong Zhang        0,
130140d92e34SHong Zhang        0,
130240d92e34SHong Zhang /*124*/0,
130340d92e34SHong Zhang        0,
130440d92e34SHong Zhang        0,
130540d92e34SHong Zhang        0,
130640d92e34SHong Zhang        0,
130740d92e34SHong Zhang /*129*/0,
130840d92e34SHong Zhang        0,
130940d92e34SHong Zhang        0,
131040d92e34SHong Zhang        0,
131140d92e34SHong Zhang        0,
131240d92e34SHong Zhang /*134*/0,
131340d92e34SHong Zhang        0,
131440d92e34SHong Zhang        0,
131540d92e34SHong Zhang        0,
1316*4222ddf1SHong Zhang        0,
1317*4222ddf1SHong Zhang        0,
1318*4222ddf1SHong Zhang /*140*/0,
1319*4222ddf1SHong Zhang        0,
1320*4222ddf1SHong Zhang        0,
1321*4222ddf1SHong Zhang        0,
1322*4222ddf1SHong Zhang        0,
1323*4222ddf1SHong Zhang /*145*/0,
1324*4222ddf1SHong Zhang        0,
132540d92e34SHong Zhang        0
132640d92e34SHong Zhang };
132740d92e34SHong Zhang 
1328ed36708cSHong Zhang /*MC
1329ed36708cSHong Zhang    MATELEMENTAL = "elemental" - A matrix type for dense matrices using the Elemental package
1330ed36708cSHong Zhang 
1331c2b89b5dSBarry Smith   Use ./configure --download-elemental to install PETSc to use Elemental
1332c2b89b5dSBarry Smith 
13333ca39a21SBarry Smith   Use -pc_type lu -pc_factor_mat_solver_type elemental to use this direct solver
1334c2b89b5dSBarry Smith 
1335ed36708cSHong Zhang    Options Database Keys:
13365cc86fc1SJed Brown + -mat_type elemental - sets the matrix type to "elemental" during a call to MatSetFromOptions()
13375cc86fc1SJed Brown - -mat_elemental_grid_height - sets Grid Height for 2D cyclic ordering of internal matrix
1338ed36708cSHong Zhang 
1339ed36708cSHong Zhang   Level: beginner
1340ed36708cSHong Zhang 
13415cb544a0SHong Zhang .seealso: MATDENSE
1342ed36708cSHong Zhang M*/
13434a29722dSXuan Zhou 
13448cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_Elemental(Mat A)
1345db31f6deSJed Brown {
1346db31f6deSJed Brown   Mat_Elemental      *a;
1347db31f6deSJed Brown   PetscErrorCode     ierr;
13485682a260SJack Poulson   PetscBool          flg,flg1;
13495e9f5b67SHong Zhang   Mat_Elemental_Grid *commgrid;
13505e9f5b67SHong Zhang   MPI_Comm           icomm;
13515682a260SJack Poulson   PetscInt           optv1;
1352db31f6deSJed Brown 
1353db31f6deSJed Brown   PetscFunctionBegin;
1354607a6623SBarry Smith   ierr = PetscElementalInitializePackage();CHKERRQ(ierr);
135540d92e34SHong Zhang   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
135640d92e34SHong Zhang   A->insertmode = NOT_SET_VALUES;
1357db31f6deSJed Brown 
1358b00a9115SJed Brown   ierr = PetscNewLog(A,&a);CHKERRQ(ierr);
1359db31f6deSJed Brown   A->data = (void*)a;
1360db31f6deSJed Brown 
1361db31f6deSJed Brown   /* Set up the elemental matrix */
1362e8146892SSatish Balay   El::mpi::Comm cxxcomm(PetscObjectComm((PetscObject)A));
13635e9f5b67SHong Zhang 
13645e9f5b67SHong Zhang   /* Grid needs to be shared between multiple Mats on the same communicator, implement by attribute caching on the MPI_Comm */
13655e9f5b67SHong Zhang   if (Petsc_Elemental_keyval == MPI_KEYVAL_INVALID) {
136612801b39SBarry Smith     ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Elemental_keyval,(void*)0);CHKERRQ(ierr);
13675e9f5b67SHong Zhang   }
13680c18141cSBarry Smith   ierr = PetscCommDuplicate(cxxcomm.comm,&icomm,NULL);CHKERRQ(ierr);
136947435625SJed Brown   ierr = MPI_Comm_get_attr(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr);
13705e9f5b67SHong Zhang   if (!flg) {
1371b00a9115SJed Brown     ierr = PetscNewLog(A,&commgrid);CHKERRQ(ierr);
13725cb544a0SHong Zhang 
1373ce94432eSBarry Smith     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"Elemental Options","Mat");CHKERRQ(ierr);
1374e8146892SSatish Balay     /* displayed default grid sizes (CommSize,1) are set by us arbitrarily until El::Grid() is called */
1375e8146892SSatish Balay     ierr = PetscOptionsInt("-mat_elemental_grid_height","Grid Height","None",El::mpi::Size(cxxcomm),&optv1,&flg1);CHKERRQ(ierr);
13765682a260SJack Poulson     if (flg1) {
1377e8146892SSatish Balay       if (El::mpi::Size(cxxcomm) % optv1 != 0) {
1378e8146892SSatish Balay         SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"Grid Height %D must evenly divide CommSize %D",optv1,(PetscInt)El::mpi::Size(cxxcomm));
1379ed667823SXuan Zhou       }
1380e8146892SSatish Balay       commgrid->grid = new El::Grid(cxxcomm,optv1); /* use user-provided grid height */
13812ef0cf24SXuan Zhou     } else {
1382e8146892SSatish Balay       commgrid->grid = new El::Grid(cxxcomm); /* use Elemental default grid sizes */
1383da0640a4SHong Zhang       /* printf("new commgrid->grid = %p\n",commgrid->grid);  -- memory leak revealed by valgrind? */
1384ed667823SXuan Zhou     }
13855e9f5b67SHong Zhang     commgrid->grid_refct = 1;
138647435625SJed Brown     ierr = MPI_Comm_set_attr(icomm,Petsc_Elemental_keyval,(void*)commgrid);CHKERRQ(ierr);
1387ea394475SSatish Balay 
1388ea394475SSatish Balay     a->pivoting    = 1;
1389ea394475SSatish Balay     ierr = PetscOptionsInt("-mat_elemental_pivoting","Pivoting","None",a->pivoting,&a->pivoting,NULL);CHKERRQ(ierr);
1390ea394475SSatish Balay 
13912a808120SBarry Smith     ierr = PetscOptionsEnd();CHKERRQ(ierr);
13925e9f5b67SHong Zhang   } else {
13935e9f5b67SHong Zhang     commgrid->grid_refct++;
13945e9f5b67SHong Zhang   }
13955e9f5b67SHong Zhang   ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr);
13965e9f5b67SHong Zhang   a->grid        = commgrid->grid;
1397e8146892SSatish Balay   a->emat        = new El::DistMatrix<PetscElemScalar>(*a->grid);
139832d7a744SHong Zhang   a->roworiented = PETSC_TRUE;
1399db31f6deSJed Brown 
1400bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatGetOwnershipIS_C",MatGetOwnershipIS_Elemental);CHKERRQ(ierr);
1401db31f6deSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject)A,MATELEMENTAL);CHKERRQ(ierr);
1402db31f6deSJed Brown   PetscFunctionReturn(0);
1403db31f6deSJed Brown }
1404