xref: /petsc/src/dm/impls/moab/dmmoab.cxx (revision 304006b37668cad3f6c43c04b9f2c4dc2eda5f97)
1 #include <petsc/private/dmmbimpl.h> /*I  "petscdmmoab.h"   I*/
2 
3 #include <petscdmmoab.h>
4 #include <MBTagConventions.hpp>
5 #include <moab/Skinner.hpp>
6 
7 /*MC
8   DMMOAB = "moab" - A DM object that encapsulates an unstructured mesh described by the MOAB mesh database.
9                     Direct access to the MOAB Interface and other mesh manipulation related objects are available
10                     through public API. Ability to create global and local representation of Vecs containing all
11                     unknowns in the interior and shared boundary via a transparent tag-data wrapper is provided
12                     along with utility functions to traverse the mesh and assemble a discrete system via
13                     field-based/blocked Vec(Get/Set) methods. Input from and output to different formats are
14                     available.
15 
16   Reference: http://www.mcs.anl.gov/~fathom/moab-docs/html/contents.html
17 
18   Level: intermediate
19 
20 .seealso: DMType, DMMoabCreate(), DMCreate(), DMSetType(), DMMoabCreateMoab()
21 M*/
22 
23 /* External function declarations here */
24 PETSC_EXTERN PetscErrorCode DMCreateInterpolation_Moab(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling);
25 PETSC_EXTERN PetscErrorCode DMCreateDefaultConstraints_Moab(DM dm);
26 PETSC_EXTERN PetscErrorCode DMCreateMatrix_Moab(DM dm,  Mat *J);
27 PETSC_EXTERN PetscErrorCode DMCreateCoordinateDM_Moab(DM dm, DM *cdm);
28 PETSC_EXTERN PetscErrorCode DMRefine_Moab(DM dm, MPI_Comm comm, DM *dmRefined);
29 PETSC_EXTERN PetscErrorCode DMCoarsen_Moab(DM dm, MPI_Comm comm, DM *dmCoarsened);
30 PETSC_EXTERN PetscErrorCode DMRefineHierarchy_Moab(DM dm, PetscInt nlevels, DM dmRefined[]);
31 PETSC_EXTERN PetscErrorCode DMCoarsenHierarchy_Moab(DM dm,PetscInt nlevels,DM dmCoarsened[]);
32 PETSC_EXTERN PetscErrorCode DMClone_Moab(DM dm, DM *newdm);
33 PETSC_EXTERN PetscErrorCode DMCreateGlobalVector_Moab(DM,Vec *);
34 PETSC_EXTERN PetscErrorCode DMCreateLocalVector_Moab(DM,Vec *);
35 PETSC_EXTERN PetscErrorCode DMCreateMatrix_Moab(DM dm,Mat *J);
36 PETSC_EXTERN PetscErrorCode DMGlobalToLocalBegin_Moab(DM,Vec,InsertMode,Vec);
37 PETSC_EXTERN PetscErrorCode DMGlobalToLocalEnd_Moab(DM,Vec,InsertMode,Vec);
38 PETSC_EXTERN PetscErrorCode DMLocalToGlobalBegin_Moab(DM,Vec,InsertMode,Vec);
39 PETSC_EXTERN PetscErrorCode DMLocalToGlobalEnd_Moab(DM,Vec,InsertMode,Vec);
40 
41 
42 /* Un-implemented routines */
43 /*
44 PETSC_EXTERN PetscErrorCode DMCreateDefaultSection_Moab(DM dm);
45 PETSC_EXTERN PetscErrorCode DMCreateInjection_Moab(DM dmCoarse, DM dmFine, Mat *mat);
46 PETSC_EXTERN PetscErrorCode DMLoad_Moab(DM dm, PetscViewer viewer);
47 PETSC_EXTERN PetscErrorCode DMGetDimPoints_Moab(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd);
48 PETSC_EXTERN PetscErrorCode DMCreateSubDM_Moab(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm);
49 PETSC_EXTERN PetscErrorCode DMLocatePoints_Moab(DM dm, Vec v, IS *cellIS);
50 */
51 
52 /*@
53   DMMoabCreate - Creates a DMMoab object, which encapsulates a moab instance
54 
55   Collective on MPI_Comm
56 
57   Input Parameter:
58 . comm - The communicator for the DMMoab object
59 
60   Output Parameter:
61 . dmb  - The DMMoab object
62 
63   Level: beginner
64 
65 .keywords: DMMoab, create
66 @*/
67 PetscErrorCode DMMoabCreate(MPI_Comm comm, DM *dmb)
68 {
69   PetscErrorCode ierr;
70 
71   PetscFunctionBegin;
72   PetscValidPointer(dmb,2);
73   ierr = DMCreate(comm, dmb);CHKERRQ(ierr);
74   ierr = DMSetType(*dmb, DMMOAB);CHKERRQ(ierr);
75   PetscFunctionReturn(0);
76 }
77 
78 /*@
79   DMMoabCreateMoab - Creates a DMMoab object, optionally from an instance and other data
80 
81   Collective on MPI_Comm
82 
83   Input Parameter:
84 . comm - The communicator for the DMMoab object
85 . mbiface - (ptr to) the MOAB Instance; if passed in NULL, MOAB instance is created inside PETSc, and destroyed
86          along with the DMMoab
87 . pcomm - (ptr to) a ParallelComm; if NULL, creates one internally for the whole communicator
88 . ltog_tag - A tag to use to retrieve global id for an entity; if 0, will use GLOBAL_ID_TAG_NAME/tag
89 . range - If non-NULL, contains range of entities to which DOFs will be assigned
90 
91   Output Parameter:
92 . dmb  - The DMMoab object
93 
94   Level: intermediate
95 
96 .keywords: DMMoab, create
97 @*/
98 PetscErrorCode DMMoabCreateMoab(MPI_Comm comm, moab::Interface *mbiface, moab::ParallelComm *pcomm, moab::Tag *ltog_tag, moab::Range *range, DM *dmb)
99 {
100   PetscErrorCode ierr;
101   moab::ErrorCode merr;
102   moab::EntityHandle partnset;
103   PetscInt rank, nprocs;
104   DM             dmmb;
105   DM_Moab        *dmmoab;
106 
107   PetscFunctionBegin;
108   PetscValidPointer(dmb,6);
109 
110   ierr = DMMoabCreate(comm, &dmmb);CHKERRQ(ierr);
111   dmmoab = (DM_Moab*)(dmmb)->data;
112 
113   if (!mbiface) {
114     dmmoab->mbiface = new moab::Core();
115     dmmoab->icreatedinstance = PETSC_TRUE;
116   }
117   else {
118     dmmoab->mbiface = mbiface;
119     dmmoab->icreatedinstance = PETSC_FALSE;
120   }
121 
122   /* by default the fileset = root set. This set stores the hierarchy of entities belonging to current DM */
123   dmmoab->fileset=0;
124   dmmoab->hlevel=0;
125   dmmoab->nghostrings=0;
126 
127   if (!pcomm) {
128     ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
129     ierr = MPI_Comm_size(comm, &nprocs);CHKERRQ(ierr);
130 
131     /* Create root sets for each mesh.  Then pass these
132        to the load_file functions to be populated. */
133     merr = dmmoab->mbiface->create_meshset(moab::MESHSET_SET, partnset);MBERR("Creating partition set failed", merr);
134 
135     /* Create the parallel communicator object with the partition handle associated with MOAB */
136     dmmoab->pcomm = moab::ParallelComm::get_pcomm(dmmoab->mbiface, partnset, &comm);
137   }
138   else {
139     ierr = DMMoabSetParallelComm(dmmb, pcomm);CHKERRQ(ierr);
140   }
141 
142   /* do the remaining initializations for DMMoab */
143   dmmoab->bs = 1;
144   dmmoab->numFields = 1;
145   ierr = PetscMalloc(dmmoab->numFields*sizeof(char*),&dmmoab->fieldNames);CHKERRQ(ierr);
146   ierr = PetscStrallocpy("DEFAULT", (char**) &dmmoab->fieldNames[0]);CHKERRQ(ierr);
147   dmmoab->rw_dbglevel = 0;
148   dmmoab->partition_by_rank = PETSC_FALSE;
149   dmmoab->extra_read_options[0] = '\0';
150   dmmoab->extra_write_options[0] = '\0';
151   dmmoab->read_mode = READ_PART;
152   dmmoab->write_mode = WRITE_PART;
153 
154   /* set global ID tag handle */
155   if (ltog_tag && *ltog_tag) {
156     ierr = DMMoabSetLocalToGlobalTag(dmmb, *ltog_tag);CHKERRQ(ierr);
157   }
158   else {
159     merr = dmmoab->mbiface->tag_get_handle(GLOBAL_ID_TAG_NAME, dmmoab->ltog_tag);MBERRNM(merr);
160     if (ltog_tag) *ltog_tag = dmmoab->ltog_tag;
161   }
162 
163   merr = dmmoab->mbiface->tag_get_handle(MATERIAL_SET_TAG_NAME, dmmoab->material_tag);MBERRNM(merr);
164 
165   /* set the local range of entities (vertices) of interest */
166   if (range) {
167     ierr = DMMoabSetLocalVertices(dmmb, range);CHKERRQ(ierr);
168   }
169   *dmb=dmmb;
170   PetscFunctionReturn(0);
171 }
172 
173 
174 #undef __FUNCT__
175 #define __FUNCT__ "DMMoabSetParallelComm"
176 /*@
177   DMMoabSetParallelComm - Set the ParallelComm used with this DMMoab
178 
179   Collective on MPI_Comm
180 
181   Input Parameter:
182 . dm    - The DMMoab object being set
183 . pcomm - The ParallelComm being set on the DMMoab
184 
185   Level: beginner
186 
187 .keywords: DMMoab, create
188 @*/
189 PetscErrorCode DMMoabSetParallelComm(DM dm,moab::ParallelComm *pcomm)
190 {
191   DM_Moab        *dmmoab = (DM_Moab*)(dm)->data;
192 
193   PetscFunctionBegin;
194   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
195   PetscValidPointer(pcomm,2);
196   dmmoab->pcomm = pcomm;
197   dmmoab->mbiface = pcomm->get_moab();
198   dmmoab->icreatedinstance = PETSC_FALSE;
199   PetscFunctionReturn(0);
200 }
201 
202 
203 /*@
204   DMMoabGetParallelComm - Get the ParallelComm used with this DMMoab
205 
206   Collective on MPI_Comm
207 
208   Input Parameter:
209 . dm    - The DMMoab object being set
210 
211   Output Parameter:
212 . pcomm - The ParallelComm for the DMMoab
213 
214   Level: beginner
215 
216 .keywords: DMMoab, create
217 @*/
218 PetscErrorCode DMMoabGetParallelComm(DM dm,moab::ParallelComm **pcomm)
219 {
220   PetscFunctionBegin;
221   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
222   *pcomm = ((DM_Moab*)(dm)->data)->pcomm;
223   PetscFunctionReturn(0);
224 }
225 
226 
227 /*@
228   DMMoabSetInterface - Set the MOAB instance used with this DMMoab
229 
230   Collective on MPI_Comm
231 
232   Input Parameter:
233 . dm      - The DMMoab object being set
234 . mbiface - The MOAB instance being set on this DMMoab
235 
236   Level: beginner
237 
238 .keywords: DMMoab, create
239 @*/
240 PetscErrorCode DMMoabSetInterface(DM dm,moab::Interface *mbiface)
241 {
242   DM_Moab        *dmmoab = (DM_Moab*)(dm)->data;
243 
244   PetscFunctionBegin;
245   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
246   PetscValidPointer(mbiface,2);
247   dmmoab->pcomm = NULL;
248   dmmoab->mbiface = mbiface;
249   dmmoab->icreatedinstance = PETSC_FALSE;
250   PetscFunctionReturn(0);
251 }
252 
253 
254 /*@
255   DMMoabGetInterface - Get the MOAB instance used with this DMMoab
256 
257   Collective on MPI_Comm
258 
259   Input Parameter:
260 . dm      - The DMMoab object being set
261 
262   Output Parameter:
263 . mbiface - The MOAB instance set on this DMMoab
264 
265   Level: beginner
266 
267 .keywords: DMMoab, create
268 @*/
269 PetscErrorCode DMMoabGetInterface(DM dm,moab::Interface **mbiface)
270 {
271   PetscErrorCode   ierr;
272   static PetscBool cite = PETSC_FALSE;
273 
274   PetscFunctionBegin;
275   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
276   ierr = PetscCitationsRegister("@techreport{tautges_moab:_2004,\n  type = {{SAND2004-1592}},\n  title = {{MOAB:} A Mesh-Oriented Database},  institution = {Sandia National Laboratories},\n  author = {Tautges, T. J. and Meyers, R. and Merkley, K. and Stimpson, C. and Ernst, C.},\n  year = {2004},  note = {Report}\n}\n",&cite);CHKERRQ(ierr);
277   *mbiface = ((DM_Moab*)dm->data)->mbiface;
278   PetscFunctionReturn(0);
279 }
280 
281 
282 /*@
283   DMMoabSetLocalVertices - Set the entities having DOFs on this DMMoab
284 
285   Collective on MPI_Comm
286 
287   Input Parameter:
288 . dm    - The DMMoab object being set
289 . range - The entities treated by this DMMoab
290 
291   Level: beginner
292 
293 .keywords: DMMoab, create
294 @*/
295 PetscErrorCode DMMoabSetLocalVertices(DM dm,moab::Range *range)
296 {
297   moab::ErrorCode merr;
298   PetscErrorCode  ierr;
299   moab::Range     tmpvtxs;
300   DM_Moab        *dmmoab = (DM_Moab*)(dm)->data;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
304   dmmoab->vlocal->clear();
305   dmmoab->vowned->clear();
306 
307   dmmoab->vlocal->insert(range->begin(), range->end());
308 
309   /* filter based on parallel status */
310   merr = dmmoab->pcomm->filter_pstatus(*dmmoab->vlocal,PSTATUS_NOT_OWNED,PSTATUS_NOT,-1,dmmoab->vowned);MBERRNM(merr);
311 
312   /* filter all the non-owned and shared entities out of the list */
313   tmpvtxs = moab::subtract(*dmmoab->vlocal, *dmmoab->vowned);
314   merr = dmmoab->pcomm->filter_pstatus(tmpvtxs,PSTATUS_INTERFACE,PSTATUS_OR,-1,dmmoab->vghost);MBERRNM(merr);
315   tmpvtxs = moab::subtract(tmpvtxs, *dmmoab->vghost);
316   *dmmoab->vlocal = moab::subtract(*dmmoab->vlocal, tmpvtxs);
317 
318   /* compute and cache the sizes of local and ghosted entities */
319   dmmoab->nloc = dmmoab->vowned->size();
320   dmmoab->nghost = dmmoab->vghost->size();
321   ierr = MPIU_Allreduce(&dmmoab->nloc, &dmmoab->n, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr);
322   PetscFunctionReturn(0);
323 }
324 
325 
326 /*@
327   DMMoabGetAllVertices - Get the entities having DOFs on this DMMoab
328 
329   Collective on MPI_Comm
330 
331   Input Parameter:
332 . dm    - The DMMoab object being set
333 
334   Output Parameter:
335 . owned - The local vertex entities in this DMMoab = (owned+ghosted)
336 
337   Level: beginner
338 
339 .keywords: DMMoab, create
340 @*/
341 PetscErrorCode DMMoabGetAllVertices(DM dm,moab::Range *local)
342 {
343   PetscFunctionBegin;
344   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
345   if (local) *local = *((DM_Moab*)dm->data)->vlocal;
346   PetscFunctionReturn(0);
347 }
348 
349 
350 
351 /*@
352   DMMoabGetLocalVertices - Get the entities having DOFs on this DMMoab
353 
354   Collective on MPI_Comm
355 
356   Input Parameter:
357 . dm    - The DMMoab object being set
358 
359   Output Parameter:
360 . owned - The owned vertex entities in this DMMoab
361 . ghost - The ghosted entities (non-owned) stored locally in this partition
362 
363   Level: beginner
364 
365 .keywords: DMMoab, create
366 @*/
367 PetscErrorCode DMMoabGetLocalVertices(DM dm,const moab::Range **owned,const moab::Range **ghost)
368 {
369   PetscFunctionBegin;
370   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
371   if (owned) *owned = ((DM_Moab*)dm->data)->vowned;
372   if (ghost) *ghost = ((DM_Moab*)dm->data)->vghost;
373   PetscFunctionReturn(0);
374 }
375 
376 /*@
377   DMMoabGetLocalElements - Get the higher-dimensional entities that are locally owned
378 
379   Collective on MPI_Comm
380 
381   Input Parameter:
382 . dm    - The DMMoab object being set
383 
384   Output Parameter:
385 . range - The entities owned locally
386 
387   Level: beginner
388 
389 .keywords: DMMoab, create
390 @*/
391 PetscErrorCode DMMoabGetLocalElements(DM dm,const moab::Range **range)
392 {
393   PetscFunctionBegin;
394   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
395   if (range) *range = ((DM_Moab*)dm->data)->elocal;
396   PetscFunctionReturn(0);
397 }
398 
399 
400 /*@
401   DMMoabSetLocalElements - Set the entities having DOFs on this DMMoab
402 
403   Collective on MPI_Comm
404 
405   Input Parameter:
406 . dm    - The DMMoab object being set
407 . range - The entities treated by this DMMoab
408 
409   Level: beginner
410 
411 .keywords: DMMoab, create
412 @*/
413 PetscErrorCode DMMoabSetLocalElements(DM dm,moab::Range *range)
414 {
415   moab::ErrorCode merr;
416   PetscErrorCode  ierr;
417   DM_Moab        *dmmoab = (DM_Moab*)(dm)->data;
418 
419   PetscFunctionBegin;
420   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
421   dmmoab->elocal->clear();
422   dmmoab->eghost->clear();
423   dmmoab->elocal->insert(range->begin(), range->end());
424   merr = dmmoab->pcomm->filter_pstatus(*dmmoab->elocal,PSTATUS_NOT_OWNED,PSTATUS_NOT);MBERRNM(merr);
425   *dmmoab->eghost = moab::subtract(*range, *dmmoab->elocal);
426   dmmoab->neleloc=dmmoab->elocal->size();
427   dmmoab->neleghost=dmmoab->eghost->size();
428   ierr = MPIU_Allreduce(&dmmoab->nele, &dmmoab->neleloc, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr);
429   PetscInfo2(dm, "Created %D local and %D global elements.\n", dmmoab->neleloc, dmmoab->nele);
430   PetscFunctionReturn(0);
431 }
432 
433 
434 /*@
435   DMMoabSetLocalToGlobalTag - Set the tag used for local to global numbering
436 
437   Collective on MPI_Comm
438 
439   Input Parameter:
440 . dm      - The DMMoab object being set
441 . ltogtag - The MOAB tag used for local to global ids
442 
443   Level: beginner
444 
445 .keywords: DMMoab, create
446 @*/
447 PetscErrorCode DMMoabSetLocalToGlobalTag(DM dm,moab::Tag ltogtag)
448 {
449   PetscFunctionBegin;
450   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
451   ((DM_Moab*)dm->data)->ltog_tag = ltogtag;
452   PetscFunctionReturn(0);
453 }
454 
455 
456 /*@
457   DMMoabGetLocalToGlobalTag - Get the tag used for local to global numbering
458 
459   Collective on MPI_Comm
460 
461   Input Parameter:
462 . dm      - The DMMoab object being set
463 
464   Output Parameter:
465 . ltogtag - The MOAB tag used for local to global ids
466 
467   Level: beginner
468 
469 .keywords: DMMoab, create
470 @*/
471 PetscErrorCode DMMoabGetLocalToGlobalTag(DM dm,moab::Tag *ltog_tag)
472 {
473   PetscFunctionBegin;
474   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
475   *ltog_tag = ((DM_Moab*)dm->data)->ltog_tag;
476   PetscFunctionReturn(0);
477 }
478 
479 
480 /*@
481   DMMoabSetBlockSize - Set the block size used with this DMMoab
482 
483   Collective on MPI_Comm
484 
485   Input Parameter:
486 . dm - The DMMoab object being set
487 . bs - The block size used with this DMMoab
488 
489   Level: beginner
490 
491 .keywords: DMMoab, create
492 @*/
493 PetscErrorCode DMMoabSetBlockSize(DM dm,PetscInt bs)
494 {
495   PetscFunctionBegin;
496   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
497   ((DM_Moab*)dm->data)->bs = bs;
498   PetscFunctionReturn(0);
499 }
500 
501 
502 /*@
503   DMMoabGetBlockSize - Get the block size used with this DMMoab
504 
505   Collective on MPI_Comm
506 
507   Input Parameter:
508 . dm - The DMMoab object being set
509 
510   Output Parameter:
511 . bs - The block size used with this DMMoab
512 
513   Level: beginner
514 
515 .keywords: DMMoab, create
516 @*/
517 PetscErrorCode DMMoabGetBlockSize(DM dm,PetscInt *bs)
518 {
519   PetscFunctionBegin;
520   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
521   *bs = ((DM_Moab*)dm->data)->bs;
522   PetscFunctionReturn(0);
523 }
524 
525 
526 /*@
527   DMMoabGetSize - Get the global vertex size used with this DMMoab
528 
529   Collective on DM
530 
531   Input Parameter:
532 . dm - The DMMoab object being set
533 
534   Output Parameter:
535 . neg - The number of global elements in the DMMoab instance
536 . nvg - The number of global vertices in the DMMoab instance
537 
538   Level: beginner
539 
540 .keywords: DMMoab, create
541 @*/
542 PetscErrorCode DMMoabGetSize(DM dm,PetscInt *neg,PetscInt *nvg)
543 {
544   PetscFunctionBegin;
545   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
546   if(neg) *neg = ((DM_Moab*)dm->data)->nele;
547   if(nvg) *nvg = ((DM_Moab*)dm->data)->n;
548   PetscFunctionReturn(0);
549 }
550 
551 
552 /*@
553   DMMoabGetLocalSize - Get the local and ghosted vertex size used with this DMMoab
554 
555   Collective on DM
556 
557   Input Parameter:
558 . dm - The DMMoab object being set
559 
560   Output Parameter:
561 + nel - The number of owned elements in this processor
562 . neg - The number of ghosted elements in this processor
563 . nvl - The number of owned vertices in this processor
564 . nvg - The number of ghosted vertices in this processor
565 
566   Level: beginner
567 
568 .keywords: DMMoab, create
569 @*/
570 PetscErrorCode DMMoabGetLocalSize(DM dm,PetscInt *nel,PetscInt *neg,PetscInt *nvl,PetscInt *nvg)
571 {
572   PetscFunctionBegin;
573   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
574   if(nel) *nel = ((DM_Moab*)dm->data)->neleloc;
575   if(neg) *neg = ((DM_Moab*)dm->data)->neleghost;
576   if(nvl) *nvl = ((DM_Moab*)dm->data)->nloc;
577   if(nvg) *nvg = ((DM_Moab*)dm->data)->nghost;
578   PetscFunctionReturn(0);
579 }
580 
581 
582 /*@
583   DMMoabGetOffset - Get the local offset for the global vector
584 
585   Collective on MPI_Comm
586 
587   Input Parameter:
588 . dm - The DMMoab object being set
589 
590   Output Parameter:
591 . offset - The local offset for the global vector
592 
593   Level: beginner
594 
595 .keywords: DMMoab, create
596 @*/
597 PetscErrorCode DMMoabGetOffset(DM dm,PetscInt *offset)
598 {
599   PetscFunctionBegin;
600   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
601   *offset = ((DM_Moab*)dm->data)->vstart;
602   PetscFunctionReturn(0);
603 }
604 
605 
606 /*@
607   DMMoabGetDimension - Get the dimension of the DM Mesh
608 
609   Collective on MPI_Comm
610 
611   Input Parameter:
612 . dm - The DMMoab object
613 
614   Output Parameter:
615 . dim - The dimension of DM
616 
617   Level: beginner
618 
619 .keywords: DMMoab, create
620 @*/
621 PetscErrorCode DMMoabGetDimension(DM dm,PetscInt *dim)
622 {
623   PetscFunctionBegin;
624   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
625   *dim = ((DM_Moab*)dm->data)->dim;
626   PetscFunctionReturn(0);
627 }
628 
629 
630 #undef __FUNCT__
631 #define __FUNCT__ "DMMoabGetHierarchyLevel"
632 /*@
633   DMMoabGetHierarchyLevel - Get the current level of the mesh hierarchy
634   generated through uniform refinement.
635 
636   Collective on DM
637 
638   Input Parameter:
639 . dm - The DMMoab object being set
640 
641   Output Parameter:
642 . nvg - The current mesh hierarchy level
643 
644   Level: beginner
645 
646 .keywords: DMMoab, multigrid
647 @*/
648 PetscErrorCode DMMoabGetHierarchyLevel(DM dm,PetscInt *nlevel)
649 {
650   PetscFunctionBegin;
651   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
652   if(nlevel) *nlevel = ((DM_Moab*)dm->data)->hlevel;
653   PetscFunctionReturn(0);
654 }
655 
656 
657 #undef __FUNCT__
658 #define __FUNCT__ "DMMoabGetMaterialBlock"
659 /*@
660   DMMoabGetMaterialBlock - Get the material ID corresponding to the current entity of the DM Mesh
661 
662   Collective on MPI_Comm
663 
664   Input Parameter:
665 . dm - The DMMoab object
666 . ehandle - The element entity handle
667 
668   Output Parameter:
669 . mat - The material ID for the current entity
670 
671   Level: beginner
672 
673 .keywords: DMMoab, create
674 @*/
675 PetscErrorCode DMMoabGetMaterialBlock(DM dm,const moab::EntityHandle ehandle, PetscInt *mat)
676 {
677   DM_Moab         *dmmoab;
678   moab::ErrorCode merr;
679 
680   PetscFunctionBegin;
681   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
682   if (*mat) {
683     dmmoab = (DM_Moab*)(dm)->data;
684     merr=dmmoab->mbiface->tag_get_data(dmmoab->material_tag, &ehandle, 1, mat);MBERRNM(merr);
685   }
686   PetscFunctionReturn(0);
687 }
688 
689 
690 /*@
691   DMMoabGetVertexCoordinates - Get the coordinates corresponding to the requested vertex entities
692 
693   Collective on MPI_Comm
694 
695   Input Parameter:
696 . dm - The DMMoab object
697 . nconn - Number of entities whose coordinates are needed
698 . conn - The vertex entity handles
699 
700   Output Parameter:
701 . vpos - The coordinates of the requested vertex entities
702 
703   Level: beginner
704 
705 .seealso: DMMoabGetVertexConnectivity()
706 @*/
707 PetscErrorCode DMMoabGetVertexCoordinates(DM dm,PetscInt nconn,const moab::EntityHandle *conn,PetscReal *vpos)
708 {
709   DM_Moab         *dmmoab;
710   PetscErrorCode  ierr;
711   moab::ErrorCode merr;
712 
713   PetscFunctionBegin;
714   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
715   PetscValidPointer(conn,3);
716   dmmoab = (DM_Moab*)(dm)->data;
717 
718   if (!vpos) {
719     ierr = PetscMalloc1(nconn*3, &vpos);CHKERRQ(ierr);
720   }
721 
722   /* Get connectivity information in MOAB canonical ordering */
723   merr = dmmoab->mbiface->get_coords(conn, nconn, vpos);MBERRNM(merr);
724   PetscFunctionReturn(0);
725 }
726 
727 
728 /*@
729   DMMoabGetVertexConnectivity - Get the vertex adjacency for the given entity
730 
731   Collective on MPI_Comm
732 
733   Input Parameter:
734 . dm - The DMMoab object
735 . vhandle - Vertex entity handle
736 
737   Output Parameter:
738 . nconn - Number of entities whose coordinates are needed
739 . conn - The vertex entity handles
740 
741   Level: beginner
742 
743 .seealso: DMMoabGetVertexCoordinates(), DMMoabRestoreVertexConnectivity()
744 @*/
745 PetscErrorCode DMMoabGetVertexConnectivity(DM dm,moab::EntityHandle vhandle,PetscInt* nconn, moab::EntityHandle **conn)
746 {
747   DM_Moab        *dmmoab;
748   std::vector<moab::EntityHandle> adj_entities,connect;
749   PetscErrorCode  ierr;
750   moab::ErrorCode merr;
751 
752   PetscFunctionBegin;
753   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
754   PetscValidPointer(conn,4);
755   dmmoab = (DM_Moab*)(dm)->data;
756 
757   /* Get connectivity information in MOAB canonical ordering */
758   merr = dmmoab->mbiface->get_adjacencies(&vhandle, 1, 1, true, adj_entities, moab::Interface::UNION);MBERRNM(merr);
759   merr = dmmoab->mbiface->get_connectivity(&adj_entities[0],adj_entities.size(),connect);MBERRNM(merr);
760 
761   if (conn) {
762     ierr = PetscMalloc(sizeof(moab::EntityHandle)*connect.size(), conn);CHKERRQ(ierr);
763     ierr = PetscMemcpy(*conn, &connect[0], sizeof(moab::EntityHandle)*connect.size());CHKERRQ(ierr);
764   }
765   if (nconn) *nconn=connect.size();
766   PetscFunctionReturn(0);
767 }
768 
769 
770 /*@
771   DMMoabRestoreVertexConnectivity - Restore the vertex connectivity for the given entity
772 
773   Collective on MPI_Comm
774 
775   Input Parameter:
776 . dm - The DMMoab object
777 . vhandle - Vertex entity handle
778 . nconn - Number of entities whose coordinates are needed
779 . conn - The vertex entity handles
780 
781   Level: beginner
782 
783 .seealso: DMMoabGetVertexCoordinates(), DMMoabGetVertexConnectivity()
784 @*/
785 PetscErrorCode DMMoabRestoreVertexConnectivity(DM dm,moab::EntityHandle ehandle,PetscInt* nconn, moab::EntityHandle **conn)
786 {
787   PetscErrorCode  ierr;
788 
789   PetscFunctionBegin;
790   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
791   PetscValidPointer(conn,4);
792 
793   if (conn) {
794     ierr = PetscFree(*conn);CHKERRQ(ierr);
795   }
796   if (nconn) *nconn=0;
797   PetscFunctionReturn(0);
798 }
799 
800 
801 /*@
802   DMMoabGetElementConnectivity - Get the vertex adjacency for the given entity
803 
804   Collective on MPI_Comm
805 
806   Input Parameter:
807 . dm - The DMMoab object
808 . ehandle - Vertex entity handle
809 
810   Output Parameter:
811 . nconn - Number of entities whose coordinates are needed
812 . conn - The vertex entity handles
813 
814   Level: beginner
815 
816 .seealso: DMMoabGetVertexCoordinates(), DMMoabGetVertexConnectivity(), DMMoabRestoreVertexConnectivity()
817 @*/
818 PetscErrorCode DMMoabGetElementConnectivity(DM dm,moab::EntityHandle ehandle,PetscInt* nconn,const moab::EntityHandle **conn)
819 {
820   DM_Moab        *dmmoab;
821   const moab::EntityHandle *connect;
822   moab::ErrorCode merr;
823   PetscInt nnodes;
824 
825   PetscFunctionBegin;
826   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
827   PetscValidPointer(conn,4);
828   dmmoab = (DM_Moab*)(dm)->data;
829 
830   /* Get connectivity information in MOAB canonical ordering */
831   merr = dmmoab->mbiface->get_connectivity(ehandle, connect, nnodes);MBERRNM(merr);
832   if (conn) *conn=connect;
833   if (nconn) *nconn=nnodes;
834   PetscFunctionReturn(0);
835 }
836 
837 
838 /*@
839   DMMoabIsEntityOnBoundary - Check whether a given entity is on the boundary (vertex, edge, face, element)
840 
841   Collective on MPI_Comm
842 
843   Input Parameter:
844 . dm - The DMMoab object
845 . ent - Entity handle
846 
847   Output Parameter:
848 . ent_on_boundary - PETSC_TRUE if entity on boundary; PETSC_FALSE otherwise
849 
850   Level: beginner
851 
852 .seealso: DMMoabCheckBoundaryVertices()
853 @*/
854 PetscErrorCode DMMoabIsEntityOnBoundary(DM dm,const moab::EntityHandle ent,PetscBool* ent_on_boundary)
855 {
856   moab::EntityType etype;
857   DM_Moab         *dmmoab;
858   PetscInt         edim;
859 
860   PetscFunctionBegin;
861   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
862   PetscValidPointer(ent_on_boundary,3);
863   dmmoab = (DM_Moab*)(dm)->data;
864 
865   /* get the entity type and handle accordingly */
866   etype=dmmoab->mbiface->type_from_handle(ent);
867   if(etype >= moab::MBPOLYHEDRON) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Entity type on the boundary skin is invalid. EntityType = %D\n",etype);
868 
869   /* get the entity dimension */
870   edim=dmmoab->mbiface->dimension_from_handle(ent);
871 
872   *ent_on_boundary=PETSC_FALSE;
873   if(etype == moab::MBVERTEX && edim == 0) {
874     *ent_on_boundary=((dmmoab->bndyvtx->index(ent) >= 0) ? PETSC_TRUE:PETSC_FALSE);
875   }
876   else {
877     if (edim == dmmoab->dim) {  /* check the higher-dimensional elements first */
878       if (dmmoab->bndyelems->index(ent) >= 0) *ent_on_boundary=PETSC_TRUE;
879     }
880     else {                      /* next check the lower-dimensional faces */
881       if (dmmoab->bndyfaces->index(ent) >= 0) *ent_on_boundary=PETSC_TRUE;
882     }
883   }
884   PetscFunctionReturn(0);
885 }
886 
887 
888 /*@
889   DMMoabIsEntityOnBoundary - Check whether a given entity is on the boundary (vertex, edge, face, element)
890 
891   Input Parameter:
892 . dm - The DMMoab object
893 . nconn - Number of handles
894 . cnt - Array of entity handles
895 
896   Output Parameter:
897 . isbdvtx - Array of boundary markers - PETSC_TRUE if entity on boundary; PETSC_FALSE otherwise
898 
899   Level: beginner
900 
901 .seealso: DMMoabIsEntityOnBoundary()
902 @*/
903 PetscErrorCode DMMoabCheckBoundaryVertices(DM dm,PetscInt nconn,const moab::EntityHandle *cnt,PetscBool* isbdvtx)
904 {
905   DM_Moab        *dmmoab;
906   PetscInt       i;
907 
908   PetscFunctionBegin;
909   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
910   PetscValidPointer(cnt,3);
911   PetscValidPointer(isbdvtx,4);
912   dmmoab = (DM_Moab*)(dm)->data;
913 
914   for (i=0; i < nconn; ++i) {
915     isbdvtx[i]=(dmmoab->bndyvtx->index(cnt[i]) >= 0 ? PETSC_TRUE:PETSC_FALSE);
916   }
917   PetscFunctionReturn(0);
918 }
919 
920 
921 /*@
922   DMMoabGetBoundaryMarkers - Return references to the vertices, faces, elements on the boundary
923 
924   Input Parameter:
925 . dm - The DMMoab object
926 
927   Output Parameter:
928 . bdvtx - Boundary vertices
929 . bdelems - Boundary elements
930 . bdfaces - Boundary faces
931 
932   Level: beginner
933 
934 .seealso: DMMoabCheckBoundaryVertices(), DMMoabIsEntityOnBoundary()
935 @*/
936 PetscErrorCode DMMoabGetBoundaryMarkers(DM dm,const moab::Range **bdvtx,const moab::Range** bdelems,const moab::Range** bdfaces)
937 {
938   DM_Moab        *dmmoab;
939 
940   PetscFunctionBegin;
941   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
942   dmmoab = (DM_Moab*)(dm)->data;
943 
944   if (bdvtx)  *bdvtx = dmmoab->bndyvtx;
945   if (bdfaces)  *bdfaces = dmmoab->bndyfaces;
946   if (bdelems)  *bdfaces = dmmoab->bndyelems;
947   PetscFunctionReturn(0);
948 }
949 
950 
951 PETSC_EXTERN PetscErrorCode DMDestroy_Moab(DM dm)
952 {
953   PetscErrorCode  ierr;
954   PetscInt        i;
955   moab::ErrorCode merr;
956   DM_Moab        *dmmoab = (DM_Moab*)dm->data;
957 
958   PetscFunctionBegin;
959   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
960 
961   dmmoab->refct--;
962   if (!dmmoab->refct) {
963     delete dmmoab->vlocal;
964     delete dmmoab->vowned;
965     delete dmmoab->vghost;
966     delete dmmoab->elocal;
967     delete dmmoab->eghost;
968     delete dmmoab->bndyvtx;
969     delete dmmoab->bndyfaces;
970     delete dmmoab->bndyelems;
971 
972     ierr = PetscFree(dmmoab->gsindices);CHKERRQ(ierr);
973     ierr = PetscFree2(dmmoab->gidmap,dmmoab->lidmap);CHKERRQ(ierr);
974     ierr = PetscFree(dmmoab->dfill);CHKERRQ(ierr);
975     ierr = PetscFree(dmmoab->ofill);CHKERRQ(ierr);
976     if (dmmoab->fieldNames) {
977       for(i=0; i<dmmoab->numFields; i++) {
978         ierr = PetscFree(dmmoab->fieldNames[i]);CHKERRQ(ierr);
979       }
980       ierr = PetscFree(dmmoab->fieldNames);CHKERRQ(ierr);
981     }
982 
983     if (dmmoab->nhlevels) {
984       ierr = PetscFree(dmmoab->hsets);CHKERRQ(ierr);
985       dmmoab->nhlevels=0;
986       if (!dmmoab->hlevel && dmmoab->icreatedinstance) delete dmmoab->hierarchy;
987       dmmoab->hierarchy=NULL;
988     }
989 
990     if (dmmoab->icreatedinstance) {
991       merr = dmmoab->mbiface->delete_mesh();MBERRNM(merr);
992       delete dmmoab->mbiface;
993     }
994     dmmoab->mbiface = NULL;
995     dmmoab->pcomm = NULL;
996 
997     ierr = VecScatterDestroy(&dmmoab->ltog_sendrecv);CHKERRQ(ierr);
998     ierr = ISLocalToGlobalMappingDestroy(&dmmoab->ltog_map);CHKERRQ(ierr);
999     ierr = PetscFree(dm->data);CHKERRQ(ierr);
1000   }
1001   PetscFunctionReturn(0);
1002 }
1003 
1004 
1005 PETSC_EXTERN PetscErrorCode DMSetFromOptions_Moab(PetscOptionItems *PetscOptionsObject,DM dm)
1006 {
1007   PetscErrorCode ierr;
1008   DM_Moab        *dmmoab = (DM_Moab*)dm->data;
1009 
1010   PetscFunctionBegin;
1011   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1012   ierr = PetscOptionsHead(PetscOptionsObject,"DMMoab Options");CHKERRQ(ierr);
1013   ierr  = PetscOptionsInt("-dm_moab_rw_dbg", "The verbosity level for reading and writing MOAB meshes", "DMView", dmmoab->rw_dbglevel, &dmmoab->rw_dbglevel, NULL);CHKERRQ(ierr);
1014   ierr  = PetscOptionsBool("-dm_moab_partiton_by_rank", "Use partition by rank when reading MOAB meshes from file", "DMView", dmmoab->partition_by_rank, &dmmoab->partition_by_rank, NULL);CHKERRQ(ierr);
1015   /* TODO: typically, the read options are needed before a DM is completely created and available in which case, the options wont be available ?? */
1016   ierr  = PetscOptionsString("-dm_moab_read_opts", "Extra options to enable MOAB reader to load DM from file", "DMView", dmmoab->extra_read_options, dmmoab->extra_read_options, PETSC_MAX_PATH_LEN, NULL);CHKERRQ(ierr);
1017   ierr  = PetscOptionsString("-dm_moab_write_opts", "Extra options to enable MOAB writer to serialize DM to file", "DMView", dmmoab->extra_write_options, dmmoab->extra_write_options, PETSC_MAX_PATH_LEN, NULL);CHKERRQ(ierr);
1018   ierr  = PetscOptionsEnum("-dm_moab_read_mode", "MOAB parallel read mode", "DMView", MoabReadModes, (PetscEnum)dmmoab->read_mode, (PetscEnum*)&dmmoab->read_mode, NULL);CHKERRQ(ierr);
1019   ierr  = PetscOptionsEnum("-dm_moab_write_mode", "MOAB parallel write mode", "DMView", MoabWriteModes, (PetscEnum)dmmoab->write_mode, (PetscEnum*)&dmmoab->write_mode, NULL);CHKERRQ(ierr);
1020   PetscFunctionReturn(0);
1021 }
1022 
1023 
1024 PETSC_EXTERN PetscErrorCode DMSetUp_Moab(DM dm)
1025 {
1026   PetscErrorCode          ierr;
1027   moab::ErrorCode         merr;
1028   Vec                     local, global;
1029   IS                      from,to;
1030   moab::Range::iterator   iter;
1031   PetscInt                i,j,f,bs,vent,totsize,*lgmap;
1032   DM_Moab                *dmmoab = (DM_Moab*)dm->data;
1033   moab::Range             adjs;
1034 
1035   PetscFunctionBegin;
1036   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1037   /* Get the local and shared vertices and cache it */
1038   if (dmmoab->mbiface == NULL || dmmoab->pcomm == NULL) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ORDER, "Set the MOAB Interface and ParallelComm objects before calling SetUp.");
1039 
1040   /* Get the entities recursively in the current part of the mesh, if user did not set the local vertices explicitly */
1041   if (dmmoab->vlocal->empty())
1042   {
1043     //merr = dmmoab->mbiface->get_entities_by_type(dmmoab->fileset,moab::MBVERTEX,*dmmoab->vlocal,true);MBERRNM(merr);
1044     merr = dmmoab->mbiface->get_entities_by_dimension(dmmoab->fileset, 0, *dmmoab->vlocal, false);MBERRNM(merr);
1045 
1046     /* filter based on parallel status */
1047     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->vlocal,PSTATUS_NOT_OWNED,PSTATUS_NOT,-1,dmmoab->vowned);MBERRNM(merr);
1048 
1049     /* filter all the non-owned and shared entities out of the list */
1050     adjs = moab::subtract(*dmmoab->vlocal, *dmmoab->vowned);
1051     merr = dmmoab->pcomm->filter_pstatus(adjs,PSTATUS_GHOST|PSTATUS_INTERFACE,PSTATUS_OR,-1,dmmoab->vghost);MBERRNM(merr);
1052     adjs = moab::subtract(adjs, *dmmoab->vghost);
1053     *dmmoab->vlocal = moab::subtract(*dmmoab->vlocal, adjs);
1054 
1055     /* compute and cache the sizes of local and ghosted entities */
1056     dmmoab->nloc = dmmoab->vowned->size();
1057     dmmoab->nghost = dmmoab->vghost->size();
1058 
1059     ierr = MPIU_Allreduce(&dmmoab->nloc, &dmmoab->n, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr);
1060     PetscInfo4(NULL, "Filset ID: %u, Vertices: local - %D, owned - %D, ghosted - %D.\n", dmmoab->fileset, dmmoab->vlocal->size(), dmmoab->nloc, dmmoab->nghost);
1061   }
1062 
1063   {
1064     /* get the information about the local elements in the mesh */
1065     dmmoab->eghost->clear();
1066 
1067     /* first decipher the leading dimension */
1068     for (i=3;i>0;i--) {
1069       dmmoab->elocal->clear();
1070       merr = dmmoab->mbiface->get_entities_by_dimension(dmmoab->fileset, i, *dmmoab->elocal, false);MBERRNM(merr);
1071 
1072       /* store the current mesh dimension */
1073       if (dmmoab->elocal->size()) {
1074         dmmoab->dim=i;
1075         break;
1076       }
1077     }
1078 
1079     ierr = DMSetDimension(dm, dmmoab->dim);CHKERRQ(ierr);
1080 
1081     /* filter the ghosted and owned element list */
1082     *dmmoab->eghost = *dmmoab->elocal;
1083     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->elocal,PSTATUS_NOT_OWNED,PSTATUS_NOT);MBERRNM(merr);
1084     *dmmoab->eghost = moab::subtract(*dmmoab->eghost, *dmmoab->elocal);
1085 
1086     dmmoab->neleloc = dmmoab->elocal->size();
1087     dmmoab->neleghost = dmmoab->eghost->size();
1088 
1089     ierr = MPIU_Allreduce(&dmmoab->neleloc, &dmmoab->nele, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr);
1090     PetscInfo3(NULL, "%d-dim elements: owned - %D, ghosted - %D.\n", dmmoab->dim, dmmoab->neleloc, dmmoab->neleghost);
1091   }
1092 
1093   bs = dmmoab->bs;
1094   if (!dmmoab->ltog_tag) {
1095     /* Get the global ID tag. The global ID tag is applied to each
1096        vertex. It acts as an global identifier which MOAB uses to
1097        assemble the individual pieces of the mesh */
1098     merr = dmmoab->mbiface->tag_get_handle(GLOBAL_ID_TAG_NAME, dmmoab->ltog_tag);MBERRNM(merr);
1099   }
1100 
1101   totsize=dmmoab->vlocal->size();
1102   if (totsize != dmmoab->nloc+dmmoab->nghost) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mismatch between local and owned+ghost vertices. %D != %D.",totsize,dmmoab->nloc+dmmoab->nghost);
1103   ierr = PetscCalloc1(totsize,&dmmoab->gsindices);CHKERRQ(ierr);
1104   {
1105     /* first get the local indices */
1106     merr = dmmoab->mbiface->tag_get_data(dmmoab->ltog_tag,*dmmoab->vowned,&dmmoab->gsindices[0]);MBERRNM(merr);
1107     if (dmmoab->nghost) {  /* next get the ghosted indices */
1108       merr = dmmoab->mbiface->tag_get_data(dmmoab->ltog_tag,*dmmoab->vghost,&dmmoab->gsindices[dmmoab->nloc]);MBERRNM(merr);
1109     }
1110 
1111     /* find out the local and global minima of GLOBAL_ID */
1112     dmmoab->lminmax[0]=dmmoab->lminmax[1]=dmmoab->gsindices[0];
1113     for (i=0; i<totsize; ++i) {
1114       if(dmmoab->lminmax[0]>dmmoab->gsindices[i]) dmmoab->lminmax[0]=dmmoab->gsindices[i];
1115       if(dmmoab->lminmax[1]<dmmoab->gsindices[i]) dmmoab->lminmax[1]=dmmoab->gsindices[i];
1116     }
1117 
1118     ierr = MPIU_Allreduce(&dmmoab->lminmax[0], &dmmoab->gminmax[0], 1, MPI_INT, MPI_MIN, ((PetscObject)dm)->comm);CHKERRQ(ierr);
1119     ierr = MPIU_Allreduce(&dmmoab->lminmax[1], &dmmoab->gminmax[1], 1, MPI_INT, MPI_MAX, ((PetscObject)dm)->comm);CHKERRQ(ierr);
1120 
1121     /* set the GID map */
1122     for (i=0; i<totsize; ++i) {
1123       dmmoab->gsindices[i]-=dmmoab->gminmax[0];   /* zero based index needed for IS */
1124     }
1125     dmmoab->lminmax[0]-=dmmoab->gminmax[0];
1126     dmmoab->lminmax[1]-=dmmoab->gminmax[0];
1127 
1128     PetscInfo4(NULL, "GLOBAL_ID: Local [min, max] - [%D, %D], Global [min, max] - [%D, %D]\n", dmmoab->lminmax[0], dmmoab->lminmax[1], dmmoab->gminmax[0], dmmoab->gminmax[1]);
1129   }
1130   if(!(dmmoab->bs==dmmoab->numFields || dmmoab->bs == 1)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mismatch between block size and number of component fields. %D != 1 OR %D != %D.",dmmoab->bs,dmmoab->bs,dmmoab->numFields);
1131 
1132   {
1133     dmmoab->seqstart=((PetscInt)dmmoab->vlocal->front());
1134     dmmoab->seqend=((PetscInt)dmmoab->vlocal->back());
1135     PetscInfo2(NULL, "SEQUENCE: Local [min, max] - [%D, %D]\n", dmmoab->seqstart, dmmoab->seqend);
1136 
1137     ierr = PetscMalloc2(dmmoab->seqend-dmmoab->seqstart+1,&dmmoab->gidmap,dmmoab->seqend-dmmoab->seqstart+1,&dmmoab->lidmap);CHKERRQ(ierr);
1138     ierr = PetscMalloc1(totsize*dmmoab->numFields,&lgmap);CHKERRQ(ierr);
1139 
1140     i=j=0;
1141     /* set the owned vertex data first */
1142     for(moab::Range::iterator iter = dmmoab->vowned->begin(); iter != dmmoab->vowned->end(); iter++,i++) {
1143       vent=(PetscInt)(*iter)-dmmoab->seqstart;
1144       dmmoab->gidmap[vent]=dmmoab->gsindices[i];
1145       dmmoab->lidmap[vent]=i;
1146       for (f=0;f<dmmoab->numFields;f++,j++) {
1147         lgmap[j]=(bs > 1 ? dmmoab->gsindices[i]*dmmoab->numFields+f : totsize*f+dmmoab->gsindices[i]);
1148       }
1149     }
1150     /* next arrange all the ghosted data information */
1151     for(moab::Range::iterator iter = dmmoab->vghost->begin(); iter != dmmoab->vghost->end(); iter++,i++) {
1152       vent=(PetscInt)(*iter)-dmmoab->seqstart;
1153       dmmoab->gidmap[vent]=dmmoab->gsindices[i];
1154       dmmoab->lidmap[vent]=i;
1155       for (f=0;f<dmmoab->numFields;f++,j++) {
1156         lgmap[j]=(bs > 1 ? dmmoab->gsindices[i]*dmmoab->numFields+f : totsize*f+dmmoab->gsindices[i]);
1157       }
1158     }
1159 
1160     /* We need to create the Global to Local Vector Scatter Contexts
1161        1) First create a local and global vector
1162        2) Create a local and global IS
1163        3) Create VecScatter and LtoGMapping objects
1164        4) Cleanup the IS and Vec objects
1165     */
1166     ierr = DMCreateGlobalVector(dm, &global);CHKERRQ(ierr);
1167     ierr = DMCreateLocalVector(dm, &local);CHKERRQ(ierr);
1168 
1169     ierr = VecGetOwnershipRange(global, &dmmoab->vstart, &dmmoab->vend);CHKERRQ(ierr);
1170 
1171     /* global to local must retrieve ghost points */
1172     ierr = ISCreateStride(((PetscObject)dm)->comm,dmmoab->nloc*dmmoab->numFields,dmmoab->vstart,1,&from);CHKERRQ(ierr);
1173     ierr = ISSetBlockSize(from,bs);CHKERRQ(ierr);
1174 
1175     ierr = ISCreateGeneral(((PetscObject)dm)->comm,dmmoab->nloc*dmmoab->numFields,&lgmap[0],PETSC_COPY_VALUES,&to);CHKERRQ(ierr);
1176     ierr = ISSetBlockSize(to,bs);CHKERRQ(ierr);
1177 
1178     if (!dmmoab->ltog_map) {
1179       /* create to the local to global mapping for vectors in order to use VecSetValuesLocal */
1180       ierr = ISLocalToGlobalMappingCreate(((PetscObject)dm)->comm,dmmoab->bs,totsize*dmmoab->numFields,lgmap,
1181                                           PETSC_COPY_VALUES,&dmmoab->ltog_map);CHKERRQ(ierr);
1182     }
1183 
1184     /* now create the scatter object from local to global vector */
1185     ierr = VecScatterCreate(local,from,global,to,&dmmoab->ltog_sendrecv);CHKERRQ(ierr);
1186 
1187     /* clean up IS, Vec */
1188     ierr = PetscFree(lgmap);CHKERRQ(ierr);
1189     ierr = ISDestroy(&from);CHKERRQ(ierr);
1190     ierr = ISDestroy(&to);CHKERRQ(ierr);
1191     ierr = VecDestroy(&local);CHKERRQ(ierr);
1192     ierr = VecDestroy(&global);CHKERRQ(ierr);
1193   }
1194 
1195   dmmoab->bndyvtx = new moab::Range();
1196   dmmoab->bndyfaces = new moab::Range();
1197   dmmoab->bndyelems = new moab::Range();
1198   /* skin the boundary and store nodes */
1199   {
1200     /* get the skin vertices of boundary faces for the current partition and then filter
1201        the local, boundary faces, vertices and elements alone via PSTATUS flags;
1202        this should not give us any ghosted boundary, but if user needs such a functionality
1203        it would be easy to add it based on the find_skin query below */
1204     moab::Skinner skinner(dmmoab->mbiface);
1205 
1206     /* get the entities on the skin - only the faces */
1207     merr = skinner.find_skin(dmmoab->fileset, *dmmoab->elocal, false, *dmmoab->bndyfaces, NULL, false, true, false);MBERRNM(merr); // 'false' param indicates we want faces back, not vertices
1208 
1209     /* filter all the non-owned and shared entities out of the list */
1210     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->bndyfaces,PSTATUS_NOT_OWNED,PSTATUS_NOT);MBERRNM(merr);
1211     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->bndyfaces,PSTATUS_SHARED,PSTATUS_NOT);MBERRNM(merr);
1212 
1213     /* get all the nodes via connectivity and the parent elements via adjacency information */
1214     merr = dmmoab->mbiface->get_connectivity(*dmmoab->bndyfaces, *dmmoab->bndyvtx, false);MBERRNM(ierr);
1215     merr = dmmoab->mbiface->get_adjacencies(*dmmoab->bndyvtx, dmmoab->dim, false, *dmmoab->bndyelems, moab::Interface::UNION);MBERRNM(ierr);
1216   }
1217   PetscInfo3(NULL, "Found %D boundary vertices, %D boundary faces and %D boundary elements.\n", dmmoab->bndyvtx->size(), dmmoab->bndyfaces->size(), dmmoab->bndyelems->size());
1218   PetscFunctionReturn(0);
1219 }
1220 
1221 
1222 #undef __FUNCT__
1223 #define __FUNCT__ "DMMoabCreateVertices"
1224 /*@
1225   DMMoabCreateVertices - Creates and adds several vertices to the primary set represented by the DM.
1226 
1227   Collective on MPI_Comm
1228 
1229   Input Parameters:
1230 + dm - The DM object
1231 . type - The type of element to create and add (Edge/Tri/Quad/Tet/Hex/Prism/Pyramid/Polygon/Polyhedra)
1232 . conn - The connectivity of the element
1233 . nverts - The number of vertices that form the element
1234 
1235   Output Parameter:
1236 . overts  - The list of vertices that were created (can be NULL)
1237 
1238   Level: beginner
1239 
1240 .keywords: DM, create vertices
1241 
1242 .seealso: DMMoabCreateSubmesh(), DMMoabCreateElement()
1243 @*/
1244 PetscErrorCode DMMoabCreateVertices(DM dm, const PetscReal* coords, PetscInt nverts, moab::Range* overts)
1245 {
1246   moab::ErrorCode     merr;
1247   DM_Moab            *dmmoab;
1248   moab::Range         verts;
1249 
1250   PetscFunctionBegin;
1251   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1252   PetscValidPointer(coords,2);
1253 
1254   dmmoab = (DM_Moab*) dm->data;
1255 
1256   /* Insert new points */
1257   merr = dmmoab->mbiface->create_vertices(&coords[0],nverts,verts);MBERRNM(merr);
1258   merr = dmmoab->mbiface->add_entities(dmmoab->fileset,verts);MBERRNM(merr);
1259 
1260   if (overts) *overts=verts;
1261   PetscFunctionReturn(0);
1262 }
1263 
1264 
1265 #undef __FUNCT__
1266 #define __FUNCT__ "DMMoabCreateElement"
1267 /*@
1268   DMMoabCreateElement - Adds an element of specified type to the primary set represented by the DM.
1269 
1270   Collective on MPI_Comm
1271 
1272   Input Parameters:
1273 + dm - The DM object
1274 . type - The type of element to create and add (Edge/Tri/Quad/Tet/Hex/Prism/Pyramid/Polygon/Polyhedra)
1275 . conn - The connectivity of the element
1276 . nverts - The number of vertices that form the element
1277 
1278   Output Parameter:
1279 . oelem  - The handle to the element created and added to the DM object
1280 
1281   Level: beginner
1282 
1283 .keywords: DM, create element
1284 
1285 .seealso: DMMoabCreateSubmesh(), DMMoabCreateVertices()
1286 @*/
1287 PetscErrorCode DMMoabCreateElement(DM dm, const moab::EntityType type, const moab::EntityHandle* conn, PetscInt nverts, moab::EntityHandle* oelem)
1288 {
1289   moab::ErrorCode     merr;
1290   DM_Moab            *dmmoab;
1291   moab::EntityHandle  elem;
1292 
1293   PetscFunctionBegin;
1294   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1295   PetscValidPointer(conn,3);
1296 
1297   dmmoab = (DM_Moab*) dm->data;
1298 
1299   /* Insert new element */
1300   merr = dmmoab->mbiface->create_element(type,conn,nverts,elem);MBERRNM(merr);
1301   merr = dmmoab->mbiface->add_entities(dmmoab->fileset,&elem,1);MBERRNM(merr);
1302 
1303   if (oelem) *oelem = elem;
1304   PetscFunctionReturn(0);
1305 }
1306 
1307 
1308 #undef __FUNCT__
1309 #define __FUNCT__ "DMMoabCreateSubmesh"
1310 /*@
1311   DMMoabCreateSubmesh - Creates a sub-DM object with a set that contains all vertices/elements of the parent
1312   in addition to providing support for dynamic mesh modifications. This is useful for AMR calculations to
1313   create a DM object on a refined level.
1314 
1315   Collective on MPI_Comm
1316 
1317   Input Parameters:
1318 + dm - The DM object
1319 
1320   Output Parameter:
1321 . newdm  - The sub DM object with updated set information
1322 
1323   Level: advanced
1324 
1325 .keywords: DM, sub-DM
1326 
1327 .seealso: DMCreate(), DMMoabCreateVertices(), DMMoabCreateElement()
1328 @*/
1329 PetscErrorCode DMMoabCreateSubmesh(DM dm, DM *newdm)
1330 {
1331   DM_Moab            *dmmoab;
1332   DM_Moab            *ndmmoab;
1333   moab::ErrorCode    merr;
1334   PetscErrorCode     ierr;
1335 
1336   PetscFunctionBegin;
1337   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1338 
1339   dmmoab = (DM_Moab*) dm->data;
1340 
1341   /* Create the basic DMMoab object and keep the default parameters created by DM impls */
1342   ierr = DMMoabCreateMoab(((PetscObject)dm)->comm, dmmoab->mbiface, dmmoab->pcomm, &dmmoab->ltog_tag, PETSC_NULL, newdm);CHKERRQ(ierr);
1343 
1344   /* get all the necessary handles from the private DM object */
1345   ndmmoab = (DM_Moab*) (*newdm)->data;
1346 
1347   /* set the sub-mesh's parent DM reference */
1348   ndmmoab->parent = &dm;
1349 
1350   /* create a file set to associate all entities in current mesh */
1351   merr = ndmmoab->mbiface->create_meshset(moab::MESHSET_SET, ndmmoab->fileset);MBERR("Creating file set failed", merr);
1352 
1353   /* create a meshset and then add old fileset as child */
1354   merr = ndmmoab->mbiface->add_entities(ndmmoab->fileset, *dmmoab->vlocal);MBERR("Adding child vertices to parent failed", merr);
1355   merr = ndmmoab->mbiface->add_entities(ndmmoab->fileset, *dmmoab->elocal);MBERR("Adding child elements to parent failed", merr);
1356 
1357   /* preserve the field association between the parent and sub-mesh objects */
1358   ierr = DMMoabSetFieldNames(*newdm, dmmoab->numFields, dmmoab->fieldNames);CHKERRQ(ierr);
1359   PetscFunctionReturn(0);
1360 }
1361 
1362 
1363 #undef __FUNCT__
1364 #define __FUNCT__ "DMMoabView_Ascii"
1365 PETSC_EXTERN PetscErrorCode DMMoabView_Ascii(DM dm, PetscViewer viewer)
1366 {
1367   DM_Moab          *dmmoab = (DM_Moab*)(dm)->data;
1368   const char       *name;
1369   MPI_Comm          comm;
1370   PetscMPIInt       size;
1371   PetscErrorCode    ierr;
1372 
1373   PetscFunctionBegin;
1374   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1375   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
1376   ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
1377   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1378   if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimensions:\n", name, dmmoab->dim);CHKERRQ(ierr);}
1379   else      {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dmmoab->dim);CHKERRQ(ierr);}
1380   /* print details about the global mesh */
1381   {
1382     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1383     ierr = PetscViewerASCIIPrintf(viewer, "Sizes: cells=%D, vertices=%D, blocks=%D\n", dmmoab->n, dmmoab->nele, dmmoab->bs);CHKERRQ(ierr);
1384     /* print boundary data */
1385     ierr = PetscViewerASCIIPrintf(viewer, "Boundary trace:\n", dmmoab->bndyelems->size(), dmmoab->bndyfaces->size(), dmmoab->bndyvtx->size());CHKERRQ(ierr);
1386     {
1387       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1388       ierr = PetscViewerASCIIPrintf(viewer, "cells=%D, faces=%D, vertices=%D\n", dmmoab->bndyelems->size(), dmmoab->bndyfaces->size(), dmmoab->bndyvtx->size());CHKERRQ(ierr);
1389       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1390     }
1391     /* print field data */
1392     ierr = PetscViewerASCIIPrintf(viewer, "Fields: %D components\n", dmmoab->numFields);CHKERRQ(ierr);
1393     {
1394       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1395       for (int i=0; i<dmmoab->numFields; ++i) {
1396         ierr = PetscViewerASCIIPrintf(viewer, "[%D] - %s\n", i, dmmoab->fieldNames[i]);CHKERRQ(ierr);
1397       }
1398       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1399     }
1400     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1401   }
1402   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1403   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1404   PetscFunctionReturn(0);
1405 }
1406 
1407 #undef __FUNCT__
1408 #define __FUNCT__ "DMMoabView_VTK"
1409 PETSC_EXTERN PetscErrorCode DMMoabView_VTK(DM dm,PetscViewer v)
1410 {
1411   PetscFunctionReturn(0);
1412 }
1413 
1414 #undef __FUNCT__
1415 #define __FUNCT__ "DMMoabView_HDF5"
1416 PETSC_EXTERN PetscErrorCode DMMoabView_HDF5(DM dm,PetscViewer v)
1417 {
1418   PetscFunctionReturn(0);
1419 }
1420 
1421 #undef __FUNCT__
1422 #define __FUNCT__ "DMView_Moab"
1423 PETSC_EXTERN PetscErrorCode DMView_Moab(DM dm,PetscViewer viewer)
1424 {
1425   PetscBool      iascii, ishdf5, isvtk;
1426   PetscErrorCode ierr;
1427 
1428   PetscFunctionBegin;
1429   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1430   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1431   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
1432   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
1433   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1434   if (iascii) {
1435     ierr = DMMoabView_Ascii(dm, viewer);CHKERRQ(ierr);
1436   } else if (ishdf5) {
1437 #if defined(PETSC_HAVE_HDF5) && defined(MOAB_HAVE_HDF5)
1438     ierr = PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_VIZ);CHKERRQ(ierr);
1439     ierr = DMMoabView_HDF5(dm, viewer);CHKERRQ(ierr);
1440     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
1441 #else
1442     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1443 #endif
1444   }
1445   else if (isvtk) {
1446     ierr = DMMoabView_VTK(dm, viewer);CHKERRQ(ierr);
1447   }
1448   PetscFunctionReturn(0);
1449 }
1450 
1451 
1452 #undef __FUNCT__
1453 #define __FUNCT__ "DMInitialize_Moab"
1454 PETSC_EXTERN PetscErrorCode DMInitialize_Moab(DM dm)
1455 {
1456   PetscFunctionBegin;
1457   dm->ops->view                            = DMView_Moab;
1458   dm->ops->load                            = NULL /*DMLoad_Moab*/;
1459   dm->ops->setfromoptions                  = DMSetFromOptions_Moab;
1460   dm->ops->clone                           = DMClone_Moab;
1461   dm->ops->setup                           = DMSetUp_Moab;
1462   dm->ops->createdefaultsection            = NULL;
1463   dm->ops->createdefaultconstraints        = NULL;
1464   dm->ops->createglobalvector              = DMCreateGlobalVector_Moab;
1465   dm->ops->createlocalvector               = DMCreateLocalVector_Moab;
1466   dm->ops->getlocaltoglobalmapping         = NULL;
1467   dm->ops->createfieldis                   = NULL;
1468   dm->ops->createcoordinatedm              = NULL /*DMCreateCoordinateDM_Moab*/;
1469   dm->ops->getcoloring                     = NULL;
1470   dm->ops->creatematrix                    = DMCreateMatrix_Moab;
1471   dm->ops->createinterpolation             = DMCreateInterpolation_Moab;
1472   dm->ops->getaggregates                   = NULL;
1473   dm->ops->getinjection                    = NULL /*DMCreateInjection_Moab*/;
1474   dm->ops->refine                          = DMRefine_Moab;
1475   dm->ops->coarsen                         = DMCoarsen_Moab;
1476   dm->ops->refinehierarchy                 = DMRefineHierarchy_Moab;
1477   dm->ops->coarsenhierarchy                = DMCoarsenHierarchy_Moab;
1478   dm->ops->globaltolocalbegin              = DMGlobalToLocalBegin_Moab;
1479   dm->ops->globaltolocalend                = DMGlobalToLocalEnd_Moab;
1480   dm->ops->localtoglobalbegin              = DMLocalToGlobalBegin_Moab;
1481   dm->ops->localtoglobalend                = DMLocalToGlobalEnd_Moab;
1482   dm->ops->destroy                         = DMDestroy_Moab;
1483   dm->ops->createsubdm                     = NULL /*DMCreateSubDM_Moab*/;
1484   dm->ops->getdimpoints                    = NULL /*DMGetDimPoints_Moab*/;
1485   dm->ops->locatepoints                    = NULL /*DMLocatePoints_Moab*/;
1486   PetscFunctionReturn(0);
1487 }
1488 
1489 
1490 #undef __FUNCT__
1491 #define __FUNCT__ "DMClone_Moab"
1492 PETSC_EXTERN PetscErrorCode DMClone_Moab(DM dm, DM *newdm)
1493 {
1494   PetscErrorCode     ierr;
1495 
1496   PetscFunctionBegin;
1497   ierr = PetscObjectChangeTypeName((PetscObject) *newdm, DMMOAB);CHKERRQ(ierr);
1498 
1499   /* get all the necessary handles from the private DM object */
1500   (*newdm)->data = (DM_Moab*) dm->data;
1501   ((DM_Moab*)dm->data)->refct++;
1502 
1503   ierr = DMInitialize_Moab(*newdm);CHKERRQ(ierr);
1504   PetscFunctionReturn(0);
1505 }
1506 
1507 
1508 #undef __FUNCT__
1509 #define __FUNCT__ "DMCreate_Moab"
1510 PETSC_EXTERN PetscErrorCode DMCreate_Moab(DM dm)
1511 {
1512   PetscErrorCode ierr;
1513 
1514   PetscFunctionBegin;
1515   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1516   ierr = PetscNewLog(dm,(DM_Moab**)&dm->data);CHKERRQ(ierr);
1517 
1518   ((DM_Moab*)dm->data)->bs = 1;
1519   ((DM_Moab*)dm->data)->numFields = 1;
1520   ((DM_Moab*)dm->data)->n = 0;
1521   ((DM_Moab*)dm->data)->nloc = 0;
1522   ((DM_Moab*)dm->data)->nghost = 0;
1523   ((DM_Moab*)dm->data)->nele = 0;
1524   ((DM_Moab*)dm->data)->neleloc = 0;
1525   ((DM_Moab*)dm->data)->neleghost = 0;
1526   ((DM_Moab*)dm->data)->ltog_map = NULL;
1527   ((DM_Moab*)dm->data)->ltog_sendrecv = NULL;
1528 
1529   ((DM_Moab*)dm->data)->refct = 1;
1530   ((DM_Moab*)dm->data)->parent = NULL;
1531   ((DM_Moab*)dm->data)->vlocal = new moab::Range();
1532   ((DM_Moab*)dm->data)->vowned = new moab::Range();
1533   ((DM_Moab*)dm->data)->vghost = new moab::Range();
1534   ((DM_Moab*)dm->data)->elocal = new moab::Range();
1535   ((DM_Moab*)dm->data)->eghost = new moab::Range();
1536 
1537   ierr = DMInitialize_Moab(dm);CHKERRQ(ierr);
1538   PetscFunctionReturn(0);
1539 }
1540 
1541