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