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