xref: /petsc/src/dm/impls/moab/dmmoab.cxx (revision daa037dfd3c3bec8dc8659548d2b20b07c1dc6de)
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 %D local and %D 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 = %D", 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   PetscCall(PetscOptionsHead(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   PetscFunctionReturn(0);
947 }
948 
949 PETSC_EXTERN PetscErrorCode DMSetUp_Moab(DM dm)
950 {
951   moab::ErrorCode         merr;
952   Vec                     local, global;
953   IS                      from, to;
954   moab::Range::iterator   iter;
955   PetscInt                i, j, f, bs, vent, totsize, *lgmap;
956   DM_Moab                *dmmoab = (DM_Moab*)dm->data;
957   moab::Range             adjs;
958 
959   PetscFunctionBegin;
960   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
961   /* Get the local and shared vertices and cache it */
962   PetscCheckFalse(dmmoab->mbiface == NULL,PETSC_COMM_WORLD, PETSC_ERR_ORDER, "Set the MOAB Interface before calling SetUp.");
963 #ifdef MOAB_HAVE_MPI
964   PetscCheckFalse(dmmoab->pcomm == NULL,PETSC_COMM_WORLD, PETSC_ERR_ORDER, "Set the MOAB ParallelComm object before calling SetUp.");
965 #endif
966 
967   /* Get the entities recursively in the current part of the mesh, if user did not set the local vertices explicitly */
968   if (dmmoab->vlocal->empty())
969   {
970     //merr = dmmoab->mbiface->get_entities_by_type(dmmoab->fileset,moab::MBVERTEX,*dmmoab->vlocal,true);MBERRNM(merr);
971     merr = dmmoab->mbiface->get_entities_by_dimension(dmmoab->fileset, 0, *dmmoab->vlocal, false); MBERRNM(merr);
972 
973 #ifdef MOAB_HAVE_MPI
974     /* filter based on parallel status */
975     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->vlocal, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, dmmoab->vowned); MBERRNM(merr);
976 
977     /* filter all the non-owned and shared entities out of the list */
978     // *dmmoab->vghost = moab::subtract(*dmmoab->vlocal, *dmmoab->vowned);
979     adjs = moab::subtract(*dmmoab->vlocal, *dmmoab->vowned);
980     merr = dmmoab->pcomm->filter_pstatus(adjs, PSTATUS_GHOST | PSTATUS_INTERFACE, PSTATUS_OR, -1, dmmoab->vghost); MBERRNM(merr);
981     adjs = moab::subtract(adjs, *dmmoab->vghost);
982     *dmmoab->vlocal = moab::subtract(*dmmoab->vlocal, adjs);
983 #else
984     *dmmoab->vowned = *dmmoab->vlocal;
985 #endif
986 
987     /* compute and cache the sizes of local and ghosted entities */
988     dmmoab->nloc = dmmoab->vowned->size();
989     dmmoab->nghost = dmmoab->vghost->size();
990 
991 #ifdef MOAB_HAVE_MPI
992     PetscCall(MPIU_Allreduce(&dmmoab->nloc, &dmmoab->n, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm));
993     PetscInfo(NULL, "Filset ID: %u, Vertices: local - %D, owned - %D, ghosted - %D.\n", dmmoab->fileset, dmmoab->vlocal->size(), dmmoab->nloc, dmmoab->nghost);
994 #else
995     dmmoab->n = dmmoab->nloc;
996 #endif
997   }
998 
999   {
1000     /* get the information about the local elements in the mesh */
1001     dmmoab->eghost->clear();
1002 
1003     /* first decipher the leading dimension */
1004     for (i = 3; i > 0; i--) {
1005       dmmoab->elocal->clear();
1006       merr = dmmoab->mbiface->get_entities_by_dimension(dmmoab->fileset, i, *dmmoab->elocal, false); MBERRNM(merr);
1007 
1008       /* store the current mesh dimension */
1009       if (dmmoab->elocal->size()) {
1010         dmmoab->dim = i;
1011         break;
1012       }
1013     }
1014 
1015     PetscCall(DMSetDimension(dm, dmmoab->dim));
1016 
1017 #ifdef MOAB_HAVE_MPI
1018     /* filter the ghosted and owned element list */
1019     *dmmoab->eghost = *dmmoab->elocal;
1020     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->elocal, PSTATUS_NOT_OWNED, PSTATUS_NOT); MBERRNM(merr);
1021     *dmmoab->eghost = moab::subtract(*dmmoab->eghost, *dmmoab->elocal);
1022 #endif
1023 
1024     dmmoab->neleloc = dmmoab->elocal->size();
1025     dmmoab->neleghost = dmmoab->eghost->size();
1026 
1027 #ifdef MOAB_HAVE_MPI
1028     PetscCall(MPIU_Allreduce(&dmmoab->neleloc, &dmmoab->nele, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm));
1029     PetscInfo(NULL, "%d-dim elements: owned - %D, ghosted - %D.\n", dmmoab->dim, dmmoab->neleloc, dmmoab->neleghost);
1030 #else
1031     dmmoab->nele = dmmoab->neleloc;
1032 #endif
1033   }
1034 
1035   bs = dmmoab->bs;
1036   if (!dmmoab->ltog_tag) {
1037     /* Get the global ID tag. The global ID tag is applied to each
1038        vertex. It acts as an global identifier which MOAB uses to
1039        assemble the individual pieces of the mesh */
1040     merr = dmmoab->mbiface->tag_get_handle(GLOBAL_ID_TAG_NAME, dmmoab->ltog_tag); MBERRNM(merr);
1041   }
1042 
1043   totsize = dmmoab->vlocal->size();
1044   PetscCheckFalse(totsize != dmmoab->nloc + dmmoab->nghost,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mismatch between local and owned+ghost vertices. %D != %D.", totsize, dmmoab->nloc + dmmoab->nghost);
1045   PetscCall(PetscCalloc1(totsize, &dmmoab->gsindices));
1046   {
1047     /* first get the local indices */
1048     merr = dmmoab->mbiface->tag_get_data(dmmoab->ltog_tag, *dmmoab->vowned, &dmmoab->gsindices[0]); MBERRNM(merr);
1049     if (dmmoab->nghost) {  /* next get the ghosted indices */
1050       merr = dmmoab->mbiface->tag_get_data(dmmoab->ltog_tag, *dmmoab->vghost, &dmmoab->gsindices[dmmoab->nloc]); MBERRNM(merr);
1051     }
1052 
1053     /* find out the local and global minima of GLOBAL_ID */
1054     dmmoab->lminmax[0] = dmmoab->lminmax[1] = dmmoab->gsindices[0];
1055     for (i = 0; i < totsize; ++i) {
1056       if (dmmoab->lminmax[0] > dmmoab->gsindices[i]) dmmoab->lminmax[0] = dmmoab->gsindices[i];
1057       if (dmmoab->lminmax[1] < dmmoab->gsindices[i]) dmmoab->lminmax[1] = dmmoab->gsindices[i];
1058     }
1059 
1060     PetscCall(MPIU_Allreduce(&dmmoab->lminmax[0], &dmmoab->gminmax[0], 1, MPI_INT, MPI_MIN, ((PetscObject)dm)->comm));
1061     PetscCall(MPIU_Allreduce(&dmmoab->lminmax[1], &dmmoab->gminmax[1], 1, MPI_INT, MPI_MAX, ((PetscObject)dm)->comm));
1062 
1063     /* set the GID map */
1064     for (i = 0; i < totsize; ++i) {
1065       dmmoab->gsindices[i] -= dmmoab->gminmax[0]; /* zero based index needed for IS */
1066 
1067     }
1068     dmmoab->lminmax[0] -= dmmoab->gminmax[0];
1069     dmmoab->lminmax[1] -= dmmoab->gminmax[0];
1070 
1071     PetscInfo(NULL, "GLOBAL_ID: Local [min, max] - [%D, %D], Global [min, max] - [%D, %D]\n", dmmoab->lminmax[0], dmmoab->lminmax[1], dmmoab->gminmax[0], dmmoab->gminmax[1]);
1072   }
1073   PetscCheck(dmmoab->bs == dmmoab->numFields || dmmoab->bs == 1,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mismatch between block size and number of component fields. %D != 1 OR %D != %D.", dmmoab->bs, dmmoab->bs, dmmoab->numFields);
1074 
1075   {
1076     dmmoab->seqstart = dmmoab->mbiface->id_from_handle(dmmoab->vlocal->front());
1077     dmmoab->seqend = dmmoab->mbiface->id_from_handle(dmmoab->vlocal->back());
1078     PetscInfo(NULL, "SEQUENCE: Local [min, max] - [%D, %D]\n", dmmoab->seqstart, dmmoab->seqend);
1079 
1080     PetscCall(PetscMalloc2(dmmoab->seqend - dmmoab->seqstart + 1, &dmmoab->gidmap, dmmoab->seqend - dmmoab->seqstart + 1, &dmmoab->lidmap));
1081     PetscCall(PetscMalloc1(totsize * dmmoab->numFields, &lgmap));
1082 
1083     i = j = 0;
1084     /* set the owned vertex data first */
1085     for (moab::Range::iterator iter = dmmoab->vowned->begin(); iter != dmmoab->vowned->end(); iter++, i++) {
1086       vent = dmmoab->mbiface->id_from_handle(*iter) - dmmoab->seqstart;
1087       dmmoab->gidmap[vent] = dmmoab->gsindices[i];
1088       dmmoab->lidmap[vent] = i;
1089       for (f = 0; f < dmmoab->numFields; f++, j++) {
1090         lgmap[j] = (bs > 1 ? dmmoab->gsindices[i] * dmmoab->numFields + f : totsize * f + dmmoab->gsindices[i]);
1091       }
1092     }
1093     /* next arrange all the ghosted data information */
1094     for (moab::Range::iterator iter = dmmoab->vghost->begin(); iter != dmmoab->vghost->end(); iter++, i++) {
1095       vent = dmmoab->mbiface->id_from_handle(*iter) - dmmoab->seqstart;
1096       dmmoab->gidmap[vent] = dmmoab->gsindices[i];
1097       dmmoab->lidmap[vent] = i;
1098       for (f = 0; f < dmmoab->numFields; f++, j++) {
1099         lgmap[j] = (bs > 1 ? dmmoab->gsindices[i] * dmmoab->numFields + f : totsize * f + dmmoab->gsindices[i]);
1100       }
1101     }
1102 
1103     /* We need to create the Global to Local Vector Scatter Contexts
1104        1) First create a local and global vector
1105        2) Create a local and global IS
1106        3) Create VecScatter and LtoGMapping objects
1107        4) Cleanup the IS and Vec objects
1108     */
1109     PetscCall(DMCreateGlobalVector(dm, &global));
1110     PetscCall(DMCreateLocalVector(dm, &local));
1111 
1112     PetscCall(VecGetOwnershipRange(global, &dmmoab->vstart, &dmmoab->vend));
1113 
1114     /* global to local must retrieve ghost points */
1115     PetscCall(ISCreateStride(((PetscObject)dm)->comm, dmmoab->nloc * dmmoab->numFields, dmmoab->vstart, 1, &from));
1116     PetscCall(ISSetBlockSize(from, bs));
1117 
1118     PetscCall(ISCreateGeneral(((PetscObject)dm)->comm, dmmoab->nloc * dmmoab->numFields, &lgmap[0], PETSC_COPY_VALUES, &to));
1119     PetscCall(ISSetBlockSize(to, bs));
1120 
1121     if (!dmmoab->ltog_map) {
1122       /* create to the local to global mapping for vectors in order to use VecSetValuesLocal */
1123       PetscCall(ISLocalToGlobalMappingCreate(((PetscObject)dm)->comm, dmmoab->bs, totsize * dmmoab->numFields, lgmap,PETSC_COPY_VALUES, &dmmoab->ltog_map));
1124     }
1125 
1126     /* now create the scatter object from local to global vector */
1127     PetscCall(VecScatterCreate(local, from, global, to, &dmmoab->ltog_sendrecv));
1128 
1129     /* clean up IS, Vec */
1130     PetscCall(PetscFree(lgmap));
1131     PetscCall(ISDestroy(&from));
1132     PetscCall(ISDestroy(&to));
1133     PetscCall(VecDestroy(&local));
1134     PetscCall(VecDestroy(&global));
1135   }
1136 
1137   dmmoab->bndyvtx = new moab::Range();
1138   dmmoab->bndyfaces = new moab::Range();
1139   dmmoab->bndyelems = new moab::Range();
1140   /* skin the boundary and store nodes */
1141   if (!dmmoab->hlevel) {
1142     /* get the skin vertices of boundary faces for the current partition and then filter
1143        the local, boundary faces, vertices and elements alone via PSTATUS flags;
1144        this should not give us any ghosted boundary, but if user needs such a functionality
1145        it would be easy to add it based on the find_skin query below */
1146     moab::Skinner skinner(dmmoab->mbiface);
1147 
1148     /* get the entities on the skin - only the faces */
1149     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
1150 
1151 #ifdef MOAB_HAVE_MPI
1152     /* filter all the non-owned and shared entities out of the list */
1153     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->bndyfaces, PSTATUS_NOT_OWNED, PSTATUS_NOT);MBERRNM(merr);
1154     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->bndyfaces, PSTATUS_INTERFACE, PSTATUS_NOT);MBERRNM(merr);
1155 #endif
1156 
1157     /* get all the nodes via connectivity and the parent elements via adjacency information */
1158     merr = dmmoab->mbiface->get_connectivity(*dmmoab->bndyfaces, *dmmoab->bndyvtx, false);MBERRNM(merr);
1159     merr = dmmoab->mbiface->get_adjacencies(*dmmoab->bndyvtx, dmmoab->dim, false, *dmmoab->bndyelems, moab::Interface::UNION);MBERRNM(merr);
1160   }
1161   else {
1162     /* Let us query the hierarchy manager and get the results directly for this level */
1163     for (moab::Range::iterator iter = dmmoab->elocal->begin(); iter != dmmoab->elocal->end(); iter++) {
1164       moab::EntityHandle elemHandle = *iter;
1165       if (dmmoab->hierarchy->is_entity_on_boundary(elemHandle)) {
1166         dmmoab->bndyelems->insert(elemHandle);
1167         /* For this boundary element, query the vertices and add them to the list */
1168         std::vector<moab::EntityHandle> connect;
1169         merr = dmmoab->hierarchy->get_connectivity(elemHandle, dmmoab->hlevel, connect);MBERRNM(merr);
1170         for (unsigned iv=0; iv < connect.size(); ++iv)
1171           if (dmmoab->hierarchy->is_entity_on_boundary(connect[iv]))
1172             dmmoab->bndyvtx->insert(connect[iv]);
1173         /* Next, let us query the boundary faces and add them also to the list */
1174         std::vector<moab::EntityHandle> faces;
1175         merr = dmmoab->hierarchy->get_adjacencies(elemHandle, dmmoab->dim-1, faces);MBERRNM(merr);
1176         for (unsigned ifa=0; ifa < faces.size(); ++ifa)
1177           if (dmmoab->hierarchy->is_entity_on_boundary(faces[ifa]))
1178             dmmoab->bndyfaces->insert(faces[ifa]);
1179       }
1180     }
1181 #ifdef MOAB_HAVE_MPI
1182     /* filter all the non-owned and shared entities out of the list */
1183     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->bndyvtx,   PSTATUS_NOT_OWNED, PSTATUS_NOT); MBERRNM(merr);
1184     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->bndyfaces, PSTATUS_NOT_OWNED, PSTATUS_NOT); MBERRNM(merr);
1185     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->bndyelems, PSTATUS_NOT_OWNED, PSTATUS_NOT); MBERRNM(merr);
1186 #endif
1187 
1188   }
1189   PetscInfo(NULL, "Found %D boundary vertices, %D boundary faces and %D boundary elements.\n", dmmoab->bndyvtx->size(), dmmoab->bndyfaces->size(), dmmoab->bndyelems->size());
1190 
1191   /* Get the material sets and populate the data for all locally owned elements */
1192   {
1193     PetscCall(PetscCalloc1(dmmoab->elocal->size(), &dmmoab->materials));
1194     /* Get the count of entities of particular type from dmmoab->elocal
1195        -- Then, for each non-zero type, loop through and query the fileset to get the material tag data */
1196     moab::Range msets;
1197     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);
1198     if (msets.size() == 0) {
1199       PetscInfo(NULL, "No material sets found in the fileset.");
1200     }
1201 
1202     for (unsigned i=0; i < msets.size(); ++i) {
1203       moab::Range msetelems;
1204       merr = dmmoab->mbiface->get_entities_by_dimension(msets[i], dmmoab->dim, msetelems, true);MB_CHK_ERR(merr);
1205 #ifdef MOAB_HAVE_MPI
1206       /* filter all the non-owned and shared entities out of the list */
1207       merr = dmmoab->pcomm->filter_pstatus(msetelems, PSTATUS_NOT_OWNED, PSTATUS_NOT); MBERRNM(merr);
1208 #endif
1209 
1210       int partID;
1211       moab::EntityHandle mset=msets[i];
1212       merr = dmmoab->mbiface->tag_get_data(dmmoab->material_tag, &mset, 1, &partID);MB_CHK_ERR(merr);
1213 
1214       for (unsigned j=0; j < msetelems.size(); ++j)
1215         dmmoab->materials[dmmoab->elocal->index(msetelems[j])]=partID;
1216     }
1217   }
1218 
1219   PetscFunctionReturn(0);
1220 }
1221 
1222 /*@C
1223   DMMoabCreateVertices - Creates and adds several vertices to the primary set represented by the DM.
1224 
1225   Collective
1226 
1227   Input Parameters:
1228 + dm - The DM object
1229 . type - The type of element to create and add (Edge/Tri/Quad/Tet/Hex/Prism/Pyramid/Polygon/Polyhedra)
1230 . conn - The connectivity of the element
1231 - nverts - The number of vertices that form the element
1232 
1233   Output Parameter:
1234 . overts  - The list of vertices that were created (can be NULL)
1235 
1236   Level: beginner
1237 
1238 .seealso: DMMoabCreateSubmesh(), DMMoabCreateElement()
1239 @*/
1240 PetscErrorCode DMMoabCreateVertices(DM dm, const PetscReal* coords, PetscInt nverts, moab::Range* overts)
1241 {
1242   moab::ErrorCode     merr;
1243   DM_Moab            *dmmoab;
1244   moab::Range         verts;
1245 
1246   PetscFunctionBegin;
1247   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1248   PetscValidPointer(coords, 2);
1249 
1250   dmmoab = (DM_Moab*) dm->data;
1251 
1252   /* Insert new points */
1253   merr = dmmoab->mbiface->create_vertices(&coords[0], nverts, verts); MBERRNM(merr);
1254   merr = dmmoab->mbiface->add_entities(dmmoab->fileset, verts); MBERRNM(merr);
1255 
1256   if (overts) *overts = verts;
1257   PetscFunctionReturn(0);
1258 }
1259 
1260 /*@C
1261   DMMoabCreateElement - Adds an element of specified type to the primary set represented by the DM.
1262 
1263   Collective
1264 
1265   Input Parameters:
1266 + dm - The DM object
1267 . type - The type of element to create and add (Edge/Tri/Quad/Tet/Hex/Prism/Pyramid/Polygon/Polyhedra)
1268 . conn - The connectivity of the element
1269 - nverts - The number of vertices that form the element
1270 
1271   Output Parameter:
1272 . oelem  - The handle to the element created and added to the DM object
1273 
1274   Level: beginner
1275 
1276 .seealso: DMMoabCreateSubmesh(), DMMoabCreateVertices()
1277 @*/
1278 PetscErrorCode DMMoabCreateElement(DM dm, const moab::EntityType type, const moab::EntityHandle* conn, PetscInt nverts, moab::EntityHandle* oelem)
1279 {
1280   moab::ErrorCode     merr;
1281   DM_Moab            *dmmoab;
1282   moab::EntityHandle  elem;
1283 
1284   PetscFunctionBegin;
1285   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1286   PetscValidPointer(conn, 3);
1287 
1288   dmmoab = (DM_Moab*) dm->data;
1289 
1290   /* Insert new element */
1291   merr = dmmoab->mbiface->create_element(type, conn, nverts, elem); MBERRNM(merr);
1292   merr = dmmoab->mbiface->add_entities(dmmoab->fileset, &elem, 1); MBERRNM(merr);
1293 
1294   if (oelem) *oelem = elem;
1295   PetscFunctionReturn(0);
1296 }
1297 
1298 /*@C
1299   DMMoabCreateSubmesh - Creates a sub-DM object with a set that contains all vertices/elements of the parent
1300   in addition to providing support for dynamic mesh modifications. This is useful for AMR calculations to
1301   create a DM object on a refined level.
1302 
1303   Collective
1304 
1305   Input Parameters:
1306 . dm - The DM object
1307 
1308   Output Parameter:
1309 . newdm  - The sub DM object with updated set information
1310 
1311   Level: advanced
1312 
1313 .seealso: DMCreate(), DMMoabCreateVertices(), DMMoabCreateElement()
1314 @*/
1315 PetscErrorCode DMMoabCreateSubmesh(DM dm, DM *newdm)
1316 {
1317   DM_Moab            *dmmoab;
1318   DM_Moab            *ndmmoab;
1319   moab::ErrorCode    merr;
1320 
1321   PetscFunctionBegin;
1322   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1323 
1324   dmmoab = (DM_Moab*) dm->data;
1325 
1326   /* Create the basic DMMoab object and keep the default parameters created by DM impls */
1327   PetscCall(DMMoabCreateMoab(((PetscObject)dm)->comm, dmmoab->mbiface, &dmmoab->ltog_tag, PETSC_NULL, newdm));
1328 
1329   /* get all the necessary handles from the private DM object */
1330   ndmmoab = (DM_Moab*) (*newdm)->data;
1331 
1332   /* set the sub-mesh's parent DM reference */
1333   ndmmoab->parent = &dm;
1334 
1335   /* create a file set to associate all entities in current mesh */
1336   merr = ndmmoab->mbiface->create_meshset(moab::MESHSET_SET, ndmmoab->fileset); MBERR("Creating file set failed", merr);
1337 
1338   /* create a meshset and then add old fileset as child */
1339   merr = ndmmoab->mbiface->add_entities(ndmmoab->fileset, *dmmoab->vlocal); MBERR("Adding child vertices to parent failed", merr);
1340   merr = ndmmoab->mbiface->add_entities(ndmmoab->fileset, *dmmoab->elocal); MBERR("Adding child elements to parent failed", merr);
1341 
1342   /* preserve the field association between the parent and sub-mesh objects */
1343   PetscCall(DMMoabSetFieldNames(*newdm, dmmoab->numFields, dmmoab->fieldNames));
1344   PetscFunctionReturn(0);
1345 }
1346 
1347 PETSC_EXTERN PetscErrorCode DMMoabView_Ascii(DM dm, PetscViewer viewer)
1348 {
1349   DM_Moab          *dmmoab = (DM_Moab*)(dm)->data;
1350   const char       *name;
1351   MPI_Comm          comm;
1352   PetscMPIInt       size;
1353 
1354   PetscFunctionBegin;
1355   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
1356   PetscCallMPI(MPI_Comm_size(comm, &size));
1357   PetscCall(PetscObjectGetName((PetscObject) dm, &name));
1358   PetscCall(PetscViewerASCIIPushTab(viewer));
1359   if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %D dimensions:\n", name, dmmoab->dim));
1360   else      PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dmmoab->dim));
1361   /* print details about the global mesh */
1362   {
1363     PetscCall(PetscViewerASCIIPushTab(viewer));
1364     PetscCall(PetscViewerASCIIPrintf(viewer, "Sizes: cells=%D, vertices=%D, blocks=%D\n", dmmoab->nele, dmmoab->n, dmmoab->bs));
1365     /* print boundary data */
1366     PetscCall(PetscViewerASCIIPrintf(viewer, "Boundary trace:\n", dmmoab->bndyelems->size(), dmmoab->bndyfaces->size(), dmmoab->bndyvtx->size()));
1367     {
1368       PetscCall(PetscViewerASCIIPushTab(viewer));
1369       PetscCall(PetscViewerASCIIPrintf(viewer, "cells=%D, faces=%D, vertices=%D\n", dmmoab->bndyelems->size(), dmmoab->bndyfaces->size(), dmmoab->bndyvtx->size()));
1370       PetscCall(PetscViewerASCIIPopTab(viewer));
1371     }
1372     /* print field data */
1373     PetscCall(PetscViewerASCIIPrintf(viewer, "Fields: %D components\n", dmmoab->numFields));
1374     {
1375       PetscCall(PetscViewerASCIIPushTab(viewer));
1376       for (int i = 0; i < dmmoab->numFields; ++i) {
1377         PetscCall(PetscViewerASCIIPrintf(viewer, "[%D] - %s\n", i, dmmoab->fieldNames[i]));
1378       }
1379       PetscCall(PetscViewerASCIIPopTab(viewer));
1380     }
1381     PetscCall(PetscViewerASCIIPopTab(viewer));
1382   }
1383   PetscCall(PetscViewerASCIIPopTab(viewer));
1384   PetscCall(PetscViewerFlush(viewer));
1385   PetscFunctionReturn(0);
1386 }
1387 
1388 PETSC_EXTERN PetscErrorCode DMMoabView_VTK(DM dm, PetscViewer v)
1389 {
1390   PetscFunctionReturn(0);
1391 }
1392 
1393 PETSC_EXTERN PetscErrorCode DMMoabView_HDF5(DM dm, PetscViewer v)
1394 {
1395   PetscFunctionReturn(0);
1396 }
1397 
1398 PETSC_EXTERN PetscErrorCode DMView_Moab(DM dm, PetscViewer viewer)
1399 {
1400   PetscBool      iascii, ishdf5, isvtk;
1401 
1402   PetscFunctionBegin;
1403   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1404   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1405   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii));
1406   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,   &isvtk));
1407   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,  &ishdf5));
1408   if (iascii) {
1409     PetscCall(DMMoabView_Ascii(dm, viewer));
1410   } else if (ishdf5) {
1411 #if defined(PETSC_HAVE_HDF5) && defined(MOAB_HAVE_HDF5)
1412     PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_VIZ));
1413     PetscCall(DMMoabView_HDF5(dm, viewer));
1414     PetscCall(PetscViewerPopFormat(viewer));
1415 #else
1416     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1417 #endif
1418   }
1419   else if (isvtk) {
1420     PetscCall(DMMoabView_VTK(dm, viewer));
1421   }
1422   PetscFunctionReturn(0);
1423 }
1424 
1425 PETSC_EXTERN PetscErrorCode DMInitialize_Moab(DM dm)
1426 {
1427   PetscFunctionBegin;
1428   dm->ops->view                            = DMView_Moab;
1429   dm->ops->load                            = NULL /* DMLoad_Moab */;
1430   dm->ops->setfromoptions                  = DMSetFromOptions_Moab;
1431   dm->ops->clone                           = DMClone_Moab;
1432   dm->ops->setup                           = DMSetUp_Moab;
1433   dm->ops->createlocalsection            = NULL;
1434   dm->ops->createdefaultconstraints        = NULL;
1435   dm->ops->createglobalvector              = DMCreateGlobalVector_Moab;
1436   dm->ops->createlocalvector               = DMCreateLocalVector_Moab;
1437   dm->ops->getlocaltoglobalmapping         = NULL;
1438   dm->ops->createfieldis                   = NULL;
1439   dm->ops->createcoordinatedm              = NULL /* DMCreateCoordinateDM_Moab */;
1440   dm->ops->getcoloring                     = NULL;
1441   dm->ops->creatematrix                    = DMCreateMatrix_Moab;
1442   dm->ops->createinterpolation             = DMCreateInterpolation_Moab;
1443   dm->ops->createinjection                 = NULL /* DMCreateInjection_Moab */;
1444   dm->ops->refine                          = DMRefine_Moab;
1445   dm->ops->coarsen                         = DMCoarsen_Moab;
1446   dm->ops->refinehierarchy                 = DMRefineHierarchy_Moab;
1447   dm->ops->coarsenhierarchy                = DMCoarsenHierarchy_Moab;
1448   dm->ops->globaltolocalbegin              = DMGlobalToLocalBegin_Moab;
1449   dm->ops->globaltolocalend                = DMGlobalToLocalEnd_Moab;
1450   dm->ops->localtoglobalbegin              = DMLocalToGlobalBegin_Moab;
1451   dm->ops->localtoglobalend                = DMLocalToGlobalEnd_Moab;
1452   dm->ops->destroy                         = DMDestroy_Moab;
1453   dm->ops->createsubdm                     = NULL /* DMCreateSubDM_Moab */;
1454   dm->ops->getdimpoints                    = NULL /* DMGetDimPoints_Moab */;
1455   dm->ops->locatepoints                    = NULL /* DMLocatePoints_Moab */;
1456   PetscFunctionReturn(0);
1457 }
1458 
1459 PETSC_EXTERN PetscErrorCode DMClone_Moab(DM dm, DM *newdm)
1460 {
1461   PetscFunctionBegin;
1462   /* get all the necessary handles from the private DM object */
1463   (*newdm)->data = (DM_Moab*) dm->data;
1464   ((DM_Moab*)dm->data)->refct++;
1465 
1466   PetscCall(PetscObjectChangeTypeName((PetscObject) *newdm, DMMOAB));
1467   PetscCall(DMInitialize_Moab(*newdm));
1468   PetscFunctionReturn(0);
1469 }
1470 
1471 PETSC_EXTERN PetscErrorCode DMCreate_Moab(DM dm)
1472 {
1473   PetscFunctionBegin;
1474   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1475   PetscCall(PetscNewLog(dm, (DM_Moab**)&dm->data));
1476 
1477   ((DM_Moab*)dm->data)->bs = 1;
1478   ((DM_Moab*)dm->data)->numFields = 1;
1479   ((DM_Moab*)dm->data)->n = 0;
1480   ((DM_Moab*)dm->data)->nloc = 0;
1481   ((DM_Moab*)dm->data)->nghost = 0;
1482   ((DM_Moab*)dm->data)->nele = 0;
1483   ((DM_Moab*)dm->data)->neleloc = 0;
1484   ((DM_Moab*)dm->data)->neleghost = 0;
1485   ((DM_Moab*)dm->data)->ltog_map = NULL;
1486   ((DM_Moab*)dm->data)->ltog_sendrecv = NULL;
1487 
1488   ((DM_Moab*)dm->data)->refct = 1;
1489   ((DM_Moab*)dm->data)->parent = NULL;
1490   ((DM_Moab*)dm->data)->vlocal = new moab::Range();
1491   ((DM_Moab*)dm->data)->vowned = new moab::Range();
1492   ((DM_Moab*)dm->data)->vghost = new moab::Range();
1493   ((DM_Moab*)dm->data)->elocal = new moab::Range();
1494   ((DM_Moab*)dm->data)->eghost = new moab::Range();
1495 
1496   PetscCall(DMInitialize_Moab(dm));
1497   PetscFunctionReturn(0);
1498 }
1499