xref: /petsc/src/mat/impls/elemental/matelem.cxx (revision 724f0ad3fb121a344907d4dc797b1b7dd482d072)
1 #include <../src/mat/impls/elemental/matelemimpl.h> /*I "petscmat.h" I*/
2 
3 /*
4     The variable Petsc_Elemental_keyval is used to indicate an MPI attribute that
5   is attached to a communicator, in this case the attribute is a Mat_Elemental_Grid
6 */
7 static PetscMPIInt Petsc_Elemental_keyval = MPI_KEYVAL_INVALID;
8 
9 #undef __FUNCT__
10 #define __FUNCT__ "PetscElementalInitializePackage"
11 /*@C
12    PetscElementalInitializePackage - Initialize Elemental package
13 
14    Logically Collective
15 
16    Input Arguments:
17 .  path - the dynamic library path or PETSC_NULL
18 
19    Level: developer
20 
21 .seealso: MATELEMENTAL, PetscElementalFinalizePackage()
22 @*/
23 PetscErrorCode PetscElementalInitializePackage(const char *path)
24 {
25   PetscErrorCode ierr;
26 
27   PetscFunctionBegin;
28   if (elem::Initialized()) PetscFunctionReturn(0);
29   { /* We have already initialized MPI, so this song and dance is just to pass these variables (which won't be used by Elemental) through the interface that needs references */
30     int zero = 0;
31     char **nothing = 0;
32     elem::Initialize(zero,nothing);
33   }
34   ierr = PetscRegisterFinalize(PetscElementalFinalizePackage);CHKERRQ(ierr);
35   PetscFunctionReturn(0);
36 }
37 
38 #undef __FUNCT__
39 #define __FUNCT__ "PetscElementalFinalizePackage"
40 /*@C
41    PetscElementalFinalizePackage - Finalize Elemental package
42 
43    Logically Collective
44 
45    Level: developer
46 
47 .seealso: MATELEMENTAL, PetscElementalInitializePackage()
48 @*/
49 PetscErrorCode PetscElementalFinalizePackage(void)
50 {
51 
52   PetscFunctionBegin;
53   elem::Finalize();
54   PetscFunctionReturn(0);
55 }
56 
57 /* Sets Elemental options from the options database */
58 #undef __FUNCT__
59 #define __FUNCT__ "PetscSetElementalFromOptions"
60 PetscErrorCode PetscSetElementalFromOptions(Mat A)
61 {
62   //Mat_Elemental  *a = (Mat_Elemental*)A->data;
63   PetscErrorCode ierr;
64   //PetscInt       optv1,optv2;
65   //PetscBool      flg;
66 
67   PetscFunctionBegin;
68   ierr = PetscOptionsBegin(((PetscObject)A)->comm,((PetscObject)A)->prefix,"Elemental Options","Mat");CHKERRQ(ierr);
69   //ierr = PetscOptionsInt("-mat_elemental_grid_height","Gird Height","None",(*a->emat).Grid().Height(),&optv1,&flg);CHKERRQ(ierr);
70   //ierr = PetscOptionsInt("-mat_elemental_grid_width","Gird Width","None",(*a->emat).Grid().Width(),&optv2,&flg);CHKERRQ(ierr);
71   //if (flg) (*a->emat).Grid().ResizeTo(optv1,optv2);
72   // ierr = PetscOptionsInt("-mat_mumps_icntl_2","ICNTL(2): output stream for diagnostic printing, statistics, and warning","None",mumps->id.ICNTL(2),&icntl,&flg);CHKERRQ(ierr);
73   // if (flg) mumps->id.ICNTL(2) = icntl;
74   // ierr = PetscOptionsInt("-mat_mumps_icntl_3","ICNTL(3): output stream for global information, collected on the host","None",mumps->id.ICNTL(3),&icntl,&flg);CHKERRQ(ierr);
75   // if (flg) mumps->id.ICNTL(3) = icntl;
76 
77 
78   PetscOptionsEnd();
79   PetscFunctionReturn(0);
80 }
81 
82 #undef __FUNCT__
83 #define __FUNCT__ "MatView_Elemental"
84 static PetscErrorCode MatView_Elemental(Mat A,PetscViewer viewer)
85 {
86   PetscErrorCode ierr;
87   Mat_Elemental  *a = (Mat_Elemental*)A->data;
88   PetscBool      iascii;
89 
90   PetscFunctionBegin;
91   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
92   if (iascii) {
93     PetscViewerFormat format;
94     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
95     if (format == PETSC_VIEWER_ASCII_INFO) {
96       /* call elemental viewing function */
97       ierr = PetscViewerASCIIPrintf(viewer,"Elemental run parameters:\n");CHKERRQ(ierr);
98       ierr = PetscViewerASCIIPrintf(viewer,"  allocated entries=%d\n",(*a->emat).AllocatedMemory());CHKERRQ(ierr);
99       ierr = PetscViewerASCIIPrintf(viewer,"  grid height=%d, grid width=%d\n",(*a->emat).Grid().Height(),(*a->emat).Grid().Width());CHKERRQ(ierr);
100       if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) {
101         /* call elemental viewing function */
102         ierr = PetscPrintf(((PetscObject)viewer)->comm,"test matview_elemental 2\n");CHKERRQ(ierr);
103       }
104 
105     } else if (format == PETSC_VIEWER_DEFAULT) {
106       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
107       ierr = PetscObjectPrintClassNamePrefixType((PetscObject)A,viewer,"Matrix Object");CHKERRQ(ierr);
108       a->emat->Print("Elemental matrix (cyclic ordering)");
109       ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
110       if (A->factortype == MAT_FACTOR_NONE){
111         Mat Aaij;
112         ierr = PetscPrintf(((PetscObject)viewer)->comm,"Elemental matrix (explicit ordering)\n");CHKERRQ(ierr);
113         ierr = MatComputeExplicitOperator(A,&Aaij);CHKERRQ(ierr);
114         ierr = MatView(Aaij,viewer);CHKERRQ(ierr);
115         ierr = MatDestroy(&Aaij);CHKERRQ(ierr);
116       }
117     } else SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Format");
118   } else {
119     /* convert to aij/mpidense format and call MatView() */
120     Mat Aaij;
121     ierr = PetscPrintf(((PetscObject)viewer)->comm,"Elemental matrix (explicit ordering)\n");CHKERRQ(ierr);
122     ierr = MatComputeExplicitOperator(A,&Aaij);CHKERRQ(ierr);
123     ierr = MatView(Aaij,viewer);CHKERRQ(ierr);
124     ierr = MatDestroy(&Aaij);CHKERRQ(ierr);
125   }
126   PetscFunctionReturn(0);
127 }
128 
129 #undef __FUNCT__
130 #define __FUNCT__ "MatGetInfo_Elemental"
131 static PetscErrorCode MatGetInfo_Elemental(Mat F,MatInfoType flag,MatInfo *info)
132 {
133   PetscFunctionBegin;
134   /* this routine is called by PCSetUp_LU(). It does nothing yet. */
135   PetscFunctionReturn(0);
136 }
137 
138 #undef __FUNCT__
139 #define __FUNCT__ "MatSetValues_Elemental"
140 static PetscErrorCode MatSetValues_Elemental(Mat A,PetscInt nr,const PetscInt *rows,PetscInt nc,const PetscInt *cols,const PetscScalar *vals,InsertMode imode)
141 {
142   PetscErrorCode ierr;
143   Mat_Elemental  *a = (Mat_Elemental*)A->data;
144   PetscMPIInt    rank;
145   PetscInt       i,j,rrank,ridx,crank,cidx;
146 
147   PetscFunctionBegin;
148   ierr = MPI_Comm_rank(((PetscObject)A)->comm,&rank);CHKERRQ(ierr);
149 
150   const elem::Grid &grid = a->emat->Grid();
151   for (i=0; i<nr; i++) {
152     PetscInt erow,ecol,elrow,elcol;
153     if (rows[i] < 0) continue;
154     P2RO(A,0,rows[i],&rrank,&ridx);
155     RO2E(A,0,rrank,ridx,&erow);
156     if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_PLIB,"Incorrect row translation");
157     for (j=0; j<nc; j++) {
158       if (cols[j] < 0) continue;
159       P2RO(A,1,cols[j],&crank,&cidx);
160       RO2E(A,1,crank,cidx,&ecol);
161       if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_PLIB,"Incorrect col translation");
162       if (erow % grid.MCSize() != grid.MCRank() || ecol % grid.MRSize() != grid.MRRank()){ /* off-proc entry */
163         if (imode != ADD_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only ADD_VALUES to off-processor entry is supported");
164         /* PetscPrintf(PETSC_COMM_SELF,"[%D] add off-proc entry (%D,%D, %g) (%D %D)\n",rank,rows[i],cols[j],*(vals+i*nc),erow,ecol); */
165         a->esubmat->Set(0,0, vals[i*nc+j]);
166         a->interface->Axpy(1.0,*(a->esubmat),erow,ecol);
167         continue;
168       }
169       elrow = erow / grid.MCSize();
170       elcol = ecol / grid.MRSize();
171       switch (imode) {
172       case INSERT_VALUES: a->emat->SetLocal(elrow,elcol,vals[i*nc+j]); break;
173       case ADD_VALUES: a->emat->UpdateLocal(elrow,elcol,vals[i*nc+j]); break;
174       default: SETERRQ1(((PetscObject)A)->comm,PETSC_ERR_SUP,"No support for InsertMode %d",(int)imode);
175       }
176     }
177   }
178   PetscFunctionReturn(0);
179 }
180 
181 #undef __FUNCT__
182 #define __FUNCT__ "MatMult_Elemental"
183 static PetscErrorCode MatMult_Elemental(Mat A,Vec X,Vec Y)
184 {
185   Mat_Elemental     *a = (Mat_Elemental*)A->data;
186   PetscErrorCode    ierr;
187   const PetscScalar *x;
188   PetscScalar       *y;
189   PetscScalar       one = 1,zero = 0;
190 
191   PetscFunctionBegin;
192   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
193   ierr = VecGetArray(Y,&y);CHKERRQ(ierr);
194   { /* Scoping so that constructor is called before pointer is returned */
195     elem::DistMatrix<PetscScalar,elem::VC,elem::STAR> xe(A->cmap->N,1,0,x,A->cmap->n,*a->grid);
196     elem::DistMatrix<PetscScalar,elem::VC,elem::STAR> ye(A->rmap->N,1,0,y,A->rmap->n,*a->grid);
197     elem::Gemv(elem::NORMAL,one,*a->emat,xe,zero,ye);
198   }
199   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
200   ierr = VecRestoreArray(Y,&y);CHKERRQ(ierr);
201   PetscFunctionReturn(0);
202 }
203 
204 #undef __FUNCT__
205 #define __FUNCT__ "MatMultTranspose_Elemental"
206 static PetscErrorCode MatMultTranspose_Elemental(Mat A,Vec X,Vec Y)
207 {
208   Mat_Elemental     *a = (Mat_Elemental*)A->data;
209   PetscErrorCode    ierr;
210   const PetscScalar *x;
211   PetscScalar       *y;
212   PetscScalar       one = 1,zero = 0;
213 
214   PetscFunctionBegin;
215   printf("elemental test is called...\n");
216   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
217   ierr = VecGetArray(Y,&y);CHKERRQ(ierr);
218   { /* Scoping so that constructor is called before pointer is returned */
219     elem::DistMatrix<PetscScalar,elem::VC,elem::STAR> xe(A->rmap->N,1,0,x,A->rmap->n,*a->grid);
220     elem::DistMatrix<PetscScalar,elem::VC,elem::STAR> ye(A->cmap->N,1,0,y,A->cmap->n,*a->grid);
221     elem::Gemv(elem::TRANSPOSE,one,*a->emat,xe,zero,ye);
222   }
223   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
224   ierr = VecRestoreArray(Y,&y);CHKERRQ(ierr);
225   PetscFunctionReturn(0);
226 }
227 
228 #undef __FUNCT__
229 #define __FUNCT__ "MatMultAdd_Elemental"
230 static PetscErrorCode MatMultAdd_Elemental(Mat A,Vec X,Vec Y,Vec Z)
231 {
232   Mat_Elemental     *a = (Mat_Elemental*)A->data;
233   PetscErrorCode    ierr;
234   const PetscScalar *x;
235   PetscScalar       *z;
236   PetscScalar       one = 1.0;
237 
238   PetscFunctionBegin;
239   if (Y != Z) {ierr = VecCopy(Y,Z);CHKERRQ(ierr);}
240   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
241   ierr = VecGetArray(Z,&z);CHKERRQ(ierr);
242   { /* Scoping so that constructor is called before pointer is returned */
243     elem::DistMatrix<PetscScalar,elem::VC,elem::STAR> xe(A->cmap->N,1,0,x,A->cmap->n,*a->grid);
244     elem::DistMatrix<PetscScalar,elem::VC,elem::STAR> ze(A->rmap->N,1,0,z,A->rmap->n,*a->grid);
245     elem::Gemv(elem::NORMAL,one,*a->emat,xe,one,ze);
246   }
247   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
248   ierr = VecRestoreArray(Z,&z);CHKERRQ(ierr);
249   PetscFunctionReturn(0);
250 }
251 
252 #undef __FUNCT__
253 #define __FUNCT__ "MatMatMultNumeric_Elemental"
254 static PetscErrorCode MatMatMultNumeric_Elemental(Mat A,Mat B,Mat C)
255 {
256   Mat_Elemental  *a = (Mat_Elemental*)A->data;
257   Mat_Elemental  *b = (Mat_Elemental*)B->data;
258   Mat_Elemental  *c = (Mat_Elemental*)C->data;
259   PetscScalar    one = 1.0,zero = 0.0;
260 
261   PetscFunctionBegin;
262   { /* Scoping so that constructor is called before pointer is returned */
263     elem::Gemm(elem::NORMAL,elem::NORMAL,one,*a->emat,*b->emat,zero,*c->emat);
264   }
265   C->assembled = PETSC_TRUE;
266   PetscFunctionReturn(0);
267 }
268 
269 #undef __FUNCT__
270 #define __FUNCT__ "MatMatMultSymbolic_Elemental"
271 static PetscErrorCode MatMatMultSymbolic_Elemental(Mat A,Mat B,PetscReal fill,Mat *C)
272 {
273   PetscErrorCode ierr;
274   Mat            Ce;
275   MPI_Comm       comm=((PetscObject)A)->comm;
276 
277   PetscFunctionBegin;
278   ierr = MatCreate(comm,&Ce);CHKERRQ(ierr);
279   ierr = MatSetSizes(Ce,A->rmap->n,B->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
280   ierr = MatSetType(Ce,MATELEMENTAL);CHKERRQ(ierr);
281   ierr = MatSetUp(Ce);CHKERRQ(ierr);
282   *C = Ce;
283   PetscFunctionReturn(0);
284 }
285 
286 #undef __FUNCT__
287 #define __FUNCT__ "MatMatMult_Elemental"
288 static PetscErrorCode MatMatMult_Elemental(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
289 {
290   PetscErrorCode ierr;
291 
292   PetscFunctionBegin;
293   if (scall == MAT_INITIAL_MATRIX){
294     ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
295     ierr = MatMatMultSymbolic_Elemental(A,B,1.0,C);CHKERRQ(ierr);
296     ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
297   }
298   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
299   ierr = MatMatMultNumeric_Elemental(A,B,*C);CHKERRQ(ierr);
300   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
301   PetscFunctionReturn(0);
302 }
303 
304 #undef __FUNCT__
305 #define __FUNCT__ "MatScale_Elemental"
306 static PetscErrorCode MatScale_Elemental(Mat X,PetscScalar a)
307 {
308   Mat_Elemental  *x = (Mat_Elemental*)X->data;
309 
310   PetscFunctionBegin;
311   elem::Scal(a,*x->emat);
312   PetscFunctionReturn(0);
313 }
314 
315 #undef __FUNCT__
316 #define __FUNCT__ "MatAXPY_Elemental"
317 static PetscErrorCode MatAXPY_Elemental(Mat Y,PetscScalar a,Mat X,MatStructure str)
318 {
319   Mat_Elemental  *x = (Mat_Elemental*)X->data;
320   Mat_Elemental  *y = (Mat_Elemental*)Y->data;
321 
322   PetscFunctionBegin;
323   elem::Axpy(a,*x->emat,*y->emat);
324   PetscFunctionReturn(0);
325 }
326 
327 #undef __FUNCT__
328 #define __FUNCT__ "MatCopy_Elemental"
329 static PetscErrorCode MatCopy_Elemental(Mat A,Mat B,MatStructure str)
330 {
331   Mat_Elemental *a=(Mat_Elemental*)A->data;
332   Mat_Elemental *b=(Mat_Elemental*)B->data;
333 
334   PetscFunctionBegin;
335   elem::Copy(*a->emat,*b->emat);
336   PetscFunctionReturn(0);
337 }
338 
339 #undef __FUNCT__
340 #define __FUNCT__ "MatTranspose_Elemental"
341 static PetscErrorCode MatTranspose_Elemental(Mat A,MatReuse reuse,Mat *B)
342 {
343   /* Only out-of-place supported */
344   Mat            Be;
345   PetscErrorCode ierr;
346   MPI_Comm       comm=((PetscObject)A)->comm;
347   Mat_Elemental  *a = (Mat_Elemental*)A->data, *b;
348 
349   PetscFunctionBegin;
350   if (reuse == MAT_INITIAL_MATRIX){
351     ierr = MatCreate(comm,&Be);CHKERRQ(ierr);
352     ierr = MatSetSizes(Be,A->cmap->n,A->rmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
353     ierr = MatSetType(Be,MATELEMENTAL);CHKERRQ(ierr);
354     ierr = MatSetUp(Be);CHKERRQ(ierr);
355     *B = Be;
356   }
357   b = (Mat_Elemental*)Be->data;
358   elem::Transpose(*a->emat,*b->emat);
359   Be->assembled = PETSC_TRUE;
360   PetscFunctionReturn(0);
361 }
362 
363 #undef __FUNCT__
364 #define __FUNCT__ "MatSolve_Elemental"
365 static PetscErrorCode MatSolve_Elemental(Mat A,Vec B,Vec X)
366 {
367   Mat_Elemental     *a = (Mat_Elemental*)A->data;
368   PetscErrorCode    ierr;
369   PetscScalar       *x;
370 
371   PetscFunctionBegin;
372   ierr = VecCopy(B,X);CHKERRQ(ierr);
373   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
374   elem::DistMatrix<PetscScalar,elem::VC,elem::STAR> xe(A->rmap->N,1,0,x,A->rmap->n,*a->grid);
375   elem::DistMatrix<PetscScalar,elem::MC,elem::MR> xer = xe;
376   switch (A->factortype) {
377   case MAT_FACTOR_LU:
378     if ((*a->pivot).AllocatedMemory()) {
379       elem::SolveAfterLU(elem::NORMAL,*a->emat,*a->pivot,xer);
380       elem::Copy(xer,xe);
381     } else {
382       elem::SolveAfterLU(elem::NORMAL,*a->emat,xer);
383       elem::Copy(xer,xe);
384     }
385     break;
386   case MAT_FACTOR_CHOLESKY:
387     elem::SolveAfterCholesky(elem::UPPER,elem::NORMAL,*a->emat,xer);
388     elem::Copy(xer,xe);
389     break;
390   default:
391     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType");
392     break;
393   }
394   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
395   PetscFunctionReturn(0);
396 }
397 
398 #undef __FUNCT__
399 #define __FUNCT__ "MatMatSolve_Elemental"
400 static PetscErrorCode MatMatSolve_Elemental(Mat A,Mat B,Mat X)
401 {
402   Mat_Elemental *a=(Mat_Elemental*)A->data;
403   Mat_Elemental *b=(Mat_Elemental*)B->data;
404   Mat_Elemental *x=(Mat_Elemental*)X->data;
405 
406   PetscFunctionBegin;
407   elem::Copy(*b->emat,*x->emat);
408   switch (A->factortype) {
409   case MAT_FACTOR_LU:
410     if ((*a->pivot).AllocatedMemory()) {
411       elem::SolveAfterLU(elem::NORMAL,*a->emat,*a->pivot,*x->emat);
412     } else {
413       elem::SolveAfterLU(elem::NORMAL,*a->emat,*x->emat);
414     }
415     break;
416   case MAT_FACTOR_CHOLESKY:
417     elem::SolveAfterCholesky(elem::UPPER,elem::NORMAL,*a->emat,*x->emat);
418     break;
419   default:
420     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unfactored Matrix or Unsupported MatFactorType");
421     break;
422   }
423   PetscFunctionReturn(0);
424 }
425 
426 #undef __FUNCT__
427 #define __FUNCT__ "MatLUFactor_Elemental"
428 static PetscErrorCode MatLUFactor_Elemental(Mat A,IS row,IS col,const MatFactorInfo *info)
429 {
430   Mat_Elemental  *a = (Mat_Elemental*)A->data;
431 
432   PetscFunctionBegin;
433   if (info->dtcol){
434     elem::LU(*a->emat,*a->pivot);
435   } else {
436     elem::LU(*a->emat);
437   }
438   A->factortype = MAT_FACTOR_LU;
439   A->assembled  = PETSC_TRUE;
440   PetscFunctionReturn(0);
441 }
442 
443 #undef __FUNCT__
444 #define __FUNCT__ "MatLUFactorNumeric_Elemental"
445 static PetscErrorCode  MatLUFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info)
446 {
447   PetscErrorCode ierr;
448 
449   PetscFunctionBegin;
450   ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
451   ierr = MatLUFactor_Elemental(F,0,0,info);CHKERRQ(ierr);
452   PetscFunctionReturn(0);
453 }
454 
455 #undef __FUNCT__
456 #define __FUNCT__ "MatLUFactorSymbolic_Elemental"
457 static PetscErrorCode  MatLUFactorSymbolic_Elemental(Mat F,Mat A,IS r,IS c,const MatFactorInfo *info)
458 {
459   PetscFunctionBegin;
460   /* F is create and allocated by MatGetFactor_elemental_petsc(), skip this routine. */
461   PetscFunctionReturn(0);
462 }
463 
464 #undef __FUNCT__
465 #define __FUNCT__ "MatCholeskyFactor_Elemental"
466 static PetscErrorCode MatCholeskyFactor_Elemental(Mat A,IS perm,const MatFactorInfo *info)
467 {
468   Mat_Elemental  *a = (Mat_Elemental*)A->data;
469   elem::DistMatrix<PetscScalar,elem::MC,elem::STAR> d;
470 
471   PetscFunctionBegin;
472   elem::Cholesky(elem::UPPER,*a->emat);
473   // if (info->dtcol){
474   //   /* A = U^T * U for SPD Matrix A */
475   //   printf("Cholesky Factorization for SPD Matrices...\n");
476   //   elem::Cholesky(elem::UPPER,*a->emat);
477   // } else {
478   //   /* A = U^T * D * U * for Symmetric Matrix A */
479   //   printf("LDL^T Factorization for Symmetric Matrices.\n");
480   //   printf("This routine does not pivot. Use with caution.\n");
481   //   elem::LDLT(*a->emat,d);
482   // }
483   A->factortype = MAT_FACTOR_CHOLESKY;
484   A->assembled  = PETSC_TRUE;
485   PetscFunctionReturn(0);
486 }
487 
488 #undef __FUNCT__
489 #define __FUNCT__ "MatCholeskyFactorNumeric_Elemental"
490 static PetscErrorCode MatCholeskyFactorNumeric_Elemental(Mat F,Mat A,const MatFactorInfo *info)
491 {
492   PetscErrorCode ierr;
493 
494   PetscFunctionBegin;
495   ierr = MatCopy(A,F,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
496   ierr = MatCholeskyFactor_Elemental(F,0,info);CHKERRQ(ierr);
497   PetscFunctionReturn(0);
498 }
499 
500 #undef __FUNCT__
501 #define __FUNCT__ "MatCholeskyFactorSymbolic_Elemental"
502 static PetscErrorCode MatCholeskyFactorSymbolic_Elemental(Mat F,Mat A,IS perm,const MatFactorInfo *info)
503 {
504   PetscFunctionBegin;
505   /* F is create and allocated by MatGetFactor_elemental_petsc(), skip this routine. */
506   PetscFunctionReturn(0);
507 }
508 
509 EXTERN_C_BEGIN
510 #undef __FUNCT__
511 #define __FUNCT__ "MatGetFactor_elemental_petsc"
512 static PetscErrorCode MatGetFactor_elemental_petsc(Mat A,MatFactorType ftype,Mat *F)
513 {
514   Mat            B;
515   PetscErrorCode ierr;
516 
517   PetscFunctionBegin;
518   /* Create the factorization matrix */
519   ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr);
520   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
521   ierr = MatSetType(B,MATELEMENTAL);CHKERRQ(ierr);
522   ierr = MatSetUp(B);CHKERRQ(ierr);
523   B->factortype = ftype;
524   *F            = B;
525   PetscFunctionReturn(0);
526 }
527 EXTERN_C_END
528 
529 #undef __FUNCT__
530 #define __FUNCT__ "MatNorm_Elemental"
531 static PetscErrorCode MatNorm_Elemental(Mat A,NormType type,PetscReal *nrm)
532 {
533   Mat_Elemental *a=(Mat_Elemental*)A->data;
534 
535   PetscFunctionBegin;
536   switch (type){
537   case NORM_1:
538     *nrm = elem::Norm(*a->emat,elem::ONE_NORM);
539     break;
540   case NORM_FROBENIUS:
541     *nrm = elem::Norm(*a->emat,elem::FROBENIUS_NORM);
542     break;
543   case NORM_INFINITY:
544     *nrm = elem::Norm(*a->emat,elem::INFINITY_NORM);
545     break;
546   default:
547     printf("Error: unsupported norm type!\n");
548   }
549   PetscFunctionReturn(0);
550 }
551 
552 #undef __FUNCT__
553 #define __FUNCT__ "MatZeroEntries_Elemental"
554 static PetscErrorCode MatZeroEntries_Elemental(Mat A)
555 {
556   Mat_Elemental *a=(Mat_Elemental*)A->data;
557 
558   PetscFunctionBegin;
559   elem::Zero(*a->emat);
560   PetscFunctionReturn(0);
561 }
562 
563 EXTERN_C_BEGIN
564 #undef __FUNCT__
565 #define __FUNCT__ "MatGetOwnershipIS_Elemental"
566 static PetscErrorCode MatGetOwnershipIS_Elemental(Mat A,IS *rows,IS *cols)
567 {
568   Mat_Elemental  *a = (Mat_Elemental*)A->data;
569   PetscErrorCode ierr;
570   PetscInt       i,m,shift,stride,*idx;
571 
572   PetscFunctionBegin;
573   if (rows) {
574     m = a->emat->LocalHeight();
575     shift = a->emat->ColShift();
576     stride = a->emat->ColStride();
577     ierr = PetscMalloc(m*sizeof(PetscInt),&idx);CHKERRQ(ierr);
578     for (i=0; i<m; i++) {
579       PetscInt rank,offset;
580       E2RO(A,0,shift+i*stride,&rank,&offset);
581       RO2P(A,0,rank,offset,&idx[i]);
582     }
583     ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,rows);CHKERRQ(ierr);
584   }
585   if (cols) {
586     m = a->emat->LocalWidth();
587     shift = a->emat->RowShift();
588     stride = a->emat->RowStride();
589     ierr = PetscMalloc(m*sizeof(PetscInt),&idx);CHKERRQ(ierr);
590     for (i=0; i<m; i++) {
591       PetscInt rank,offset;
592       E2RO(A,1,shift+i*stride,&rank,&offset);
593       RO2P(A,1,rank,offset,&idx[i]);
594     }
595     ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,cols);CHKERRQ(ierr);
596   }
597   PetscFunctionReturn(0);
598 }
599 EXTERN_C_END
600 
601 #undef __FUNCT__
602 #define __FUNCT__ "MatConvert_Elemental_Dense"
603 static PetscErrorCode MatConvert_Elemental_Dense(Mat A,const MatType newtype,MatReuse reuse,Mat *B)
604 {
605   Mat                Bmpi;
606   Mat_Elemental      *a = (Mat_Elemental*)A->data;
607   MPI_Comm           comm=((PetscObject)A)->comm;
608   PetscErrorCode     ierr;
609   PetscInt           rrank,ridx,crank,cidx,nrows,ncols,i,j;
610   PetscScalar        v;
611 
612   PetscFunctionBegin;
613   if (strcmp(newtype,MATDENSE) && strcmp(newtype,MATSEQDENSE) && strcmp(newtype,MATMPIDENSE)) {
614     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported New MatType: must be MATDENSE, MATSEQDENSE or MATMPIDENSE");
615   }
616   if (1){
617     ierr = MatCreate(comm,&Bmpi);CHKERRQ(ierr);
618     ierr = MatSetSizes(Bmpi,A->rmap->n,A->cmap->n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
619     ierr = MatSetType(Bmpi,MATDENSE);CHKERRQ(ierr);
620     ierr = MatSetUp(Bmpi);CHKERRQ(ierr);
621   }
622   ierr = MatGetSize(A,&nrows,&ncols);CHKERRQ(ierr);
623   for (i=0; i<nrows; i++) {
624     PetscInt erow,ecol;
625     P2RO(A,0,i,&rrank,&ridx);
626     RO2E(A,0,rrank,ridx,&erow);
627     if (rrank < 0 || ridx < 0 || erow < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect row translation");
628     for (j=0; j<ncols; j++) {
629       P2RO(A,1,j,&crank,&cidx);
630       RO2E(A,1,crank,cidx,&ecol);
631       if (crank < 0 || cidx < 0 || ecol < 0) SETERRQ(comm,PETSC_ERR_PLIB,"Incorrect col translation");
632       v = a->emat->Get(erow,ecol);
633       ierr = MatSetValues(Bmpi,1,&i,1,&j,&v,INSERT_VALUES);CHKERRQ(ierr);
634     }
635   }
636   ierr = MatAssemblyBegin(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
637   ierr = MatAssemblyEnd(Bmpi,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
638   if (reuse == MAT_REUSE_MATRIX) {
639     //*B = Bmpi;
640     //MatDestroy(&A);
641     ierr = MatHeaderReplace(A,Bmpi);CHKERRQ(ierr);
642   } else {
643     *B = Bmpi;
644   }
645   PetscFunctionReturn(0);
646 }
647 
648 #undef __FUNCT__
649 #define __FUNCT__ "MatDestroy_Elemental"
650 static PetscErrorCode MatDestroy_Elemental(Mat A)
651 {
652   Mat_Elemental      *a = (Mat_Elemental*)A->data;
653   PetscErrorCode     ierr;
654   Mat_Elemental_Grid *commgrid;
655   PetscBool          flg;
656   MPI_Comm           icomm;
657 
658   PetscFunctionBegin;
659   a->interface->Detach();
660   delete a->interface;
661   delete a->esubmat;
662   delete a->emat;
663 
664   elem::mpi::Comm cxxcomm(((PetscObject)A)->comm);
665   ierr = PetscCommDuplicate(cxxcomm,&icomm,PETSC_NULL);CHKERRQ(ierr);
666   ierr = MPI_Attr_get(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr);
667   if (--commgrid->grid_refct == 0) {
668     delete commgrid->grid;
669     ierr = PetscFree(commgrid);CHKERRQ(ierr);
670   }
671   ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr);
672   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatGetOwnershipIS_C","",PETSC_NULL);CHKERRQ(ierr);
673   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatGetFactor_petsc_C","",PETSC_NULL);CHKERRQ(ierr);
674   ierr = PetscFree(A->data);CHKERRQ(ierr);
675   PetscFunctionReturn(0);
676 }
677 
678 #undef __FUNCT__
679 #define __FUNCT__ "MatSetUp_Elemental"
680 PetscErrorCode MatSetUp_Elemental(Mat A)
681 {
682   Mat_Elemental  *a = (Mat_Elemental*)A->data;
683   PetscErrorCode ierr;
684   PetscMPIInt    rsize,csize;
685 
686   PetscFunctionBegin;
687   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
688   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
689 
690   a->emat->ResizeTo(A->rmap->N,A->cmap->N);CHKERRQ(ierr);
691   elem::Zero(*a->emat);
692 
693   ierr = MPI_Comm_size(A->rmap->comm,&rsize);CHKERRQ(ierr);
694   ierr = MPI_Comm_size(A->cmap->comm,&csize);CHKERRQ(ierr);
695   if (csize != rsize) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_INCOMP,"Cannot use row and column communicators of different sizes");
696   a->commsize = rsize;
697   a->mr[0] = A->rmap->N % rsize; if (!a->mr[0]) a->mr[0] = rsize;
698   a->mr[1] = A->cmap->N % csize; if (!a->mr[1]) a->mr[1] = csize;
699   a->m[0] = A->rmap->N / rsize + (a->mr[0] != rsize);
700   a->m[1] = A->cmap->N / csize + (a->mr[1] != csize);
701   PetscFunctionReturn(0);
702 }
703 
704 #undef __FUNCT__
705 #define __FUNCT__ "MatAssemblyBegin_Elemental"
706 PetscErrorCode MatAssemblyBegin_Elemental(Mat A, MatAssemblyType type)
707 {
708   Mat_Elemental  *a = (Mat_Elemental*)A->data;
709 
710   PetscFunctionBegin;
711   a->interface->Detach();
712   a->interface->Attach(elem::LOCAL_TO_GLOBAL,*(a->emat));
713   PetscFunctionReturn(0);
714 }
715 
716 #undef __FUNCT__
717 #define __FUNCT__ "MatAssemblyEnd_Elemental"
718 PetscErrorCode MatAssemblyEnd_Elemental(Mat A, MatAssemblyType type)
719 {
720   PetscFunctionBegin;
721   /* Currently does nothing */
722   PetscFunctionReturn(0);
723 }
724 
725 /* -------------------------------------------------------------------*/
726 static struct _MatOps MatOps_Values = {
727        MatSetValues_Elemental,
728        0,
729        0,
730        MatMult_Elemental,
731 /* 4*/ MatMultAdd_Elemental,
732        MatMultTranspose_Elemental,
733        0, //MatMultTransposeAdd_Elemental,
734        MatSolve_Elemental,
735        0, //MatSolveAdd_Elemental,
736        0, //MatSolveTranspose_Elemental,
737 /*10*/ 0, //MatSolveTransposeAdd_Elemental,
738        MatLUFactor_Elemental,
739        MatCholeskyFactor_Elemental,
740        0,
741        MatTranspose_Elemental,
742 /*15*/ MatGetInfo_Elemental,
743        0,
744        0,
745        0,
746        MatNorm_Elemental,
747 /*20*/ MatAssemblyBegin_Elemental,
748        MatAssemblyEnd_Elemental,
749        0, //MatSetOption_Elemental,
750        MatZeroEntries_Elemental,
751 /*24*/ 0,
752        MatLUFactorSymbolic_Elemental,
753        MatLUFactorNumeric_Elemental,
754        MatCholeskyFactorSymbolic_Elemental,
755        MatCholeskyFactorNumeric_Elemental,
756 /*29*/ MatSetUp_Elemental,
757        0,
758        0,
759        0,
760        0,
761 /*34*/ 0, //MatDuplicate_Elemental,
762        0,
763        0,
764        0,
765        0,
766 /*39*/ MatAXPY_Elemental,
767        0,
768        0,
769        0,
770        MatCopy_Elemental,
771 /*44*/ 0,
772        MatScale_Elemental,
773        0,
774        0,
775        0,
776 /*49*/ 0,
777        0,
778        0,
779        0,
780        0,
781 /*54*/ 0,
782        0,
783        0,
784        0,
785        0,
786 /*59*/ 0,
787        MatDestroy_Elemental,
788        MatView_Elemental,
789        0,
790        0,
791 /*64*/ 0,
792        0,
793        0,
794        0,
795        0,
796 /*69*/ 0,
797        0,
798        MatConvert_Elemental_Dense,
799        0,
800        0,
801 /*74*/ 0,
802        0,
803        0,
804        0,
805        0,
806 /*79*/ 0,
807        0,
808        0,
809        0,
810        0,
811 /*84*/ 0,
812        0,
813        0,
814        0,
815        0,
816 /*89*/ MatMatMult_Elemental,
817        MatMatMultSymbolic_Elemental,
818        MatMatMultNumeric_Elemental,
819        0,
820        0,
821 /*94*/ 0,
822        0, //MatMatTransposeMult_Elemental,
823        0, //MatMatTransposeMultSymbolic_Elemental,
824        0, //MatMatTransposeMultNumeric_Elemental_Elemental,
825        0,
826 /*99*/ 0,
827        0,
828        0,
829        0,
830        0,
831 /*104*/0,
832        0,
833        0,
834        0,
835        0,
836 /*109*/MatMatSolve_Elemental,
837        0,
838        0,
839        0,
840        0,
841 /*114*/0,
842        0,
843        0,
844        0,
845        0,
846 /*119*/0,
847        0,
848        0,
849        0,
850        0,
851 /*124*/0,
852        0,
853        0,
854        0,
855        0,
856 /*129*/0,
857        0,
858        0,
859        0,
860        0,
861 /*134*/0,
862        0,
863        0,
864        0,
865        0
866 };
867 
868 /*MC
869    MATELEMENTAL = "elemental" - A matrix type for dense matrices using the Elemental package
870 
871    Options Database Keys:
872 . -mat_type elemental - sets the matrix type to "elemental" during a call to MatSetFromOptions()
873 
874   Level: beginner
875 
876 .seealso: MATDENSE,MatCreateElemental()
877 M*/
878 EXTERN_C_BEGIN
879 #undef __FUNCT__
880 #define __FUNCT__ "MatCreate_Elemental"
881 PETSC_EXTERN_C PetscErrorCode MatCreate_Elemental(Mat A)
882 {
883   Mat_Elemental      *a;
884   PetscErrorCode     ierr;
885   PetscBool          flg,flg1,flg2;
886   Mat_Elemental_Grid *commgrid;
887   MPI_Comm           icomm;
888   PetscInt           optv1,optv2;
889 
890   PetscFunctionBegin;
891   ierr = PetscElementalInitializePackage(PETSC_NULL);CHKERRQ(ierr);
892   ierr = PetscMemcpy(A->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
893   A->insertmode = NOT_SET_VALUES;
894 
895   ierr = PetscNewLog(A,Mat_Elemental,&a);CHKERRQ(ierr);
896   A->data = (void*)a;
897 
898   /* Set up the elemental matrix */
899   elem::mpi::Comm cxxcomm(((PetscObject)A)->comm);
900   ierr = PetscOptionsBegin(((PetscObject)A)->comm,((PetscObject)A)->prefix,"Elemental Options","Mat");CHKERRQ(ierr);
901 
902   /* Grid needs to be shared between multiple Mats on the same communicator, implement by attribute caching on the MPI_Comm */
903   if (Petsc_Elemental_keyval == MPI_KEYVAL_INVALID) {
904     ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Elemental_keyval,(void*)0);
905   }
906   ierr = PetscCommDuplicate(cxxcomm,&icomm,PETSC_NULL);CHKERRQ(ierr);
907   ierr = MPI_Attr_get(icomm,Petsc_Elemental_keyval,(void**)&commgrid,(int*)&flg);CHKERRQ(ierr);
908   if (!flg) {
909     ierr = PetscNewLog(A,Mat_Elemental_Grid,&commgrid);CHKERRQ(ierr);
910     ierr = PetscOptionsInt("-mat_elemental_grid_height","Grid Height","None",elem::mpi::CommSize(cxxcomm),&optv1,&flg1);CHKERRQ(ierr);
911     ierr = PetscOptionsInt("-mat_elemental_grid_width","Grid Width","None",1,&optv2,&flg2);CHKERRQ(ierr);
912     if (flg1 || flg2) {
913       if (optv1*optv2 != elem::mpi::CommSize(cxxcomm)) {
914         SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_INCOMP,"Grid Height times Grid Width must equal CommSize");
915       }
916       commgrid->grid = new elem::Grid(cxxcomm,optv1,optv2);
917     } else {
918       commgrid->grid = new elem::Grid(cxxcomm);
919     }
920     commgrid->grid_refct = 1;
921     ierr = MPI_Attr_put(icomm,Petsc_Elemental_keyval,(void*)commgrid);CHKERRQ(ierr);
922   } else {
923     commgrid->grid_refct++;
924   }
925   ierr = PetscCommDestroy(&icomm);CHKERRQ(ierr);
926   a->grid      = commgrid->grid;
927   a->emat      = new elem::DistMatrix<PetscScalar>(*a->grid);
928   a->esubmat   = new elem::Matrix<PetscScalar>(1,1);
929   a->interface = new elem::AxpyInterface<PetscScalar>;
930   a->pivot     = new elem::DistMatrix<PetscInt,elem::VC,elem::STAR>;
931 
932   /* build cache for off array entries formed */
933   a->interface->Attach(elem::LOCAL_TO_GLOBAL,*(a->emat));
934 
935   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatGetOwnershipIS_C","MatGetOwnershipIS_Elemental",MatGetOwnershipIS_Elemental);CHKERRQ(ierr);
936   ierr = PetscObjectComposeFunctionDynamic((PetscObject)A,"MatGetFactor_petsc_C","MatGetFactor_elemental_petsc",MatGetFactor_elemental_petsc);CHKERRQ(ierr);
937 
938   ierr = PetscObjectChangeTypeName((PetscObject)A,MATELEMENTAL);CHKERRQ(ierr);
939   PetscOptionsEnd();
940   PetscFunctionReturn(0);
941 }
942 EXTERN_C_END
943