xref: /petsc/src/dm/impls/moab/dmmoab.cxx (revision 64e1c140f280b9f14e7e1bfe948bce0ef936fcec)
1 #include <petsc/private/dmmbimpl.h> /*I  "petscdmmoab.h"   I*/
2 
3 #include <petscdmmoab.h>
4 #include <MBTagConventions.hpp>
5 #include <moab/Skinner.hpp>
6 
7 
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: http://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 
25 /*@
26   DMMoabCreate - Creates a DMMoab object, which encapsulates a moab instance
27 
28   Collective on MPI_Comm
29 
30   Input Parameter:
31 . comm - The communicator for the DMMoab object
32 
33   Output Parameter:
34 . dmb  - The DMMoab object
35 
36   Level: beginner
37 
38 .keywords: DMMoab, create
39 @*/
40 PetscErrorCode DMMoabCreate(MPI_Comm comm, DM *dmb)
41 {
42   PetscErrorCode ierr;
43 
44   PetscFunctionBegin;
45   PetscValidPointer(dmb,2);
46   ierr = DMCreate(comm, dmb);CHKERRQ(ierr);
47   ierr = DMSetType(*dmb, DMMOAB);CHKERRQ(ierr);
48   PetscFunctionReturn(0);
49 }
50 
51 /*@
52   DMMoabCreateMoab - Creates a DMMoab object, optionally from an instance and other data
53 
54   Collective on MPI_Comm
55 
56   Input Parameter:
57 . comm - The communicator for the DMMoab object
58 . mbiface - (ptr to) the MOAB Instance; if passed in NULL, MOAB instance is created inside PETSc, and destroyed
59          along with the DMMoab
60 . pcomm - (ptr to) a ParallelComm; if NULL, creates one internally for the whole communicator
61 . ltog_tag - A tag to use to retrieve global id for an entity; if 0, will use GLOBAL_ID_TAG_NAME/tag
62 . range - If non-NULL, contains range of entities to which DOFs will be assigned
63 
64   Output Parameter:
65 . dmb  - The DMMoab object
66 
67   Level: intermediate
68 
69 .keywords: DMMoab, create
70 @*/
71 PetscErrorCode DMMoabCreateMoab(MPI_Comm comm, moab::Interface *mbiface, moab::ParallelComm *pcomm, moab::Tag *ltog_tag, moab::Range *range, DM *dmb)
72 {
73   PetscErrorCode ierr;
74   moab::ErrorCode merr;
75   moab::EntityHandle partnset;
76   PetscInt rank, nprocs;
77   DM             dmmb;
78   DM_Moab        *dmmoab;
79 
80   PetscFunctionBegin;
81   PetscValidPointer(dmb,6);
82 
83   ierr = DMMoabCreate(comm, &dmmb);CHKERRQ(ierr);
84   dmmoab = (DM_Moab*)(dmmb)->data;
85 
86   if (!mbiface) {
87     dmmoab->mbiface = new moab::Core();
88     dmmoab->icreatedinstance = PETSC_TRUE;
89   }
90   else {
91     dmmoab->mbiface = mbiface;
92     dmmoab->icreatedinstance = PETSC_FALSE;
93   }
94 
95   /* by default the fileset = root set. This set stores the hierarchy of entities belonging to current DM */
96   dmmoab->fileset=0;
97   dmmoab->hlevel=0;
98   dmmoab->nghostrings=0;
99 
100   if (!pcomm) {
101     ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
102     ierr = MPI_Comm_size(comm, &nprocs);CHKERRQ(ierr);
103 
104     /* Create root sets for each mesh.  Then pass these
105        to the load_file functions to be populated. */
106     merr = dmmoab->mbiface->create_meshset(moab::MESHSET_SET, partnset);MBERR("Creating partition set failed", merr);
107 
108     /* Create the parallel communicator object with the partition handle associated with MOAB */
109     dmmoab->pcomm = moab::ParallelComm::get_pcomm(dmmoab->mbiface, partnset, &comm);
110   }
111   else {
112     ierr = DMMoabSetParallelComm(dmmb, pcomm);CHKERRQ(ierr);
113   }
114 
115   /* do the remaining initializations for DMMoab */
116   dmmoab->bs = 1;
117   dmmoab->numFields = 1;
118   ierr = PetscMalloc(dmmoab->numFields*sizeof(char*),&dmmoab->fieldNames);CHKERRQ(ierr);
119   ierr = PetscStrallocpy("DEFAULT", (char**) &dmmoab->fieldNames[0]);CHKERRQ(ierr);
120   dmmoab->rw_dbglevel = 0;
121   dmmoab->partition_by_rank = PETSC_FALSE;
122   dmmoab->extra_read_options[0] = '\0';
123   dmmoab->extra_write_options[0] = '\0';
124   dmmoab->read_mode = READ_PART;
125   dmmoab->write_mode = WRITE_PART;
126 
127   /* set global ID tag handle */
128   if (ltog_tag && *ltog_tag) {
129     ierr = DMMoabSetLocalToGlobalTag(dmmb, *ltog_tag);CHKERRQ(ierr);
130   }
131   else {
132     merr = dmmoab->mbiface->tag_get_handle(GLOBAL_ID_TAG_NAME, dmmoab->ltog_tag);MBERRNM(merr);
133     if (ltog_tag) *ltog_tag = dmmoab->ltog_tag;
134   }
135 
136   merr = dmmoab->mbiface->tag_get_handle(MATERIAL_SET_TAG_NAME, dmmoab->material_tag);MBERRNM(merr);
137 
138   /* set the local range of entities (vertices) of interest */
139   if (range) {
140     ierr = DMMoabSetLocalVertices(dmmb, range);CHKERRQ(ierr);
141   }
142   *dmb=dmmb;
143   PetscFunctionReturn(0);
144 }
145 
146 /*@
147   DMMoabSetParallelComm - Set the ParallelComm used with this DMMoab
148 
149   Collective on MPI_Comm
150 
151   Input Parameter:
152 . dm    - The DMMoab object being set
153 . pcomm - The ParallelComm being set on the DMMoab
154 
155   Level: beginner
156 
157 .keywords: DMMoab, create
158 @*/
159 PetscErrorCode DMMoabSetParallelComm(DM dm,moab::ParallelComm *pcomm)
160 {
161   DM_Moab        *dmmoab = (DM_Moab*)(dm)->data;
162 
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
165   PetscValidPointer(pcomm,2);
166   dmmoab->pcomm = pcomm;
167   dmmoab->mbiface = pcomm->get_moab();
168   dmmoab->icreatedinstance = PETSC_FALSE;
169   PetscFunctionReturn(0);
170 }
171 
172 
173 /*@
174   DMMoabGetParallelComm - Get the ParallelComm used with this DMMoab
175 
176   Collective on MPI_Comm
177 
178   Input Parameter:
179 . dm    - The DMMoab object being set
180 
181   Output Parameter:
182 . pcomm - The ParallelComm for the DMMoab
183 
184   Level: beginner
185 
186 .keywords: DMMoab, create
187 @*/
188 PetscErrorCode DMMoabGetParallelComm(DM dm,moab::ParallelComm **pcomm)
189 {
190   PetscFunctionBegin;
191   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
192   *pcomm = ((DM_Moab*)(dm)->data)->pcomm;
193   PetscFunctionReturn(0);
194 }
195 
196 
197 /*@
198   DMMoabSetInterface - Set the MOAB instance used with this DMMoab
199 
200   Collective on MPI_Comm
201 
202   Input Parameter:
203 . dm      - The DMMoab object being set
204 . mbiface - The MOAB instance being set on this DMMoab
205 
206   Level: beginner
207 
208 .keywords: DMMoab, create
209 @*/
210 PetscErrorCode DMMoabSetInterface(DM dm,moab::Interface *mbiface)
211 {
212   DM_Moab        *dmmoab = (DM_Moab*)(dm)->data;
213 
214   PetscFunctionBegin;
215   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
216   PetscValidPointer(mbiface,2);
217   dmmoab->pcomm = NULL;
218   dmmoab->mbiface = mbiface;
219   dmmoab->icreatedinstance = PETSC_FALSE;
220   PetscFunctionReturn(0);
221 }
222 
223 
224 /*@
225   DMMoabGetInterface - Get the MOAB instance used with this DMMoab
226 
227   Collective on MPI_Comm
228 
229   Input Parameter:
230 . dm      - The DMMoab object being set
231 
232   Output Parameter:
233 . mbiface - The MOAB instance set on this DMMoab
234 
235   Level: beginner
236 
237 .keywords: DMMoab, create
238 @*/
239 PetscErrorCode DMMoabGetInterface(DM dm,moab::Interface **mbiface)
240 {
241   PetscErrorCode   ierr;
242   static PetscBool cite = PETSC_FALSE;
243 
244   PetscFunctionBegin;
245   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
246   ierr = PetscCitationsRegister("@techreport{tautges_moab:_2004,\n  type = {{SAND2004-1592}},\n  title = {{MOAB:} A Mesh-Oriented Database},  institution = {Sandia National Laboratories},\n  author = {Tautges, T. J. and Meyers, R. and Merkley, K. and Stimpson, C. and Ernst, C.},\n  year = {2004},  note = {Report}\n}\n",&cite);CHKERRQ(ierr);
247   *mbiface = ((DM_Moab*)dm->data)->mbiface;
248   PetscFunctionReturn(0);
249 }
250 
251 
252 /*@
253   DMMoabSetLocalVertices - Set the entities having DOFs on this DMMoab
254 
255   Collective on MPI_Comm
256 
257   Input Parameter:
258 . dm    - The DMMoab object being set
259 . range - The entities treated by this DMMoab
260 
261   Level: beginner
262 
263 .keywords: DMMoab, create
264 @*/
265 PetscErrorCode DMMoabSetLocalVertices(DM dm,moab::Range *range)
266 {
267   moab::ErrorCode merr;
268   PetscErrorCode  ierr;
269   moab::Range     tmpvtxs;
270   DM_Moab        *dmmoab = (DM_Moab*)(dm)->data;
271 
272   PetscFunctionBegin;
273   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
274   dmmoab->vlocal->clear();
275   dmmoab->vowned->clear();
276 
277   dmmoab->vlocal->insert(range->begin(), range->end());
278 
279   /* filter based on parallel status */
280   merr = dmmoab->pcomm->filter_pstatus(*dmmoab->vlocal,PSTATUS_NOT_OWNED,PSTATUS_NOT,-1,dmmoab->vowned);MBERRNM(merr);
281 
282   /* filter all the non-owned and shared entities out of the list */
283   tmpvtxs = moab::subtract(*dmmoab->vlocal, *dmmoab->vowned);
284   merr = dmmoab->pcomm->filter_pstatus(tmpvtxs,PSTATUS_INTERFACE,PSTATUS_OR,-1,dmmoab->vghost);MBERRNM(merr);
285   tmpvtxs = moab::subtract(tmpvtxs, *dmmoab->vghost);
286   *dmmoab->vlocal = moab::subtract(*dmmoab->vlocal, tmpvtxs);
287 
288   /* compute and cache the sizes of local and ghosted entities */
289   dmmoab->nloc = dmmoab->vowned->size();
290   dmmoab->nghost = dmmoab->vghost->size();
291   ierr = MPIU_Allreduce(&dmmoab->nloc, &dmmoab->n, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr);
292   PetscFunctionReturn(0);
293 }
294 
295 
296 /*@
297   DMMoabGetAllVertices - Get the entities having DOFs on this DMMoab
298 
299   Collective on MPI_Comm
300 
301   Input Parameter:
302 . dm    - The DMMoab object being set
303 
304   Output Parameter:
305 . owned - The local vertex entities in this DMMoab = (owned+ghosted)
306 
307   Level: beginner
308 
309 .keywords: DMMoab, create
310 @*/
311 PetscErrorCode DMMoabGetAllVertices(DM dm,moab::Range *local)
312 {
313   PetscFunctionBegin;
314   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
315   if (local) *local = *((DM_Moab*)dm->data)->vlocal;
316   PetscFunctionReturn(0);
317 }
318 
319 
320 
321 /*@
322   DMMoabGetLocalVertices - Get the entities having DOFs on this DMMoab
323 
324   Collective on MPI_Comm
325 
326   Input Parameter:
327 . dm    - The DMMoab object being set
328 
329   Output Parameter:
330 . owned - The owned vertex entities in this DMMoab
331 . ghost - The ghosted entities (non-owned) stored locally in this partition
332 
333   Level: beginner
334 
335 .keywords: DMMoab, create
336 @*/
337 PetscErrorCode DMMoabGetLocalVertices(DM dm,const moab::Range **owned,const moab::Range **ghost)
338 {
339   PetscFunctionBegin;
340   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
341   if (owned) *owned = ((DM_Moab*)dm->data)->vowned;
342   if (ghost) *ghost = ((DM_Moab*)dm->data)->vghost;
343   PetscFunctionReturn(0);
344 }
345 
346 /*@
347   DMMoabGetLocalElements - Get the higher-dimensional entities that are locally owned
348 
349   Collective on MPI_Comm
350 
351   Input Parameter:
352 . dm    - The DMMoab object being set
353 
354   Output Parameter:
355 . range - The entities owned locally
356 
357   Level: beginner
358 
359 .keywords: DMMoab, create
360 @*/
361 PetscErrorCode DMMoabGetLocalElements(DM dm,const moab::Range **range)
362 {
363   PetscFunctionBegin;
364   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
365   if (range) *range = ((DM_Moab*)dm->data)->elocal;
366   PetscFunctionReturn(0);
367 }
368 
369 
370 /*@
371   DMMoabSetLocalElements - Set the entities having DOFs on this DMMoab
372 
373   Collective on MPI_Comm
374 
375   Input Parameter:
376 . dm    - The DMMoab object being set
377 . range - The entities treated by this DMMoab
378 
379   Level: beginner
380 
381 .keywords: DMMoab, create
382 @*/
383 PetscErrorCode DMMoabSetLocalElements(DM dm,moab::Range *range)
384 {
385   moab::ErrorCode merr;
386   PetscErrorCode  ierr;
387   DM_Moab        *dmmoab = (DM_Moab*)(dm)->data;
388 
389   PetscFunctionBegin;
390   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
391   dmmoab->elocal->clear();
392   dmmoab->eghost->clear();
393   dmmoab->elocal->insert(range->begin(), range->end());
394   merr = dmmoab->pcomm->filter_pstatus(*dmmoab->elocal,PSTATUS_NOT_OWNED,PSTATUS_NOT);MBERRNM(merr);
395   *dmmoab->eghost = moab::subtract(*range, *dmmoab->elocal);
396   dmmoab->neleloc=dmmoab->elocal->size();
397   dmmoab->neleghost=dmmoab->eghost->size();
398   ierr = MPIU_Allreduce(&dmmoab->nele, &dmmoab->neleloc, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr);
399   PetscInfo2(dm, "Created %D local and %D global elements.\n", dmmoab->neleloc, dmmoab->nele);
400   PetscFunctionReturn(0);
401 }
402 
403 
404 /*@
405   DMMoabSetLocalToGlobalTag - Set the tag used for local to global numbering
406 
407   Collective on MPI_Comm
408 
409   Input Parameter:
410 . dm      - The DMMoab object being set
411 . ltogtag - The MOAB tag used for local to global ids
412 
413   Level: beginner
414 
415 .keywords: DMMoab, create
416 @*/
417 PetscErrorCode DMMoabSetLocalToGlobalTag(DM dm,moab::Tag ltogtag)
418 {
419   PetscFunctionBegin;
420   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
421   ((DM_Moab*)dm->data)->ltog_tag = ltogtag;
422   PetscFunctionReturn(0);
423 }
424 
425 
426 /*@
427   DMMoabGetLocalToGlobalTag - Get the tag used for local to global numbering
428 
429   Collective on MPI_Comm
430 
431   Input Parameter:
432 . dm      - The DMMoab object being set
433 
434   Output Parameter:
435 . ltogtag - The MOAB tag used for local to global ids
436 
437   Level: beginner
438 
439 .keywords: DMMoab, create
440 @*/
441 PetscErrorCode DMMoabGetLocalToGlobalTag(DM dm,moab::Tag *ltog_tag)
442 {
443   PetscFunctionBegin;
444   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
445   *ltog_tag = ((DM_Moab*)dm->data)->ltog_tag;
446   PetscFunctionReturn(0);
447 }
448 
449 
450 /*@
451   DMMoabSetBlockSize - Set the block size used with this DMMoab
452 
453   Collective on MPI_Comm
454 
455   Input Parameter:
456 . dm - The DMMoab object being set
457 . bs - The block size used with this DMMoab
458 
459   Level: beginner
460 
461 .keywords: DMMoab, create
462 @*/
463 PetscErrorCode DMMoabSetBlockSize(DM dm,PetscInt bs)
464 {
465   PetscFunctionBegin;
466   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
467   ((DM_Moab*)dm->data)->bs = bs;
468   PetscFunctionReturn(0);
469 }
470 
471 
472 /*@
473   DMMoabGetBlockSize - Get the block size used with this DMMoab
474 
475   Collective on MPI_Comm
476 
477   Input Parameter:
478 . dm - The DMMoab object being set
479 
480   Output Parameter:
481 . bs - The block size used with this DMMoab
482 
483   Level: beginner
484 
485 .keywords: DMMoab, create
486 @*/
487 PetscErrorCode DMMoabGetBlockSize(DM dm,PetscInt *bs)
488 {
489   PetscFunctionBegin;
490   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
491   *bs = ((DM_Moab*)dm->data)->bs;
492   PetscFunctionReturn(0);
493 }
494 
495 
496 /*@
497   DMMoabGetSize - Get the global vertex size used with this DMMoab
498 
499   Collective on DM
500 
501   Input Parameter:
502 . dm - The DMMoab object being set
503 
504   Output Parameter:
505 . neg - The number of global elements in the DMMoab instance
506 . nvg - The number of global vertices in the DMMoab instance
507 
508   Level: beginner
509 
510 .keywords: DMMoab, create
511 @*/
512 PetscErrorCode DMMoabGetSize(DM dm,PetscInt *neg,PetscInt *nvg)
513 {
514   PetscFunctionBegin;
515   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
516   if(neg) *neg = ((DM_Moab*)dm->data)->nele;
517   if(nvg) *nvg = ((DM_Moab*)dm->data)->n;
518   PetscFunctionReturn(0);
519 }
520 
521 
522 /*@
523   DMMoabGetLocalSize - Get the local and ghosted vertex size used with this DMMoab
524 
525   Collective on DM
526 
527   Input Parameter:
528 . dm - The DMMoab object being set
529 
530   Output Parameter:
531 + nel - The number of owned elements in this processor
532 . neg - The number of ghosted elements in this processor
533 . nvl - The number of owned vertices in this processor
534 . nvg - The number of ghosted vertices in this processor
535 
536   Level: beginner
537 
538 .keywords: DMMoab, create
539 @*/
540 PetscErrorCode DMMoabGetLocalSize(DM dm,PetscInt *nel,PetscInt *neg,PetscInt *nvl,PetscInt *nvg)
541 {
542   PetscFunctionBegin;
543   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
544   if(nel) *nel = ((DM_Moab*)dm->data)->neleloc;
545   if(neg) *neg = ((DM_Moab*)dm->data)->neleghost;
546   if(nvl) *nvl = ((DM_Moab*)dm->data)->nloc;
547   if(nvg) *nvg = ((DM_Moab*)dm->data)->nghost;
548   PetscFunctionReturn(0);
549 }
550 
551 
552 /*@
553   DMMoabGetOffset - Get the local offset for the global vector
554 
555   Collective on MPI_Comm
556 
557   Input Parameter:
558 . dm - The DMMoab object being set
559 
560   Output Parameter:
561 . offset - The local offset for the global vector
562 
563   Level: beginner
564 
565 .keywords: DMMoab, create
566 @*/
567 PetscErrorCode DMMoabGetOffset(DM dm,PetscInt *offset)
568 {
569   PetscFunctionBegin;
570   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
571   *offset = ((DM_Moab*)dm->data)->vstart;
572   PetscFunctionReturn(0);
573 }
574 
575 
576 /*@
577   DMMoabGetDimension - Get the dimension of the DM Mesh
578 
579   Collective on MPI_Comm
580 
581   Input Parameter:
582 . dm - The DMMoab object
583 
584   Output Parameter:
585 . dim - The dimension of DM
586 
587   Level: beginner
588 
589 .keywords: DMMoab, create
590 @*/
591 PetscErrorCode DMMoabGetDimension(DM dm,PetscInt *dim)
592 {
593   PetscFunctionBegin;
594   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
595   *dim = ((DM_Moab*)dm->data)->dim;
596   PetscFunctionReturn(0);
597 }
598 
599 
600 /*@
601   DMMoabGetMaterialBlock - Get the material ID corresponding to the current entity of the DM Mesh
602 
603   Collective on MPI_Comm
604 
605   Input Parameter:
606 . dm - The DMMoab object
607 . ehandle - The element entity handle
608 
609   Output Parameter:
610 . mat - The material ID for the current entity
611 
612   Level: beginner
613 
614 .keywords: DMMoab, create
615 @*/
616 PetscErrorCode DMMoabGetMaterialBlock(DM dm,const moab::EntityHandle ehandle, PetscInt *mat)
617 {
618   DM_Moab         *dmmoab;
619   moab::ErrorCode merr;
620 
621   PetscFunctionBegin;
622   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
623   if (*mat) {
624     dmmoab = (DM_Moab*)(dm)->data;
625     merr=dmmoab->mbiface->tag_get_data(dmmoab->material_tag, &ehandle, 1, mat);MBERRNM(merr);
626   }
627   PetscFunctionReturn(0);
628 }
629 
630 
631 /*@
632   DMMoabGetVertexCoordinates - Get the coordinates corresponding to the requested vertex entities
633 
634   Collective on MPI_Comm
635 
636   Input Parameter:
637 . dm - The DMMoab object
638 . nconn - Number of entities whose coordinates are needed
639 . conn - The vertex entity handles
640 
641   Output Parameter:
642 . vpos - The coordinates of the requested vertex entities
643 
644   Level: beginner
645 
646 .seealso: DMMoabGetVertexConnectivity()
647 @*/
648 PetscErrorCode DMMoabGetVertexCoordinates(DM dm,PetscInt nconn,const moab::EntityHandle *conn,PetscReal *vpos)
649 {
650   DM_Moab         *dmmoab;
651   PetscErrorCode  ierr;
652   moab::ErrorCode merr;
653 
654   PetscFunctionBegin;
655   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
656   PetscValidPointer(conn,3);
657   dmmoab = (DM_Moab*)(dm)->data;
658 
659   if (!vpos) {
660     ierr = PetscMalloc1(nconn*3, &vpos);CHKERRQ(ierr);
661   }
662 
663   /* Get connectivity information in MOAB canonical ordering */
664   merr = dmmoab->mbiface->get_coords(conn, nconn, vpos);MBERRNM(merr);
665   PetscFunctionReturn(0);
666 }
667 
668 
669 /*@
670   DMMoabGetVertexConnectivity - Get the vertex adjacency for the given entity
671 
672   Collective on MPI_Comm
673 
674   Input Parameter:
675 . dm - The DMMoab object
676 . vhandle - Vertex entity handle
677 
678   Output Parameter:
679 . nconn - Number of entities whose coordinates are needed
680 . conn - The vertex entity handles
681 
682   Level: beginner
683 
684 .seealso: DMMoabGetVertexCoordinates(), DMMoabRestoreVertexConnectivity()
685 @*/
686 PetscErrorCode DMMoabGetVertexConnectivity(DM dm,moab::EntityHandle vhandle,PetscInt* nconn, moab::EntityHandle **conn)
687 {
688   DM_Moab        *dmmoab;
689   std::vector<moab::EntityHandle> adj_entities,connect;
690   PetscErrorCode  ierr;
691   moab::ErrorCode merr;
692 
693   PetscFunctionBegin;
694   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
695   PetscValidPointer(conn,4);
696   dmmoab = (DM_Moab*)(dm)->data;
697 
698   /* Get connectivity information in MOAB canonical ordering */
699   merr = dmmoab->mbiface->get_adjacencies(&vhandle, 1, 1, true, adj_entities, moab::Interface::UNION);MBERRNM(merr);
700   merr = dmmoab->mbiface->get_connectivity(&adj_entities[0],adj_entities.size(),connect);MBERRNM(merr);
701 
702   if (conn) {
703     ierr = PetscMalloc(sizeof(moab::EntityHandle)*connect.size(), conn);CHKERRQ(ierr);
704     ierr = PetscMemcpy(*conn, &connect[0], sizeof(moab::EntityHandle)*connect.size());CHKERRQ(ierr);
705   }
706   if (nconn) *nconn=connect.size();
707   PetscFunctionReturn(0);
708 }
709 
710 
711 /*@
712   DMMoabRestoreVertexConnectivity - Restore the vertex connectivity for the given entity
713 
714   Collective on MPI_Comm
715 
716   Input Parameter:
717 . dm - The DMMoab object
718 . vhandle - Vertex entity handle
719 . nconn - Number of entities whose coordinates are needed
720 . conn - The vertex entity handles
721 
722   Level: beginner
723 
724 .seealso: DMMoabGetVertexCoordinates(), DMMoabGetVertexConnectivity()
725 @*/
726 PetscErrorCode DMMoabRestoreVertexConnectivity(DM dm,moab::EntityHandle ehandle,PetscInt* nconn, moab::EntityHandle **conn)
727 {
728   PetscErrorCode  ierr;
729 
730   PetscFunctionBegin;
731   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
732   PetscValidPointer(conn,4);
733 
734   if (conn) {
735     ierr = PetscFree(*conn);CHKERRQ(ierr);
736   }
737   if (nconn) *nconn=0;
738   PetscFunctionReturn(0);
739 }
740 
741 
742 /*@
743   DMMoabGetElementConnectivity - Get the vertex adjacency for the given entity
744 
745   Collective on MPI_Comm
746 
747   Input Parameter:
748 . dm - The DMMoab object
749 . ehandle - Vertex entity handle
750 
751   Output Parameter:
752 . nconn - Number of entities whose coordinates are needed
753 . conn - The vertex entity handles
754 
755   Level: beginner
756 
757 .seealso: DMMoabGetVertexCoordinates(), DMMoabGetVertexConnectivity(), DMMoabRestoreVertexConnectivity()
758 @*/
759 PetscErrorCode DMMoabGetElementConnectivity(DM dm,moab::EntityHandle ehandle,PetscInt* nconn,const moab::EntityHandle **conn)
760 {
761   DM_Moab        *dmmoab;
762   const moab::EntityHandle *connect;
763   moab::ErrorCode merr;
764   PetscInt nnodes;
765 
766   PetscFunctionBegin;
767   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
768   PetscValidPointer(conn,4);
769   dmmoab = (DM_Moab*)(dm)->data;
770 
771   /* Get connectivity information in MOAB canonical ordering */
772   merr = dmmoab->mbiface->get_connectivity(ehandle, connect, nnodes);MBERRNM(merr);
773   if (conn) *conn=connect;
774   if (nconn) *nconn=nnodes;
775   PetscFunctionReturn(0);
776 }
777 
778 
779 /*@
780   DMMoabIsEntityOnBoundary - Check whether a given entity is on the boundary (vertex, edge, face, element)
781 
782   Collective on MPI_Comm
783 
784   Input Parameter:
785 . dm - The DMMoab object
786 . ent - Entity handle
787 
788   Output Parameter:
789 . ent_on_boundary - PETSC_TRUE if entity on boundary; PETSC_FALSE otherwise
790 
791   Level: beginner
792 
793 .seealso: DMMoabCheckBoundaryVertices()
794 @*/
795 PetscErrorCode DMMoabIsEntityOnBoundary(DM dm,const moab::EntityHandle ent,PetscBool* ent_on_boundary)
796 {
797   moab::EntityType etype;
798   DM_Moab         *dmmoab;
799   PetscInt         edim;
800 
801   PetscFunctionBegin;
802   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
803   PetscValidPointer(ent_on_boundary,3);
804   dmmoab = (DM_Moab*)(dm)->data;
805 
806   /* get the entity type and handle accordingly */
807   etype=dmmoab->mbiface->type_from_handle(ent);
808   if(etype >= moab::MBPOLYHEDRON) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Entity type on the boundary skin is invalid. EntityType = %D\n",etype);
809 
810   /* get the entity dimension */
811   edim=dmmoab->mbiface->dimension_from_handle(ent);
812 
813   *ent_on_boundary=PETSC_FALSE;
814   if(etype == moab::MBVERTEX && edim == 0) {
815     *ent_on_boundary=((dmmoab->bndyvtx->index(ent) >= 0) ? PETSC_TRUE:PETSC_FALSE);
816   }
817   else {
818     if (edim == dmmoab->dim) {  /* check the higher-dimensional elements first */
819       if (dmmoab->bndyelems->index(ent) >= 0) *ent_on_boundary=PETSC_TRUE;
820     }
821     else {                      /* next check the lower-dimensional faces */
822       if (dmmoab->bndyfaces->index(ent) >= 0) *ent_on_boundary=PETSC_TRUE;
823     }
824   }
825   PetscFunctionReturn(0);
826 }
827 
828 
829 /*@
830   DMMoabIsEntityOnBoundary - Check whether a given entity is on the boundary (vertex, edge, face, element)
831 
832   Input Parameter:
833 . dm - The DMMoab object
834 . nconn - Number of handles
835 . cnt - Array of entity handles
836 
837   Output Parameter:
838 . isbdvtx - Array of boundary markers - PETSC_TRUE if entity on boundary; PETSC_FALSE otherwise
839 
840   Level: beginner
841 
842 .seealso: DMMoabIsEntityOnBoundary()
843 @*/
844 PetscErrorCode DMMoabCheckBoundaryVertices(DM dm,PetscInt nconn,const moab::EntityHandle *cnt,PetscBool* isbdvtx)
845 {
846   DM_Moab        *dmmoab;
847   PetscInt       i;
848 
849   PetscFunctionBegin;
850   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
851   PetscValidPointer(cnt,3);
852   PetscValidPointer(isbdvtx,4);
853   dmmoab = (DM_Moab*)(dm)->data;
854 
855   for (i=0; i < nconn; ++i) {
856     isbdvtx[i]=(dmmoab->bndyvtx->index(cnt[i]) >= 0 ? PETSC_TRUE:PETSC_FALSE);
857   }
858   PetscFunctionReturn(0);
859 }
860 
861 
862 /*@
863   DMMoabGetBoundaryMarkers - Return references to the vertices, faces, elements on the boundary
864 
865   Input Parameter:
866 . dm - The DMMoab object
867 
868   Output Parameter:
869 . bdvtx - Boundary vertices
870 . bdelems - Boundary elements
871 . bdfaces - Boundary faces
872 
873   Level: beginner
874 
875 .seealso: DMMoabCheckBoundaryVertices(), DMMoabIsEntityOnBoundary()
876 @*/
877 PetscErrorCode DMMoabGetBoundaryMarkers(DM dm,const moab::Range **bdvtx,const moab::Range** bdelems,const moab::Range** bdfaces)
878 {
879   DM_Moab        *dmmoab;
880 
881   PetscFunctionBegin;
882   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
883   dmmoab = (DM_Moab*)(dm)->data;
884 
885   if (bdvtx)  *bdvtx = dmmoab->bndyvtx;
886   if (bdfaces)  *bdfaces = dmmoab->bndyfaces;
887   if (bdelems)  *bdfaces = dmmoab->bndyelems;
888   PetscFunctionReturn(0);
889 }
890 
891 
892 PETSC_EXTERN PetscErrorCode DMDestroy_Moab(DM dm)
893 {
894   PetscErrorCode  ierr;
895   PetscInt        i;
896   moab::ErrorCode merr;
897   DM_Moab        *dmmoab = (DM_Moab*)dm->data;
898 
899   PetscFunctionBegin;
900   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
901   if (dmmoab->icreatedinstance) {
902     delete dmmoab->mbiface;
903   }
904   dmmoab->mbiface = NULL;
905   dmmoab->pcomm = NULL;
906   delete dmmoab->vlocal;
907   delete dmmoab->vowned;
908   delete dmmoab->vghost;
909   delete dmmoab->elocal;
910   delete dmmoab->eghost;
911   delete dmmoab->bndyvtx;
912   delete dmmoab->bndyfaces;
913   delete dmmoab->bndyelems;
914 
915   ierr = PetscFree(dmmoab->gsindices);CHKERRQ(ierr);
916   ierr = PetscFree2(dmmoab->gidmap,dmmoab->lidmap);CHKERRQ(ierr);
917   ierr = PetscFree(dmmoab->dfill);CHKERRQ(ierr);
918   ierr = PetscFree(dmmoab->ofill);CHKERRQ(ierr);
919   if (dmmoab->fieldNames) {
920     for(i=0; i<dmmoab->numFields; i++) {
921       ierr = PetscFree(dmmoab->fieldNames[i]);CHKERRQ(ierr);
922     }
923     ierr = PetscFree(dmmoab->fieldNames);CHKERRQ(ierr);
924   }
925 
926   if (dmmoab->nhlevels) {
927     ierr = PetscFree(dmmoab->hsets);CHKERRQ(ierr);
928     dmmoab->nhlevels=0;
929     if (!dmmoab->hlevel && dmmoab->icreatedinstance) delete dmmoab->hierarchy;
930     dmmoab->hierarchy=NULL;
931   }
932 
933   if (dmmoab->icreatedinstance) {
934     merr = dmmoab->mbiface->delete_mesh();MBERRNM(merr);
935     delete dmmoab->mbiface;
936   }
937   dmmoab->mbiface = NULL;
938   dmmoab->pcomm = NULL;
939 
940   ierr = VecScatterDestroy(&dmmoab->ltog_sendrecv);CHKERRQ(ierr);
941   ierr = ISLocalToGlobalMappingDestroy(&dmmoab->ltog_map);CHKERRQ(ierr);
942   ierr = PetscFree(dm->data);CHKERRQ(ierr);
943   PetscFunctionReturn(0);
944 }
945 
946 
947 PETSC_EXTERN PetscErrorCode DMSetFromOptions_Moab(PetscOptionItems *PetscOptionsObject,DM dm)
948 {
949   PetscErrorCode ierr;
950   DM_Moab        *dmmoab = (DM_Moab*)dm->data;
951 
952   PetscFunctionBegin;
953   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
954   ierr = PetscOptionsHead(PetscOptionsObject,"DMMoab Options");CHKERRQ(ierr);
955   ierr  = PetscOptionsInt("-dm_moab_rw_dbg", "The verbosity level for reading and writing MOAB meshes", "DMView", dmmoab->rw_dbglevel, &dmmoab->rw_dbglevel, NULL);CHKERRQ(ierr);
956   ierr  = PetscOptionsBool("-dm_moab_partiton_by_rank", "Use partition by rank when reading MOAB meshes from file", "DMView", dmmoab->partition_by_rank, &dmmoab->partition_by_rank, NULL);CHKERRQ(ierr);
957   /* TODO: typically, the read options are needed before a DM is completely created and available in which case, the options wont be available ?? */
958   ierr  = PetscOptionsString("-dm_moab_read_opts", "Extra options to enable MOAB reader to load DM from file", "DMView", dmmoab->extra_read_options, dmmoab->extra_read_options, PETSC_MAX_PATH_LEN, NULL);CHKERRQ(ierr);
959   ierr  = PetscOptionsString("-dm_moab_write_opts", "Extra options to enable MOAB writer to serialize DM to file", "DMView", dmmoab->extra_write_options, dmmoab->extra_write_options, PETSC_MAX_PATH_LEN, NULL);CHKERRQ(ierr);
960   ierr  = PetscOptionsEnum("-dm_moab_read_mode", "MOAB parallel read mode", "DMView", MoabReadModes, (PetscEnum)dmmoab->read_mode, (PetscEnum*)&dmmoab->read_mode, NULL);CHKERRQ(ierr);
961   ierr  = PetscOptionsEnum("-dm_moab_write_mode", "MOAB parallel write mode", "DMView", MoabWriteModes, (PetscEnum)dmmoab->write_mode, (PetscEnum*)&dmmoab->write_mode, NULL);CHKERRQ(ierr);
962   PetscFunctionReturn(0);
963 }
964 
965 
966 PETSC_EXTERN PetscErrorCode DMSetUp_Moab(DM dm)
967 {
968   PetscErrorCode          ierr;
969   moab::ErrorCode         merr;
970   Vec                     local, global;
971   IS                      from,to;
972   moab::Range::iterator   iter;
973   PetscInt                i,j,f,bs,gmin,lmin,lmax,vent,totsize,*lgmap;
974   DM_Moab                *dmmoab = (DM_Moab*)dm->data;
975   moab::Range             adjs;
976 
977   PetscFunctionBegin;
978   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
979   /* Get the local and shared vertices and cache it */
980   if (dmmoab->mbiface == NULL || dmmoab->pcomm == NULL) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ORDER, "Set the MOAB Interface and ParallelComm objects before calling SetUp.");
981 
982   /* Get the entities recursively in the current part of the mesh, if user did not set the local vertices explicitly */
983   if (dmmoab->vlocal->empty())
984   {
985     //merr = dmmoab->mbiface->get_entities_by_type(dmmoab->fileset,moab::MBVERTEX,*dmmoab->vlocal,true);MBERRNM(merr);
986     merr = dmmoab->mbiface->get_entities_by_dimension(dmmoab->fileset, 0, *dmmoab->vlocal, false);MBERRNM(merr);
987 
988     /* filter based on parallel status */
989     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->vlocal,PSTATUS_NOT_OWNED,PSTATUS_NOT,-1,dmmoab->vowned);MBERRNM(merr);
990 
991     /* filter all the non-owned and shared entities out of the list */
992     adjs = moab::subtract(*dmmoab->vlocal, *dmmoab->vowned);
993     merr = dmmoab->pcomm->filter_pstatus(adjs,PSTATUS_GHOST|PSTATUS_INTERFACE,PSTATUS_OR,-1,dmmoab->vghost);MBERRNM(merr);
994     adjs = moab::subtract(adjs, *dmmoab->vghost);
995     *dmmoab->vlocal = moab::subtract(*dmmoab->vlocal, adjs);
996 
997     /* compute and cache the sizes of local and ghosted entities */
998     dmmoab->nloc = dmmoab->vowned->size();
999     dmmoab->nghost = dmmoab->vghost->size();
1000 
1001     ierr = MPIU_Allreduce(&dmmoab->nloc, &dmmoab->n, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr);
1002     PetscInfo4(NULL, "Filset ID: %u, Vertices: local - %D, owned - %D, ghosted - %D.\n", dmmoab->fileset, dmmoab->vlocal->size(), dmmoab->nloc, dmmoab->nghost);
1003   }
1004 
1005   {
1006     /* get the information about the local elements in the mesh */
1007     dmmoab->eghost->clear();
1008 
1009     /* first decipher the leading dimension */
1010     for (i=3;i>0;i--) {
1011       dmmoab->elocal->clear();
1012       merr = dmmoab->mbiface->get_entities_by_dimension(dmmoab->fileset, i, *dmmoab->elocal, false);MBERRNM(merr);
1013 
1014       /* store the current mesh dimension */
1015       if (dmmoab->elocal->size()) {
1016         dmmoab->dim=i;
1017         break;
1018       }
1019     }
1020 
1021     ierr = DMSetDimension(dm, dmmoab->dim);CHKERRQ(ierr);
1022 
1023     /* filter the ghosted and owned element list */
1024     *dmmoab->eghost = *dmmoab->elocal;
1025     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->elocal,PSTATUS_NOT_OWNED,PSTATUS_NOT);MBERRNM(merr);
1026     *dmmoab->eghost = moab::subtract(*dmmoab->eghost, *dmmoab->elocal);
1027 
1028     dmmoab->neleloc = dmmoab->elocal->size();
1029     dmmoab->neleghost = dmmoab->eghost->size();
1030 
1031     ierr = MPIU_Allreduce(&dmmoab->neleloc, &dmmoab->nele, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr);
1032     PetscInfo3(NULL, "%d-dim elements: owned - %D, ghosted - %D.\n", dmmoab->dim, dmmoab->neleloc, dmmoab->neleghost);
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   if (totsize != dmmoab->nloc+dmmoab->nghost) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Mismatch between local and owned+ghost vertices. %D != %D.",totsize,dmmoab->nloc+dmmoab->nghost);
1045   ierr = PetscCalloc1(totsize,&dmmoab->gsindices);CHKERRQ(ierr);
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     lmin=lmax=dmmoab->gsindices[0];
1055     for (i=0; i<totsize; ++i) {
1056       if(lmin>dmmoab->gsindices[i]) lmin=dmmoab->gsindices[i];
1057       if(lmax<dmmoab->gsindices[i]) lmax=dmmoab->gsindices[i];
1058     }
1059 
1060     ierr = MPIU_Allreduce(&lmin, &gmin, 1, MPI_INT, MPI_MIN, ((PetscObject)dm)->comm);CHKERRQ(ierr);
1061 
1062     /* set the GID map */
1063     for (i=0; i<totsize; ++i) {
1064       dmmoab->gsindices[i]-=gmin;   /* zero based index needed for IS */
1065     }
1066     lmin-=gmin;
1067     lmax-=gmin;
1068 
1069     PetscInfo3(NULL, "GLOBAL_ID: Local minima - %D, Local maxima - %D, Global minima - %D.\n", lmin, lmax, gmin);
1070   }
1071   if(!(dmmoab->bs==dmmoab->numFields || dmmoab->bs == 1)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mismatch between block size and number of component fields. %D != 1 OR %D != %D.",dmmoab->bs,dmmoab->bs,dmmoab->numFields);
1072 
1073   {
1074     dmmoab->seqstart=((PetscInt)dmmoab->vlocal->front());
1075     dmmoab->seqend=((PetscInt)dmmoab->vlocal->back());
1076     PetscInfo2(NULL, "SEQUENCE: Local minima - %D, Local maxima - %D.\n", dmmoab->seqstart, dmmoab->seqend);
1077 
1078     ierr = PetscMalloc2(dmmoab->seqend-dmmoab->seqstart+1,&dmmoab->gidmap,dmmoab->seqend-dmmoab->seqstart+1,&dmmoab->lidmap);CHKERRQ(ierr);
1079     ierr = PetscMalloc1(totsize*dmmoab->numFields,&lgmap);CHKERRQ(ierr);
1080 
1081     i=j=0;
1082     /* set the owned vertex data first */
1083     for(moab::Range::iterator iter = dmmoab->vowned->begin(); iter != dmmoab->vowned->end(); iter++,i++) {
1084       vent=(PetscInt)(*iter)-dmmoab->seqstart;
1085       dmmoab->gidmap[vent]=dmmoab->gsindices[i];
1086       dmmoab->lidmap[vent]=i;
1087       for (f=0;f<dmmoab->numFields;f++,j++) {
1088         lgmap[j]=(bs > 1 ? dmmoab->gsindices[i]*dmmoab->numFields+f : totsize*f+dmmoab->gsindices[i]);
1089       }
1090     }
1091     /* next arrange all the ghosted data information */
1092     for(moab::Range::iterator iter = dmmoab->vghost->begin(); iter != dmmoab->vghost->end(); iter++,i++) {
1093       vent=(PetscInt)(*iter)-dmmoab->seqstart;
1094       dmmoab->gidmap[vent]=dmmoab->gsindices[i];
1095       dmmoab->lidmap[vent]=i;
1096       for (f=0;f<dmmoab->numFields;f++,j++) {
1097         lgmap[j]=(bs > 1 ? dmmoab->gsindices[i]*dmmoab->numFields+f : totsize*f+dmmoab->gsindices[i]);
1098       }
1099     }
1100 
1101     /* We need to create the Global to Local Vector Scatter Contexts
1102        1) First create a local and global vector
1103        2) Create a local and global IS
1104        3) Create VecScatter and LtoGMapping objects
1105        4) Cleanup the IS and Vec objects
1106     */
1107     ierr = DMCreateGlobalVector(dm, &global);CHKERRQ(ierr);
1108     ierr = DMCreateLocalVector(dm, &local);CHKERRQ(ierr);
1109 
1110     ierr = VecGetOwnershipRange(global, &dmmoab->vstart, &dmmoab->vend);CHKERRQ(ierr);
1111 
1112     /* global to local must retrieve ghost points */
1113     ierr = ISCreateStride(((PetscObject)dm)->comm,dmmoab->nloc*dmmoab->numFields,dmmoab->vstart,1,&from);CHKERRQ(ierr);
1114     ierr = ISSetBlockSize(from,bs);CHKERRQ(ierr);
1115 
1116     ierr = ISCreateGeneral(((PetscObject)dm)->comm,dmmoab->nloc*dmmoab->numFields,&lgmap[0],PETSC_COPY_VALUES,&to);CHKERRQ(ierr);
1117     ierr = ISSetBlockSize(to,bs);CHKERRQ(ierr);
1118 
1119     if (!dmmoab->ltog_map) {
1120       /* create to the local to global mapping for vectors in order to use VecSetValuesLocal */
1121       ierr = ISLocalToGlobalMappingCreate(((PetscObject)dm)->comm,dmmoab->bs,totsize*dmmoab->numFields,lgmap,
1122                                           PETSC_COPY_VALUES,&dmmoab->ltog_map);CHKERRQ(ierr);
1123     }
1124 
1125     /* now create the scatter object from local to global vector */
1126     ierr = VecScatterCreate(local,from,global,to,&dmmoab->ltog_sendrecv);CHKERRQ(ierr);
1127 
1128     /* clean up IS, Vec */
1129     ierr = PetscFree(lgmap);CHKERRQ(ierr);
1130     ierr = ISDestroy(&from);CHKERRQ(ierr);
1131     ierr = ISDestroy(&to);CHKERRQ(ierr);
1132     ierr = VecDestroy(&local);CHKERRQ(ierr);
1133     ierr = VecDestroy(&global);CHKERRQ(ierr);
1134   }
1135 
1136   dmmoab->bndyvtx = new moab::Range();
1137   dmmoab->bndyfaces = new moab::Range();
1138   dmmoab->bndyelems = new moab::Range();
1139   /* skin the boundary and store nodes */
1140   {
1141     /* get the skin vertices of boundary faces for the current partition and then filter
1142        the local, boundary faces, vertices and elements alone via PSTATUS flags;
1143        this should not give us any ghosted boundary, but if user needs such a functionality
1144        it would be easy to add it based on the find_skin query below */
1145     moab::Skinner skinner(dmmoab->mbiface);
1146 
1147     /* get the entities on the skin - only the faces */
1148     merr = skinner.find_skin(dmmoab->fileset, *dmmoab->elocal, false, *dmmoab->bndyfaces, NULL, false, true, false);MBERRNM(merr); // 'false' param indicates we want faces back, not vertices
1149 
1150     /* filter all the non-owned and shared entities out of the list */
1151     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->bndyfaces,PSTATUS_NOT_OWNED,PSTATUS_NOT);MBERRNM(merr);
1152     merr = dmmoab->pcomm->filter_pstatus(*dmmoab->bndyfaces,PSTATUS_SHARED,PSTATUS_NOT);MBERRNM(merr);
1153 
1154     /* get all the nodes via connectivity and the parent elements via adjacency information */
1155     merr = dmmoab->mbiface->get_connectivity(*dmmoab->bndyfaces, *dmmoab->bndyvtx, false);MBERRNM(ierr);
1156     merr = dmmoab->mbiface->get_adjacencies(*dmmoab->bndyfaces, dmmoab->dim, false, *dmmoab->bndyelems, moab::Interface::UNION);MBERRNM(ierr);
1157   }
1158   PetscInfo3(NULL, "Found %D boundary vertices, %D boundary faces and %D boundary elements.\n", dmmoab->bndyvtx->size(), dmmoab->bndyfaces->size(), dmmoab->bndyelems->size());
1159   PetscFunctionReturn(0);
1160 }
1161 
1162 PETSC_EXTERN PetscErrorCode DMCreate_Moab(DM dm)
1163 {
1164   PetscErrorCode ierr;
1165 
1166   PetscFunctionBegin;
1167   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1168   ierr = PetscNewLog(dm,(DM_Moab**)&dm->data);CHKERRQ(ierr);
1169 
1170   ((DM_Moab*)dm->data)->bs = 1;
1171   ((DM_Moab*)dm->data)->numFields = 1;
1172   ((DM_Moab*)dm->data)->n = 0;
1173   ((DM_Moab*)dm->data)->nloc = 0;
1174   ((DM_Moab*)dm->data)->nghost = 0;
1175   ((DM_Moab*)dm->data)->nele = 0;
1176   ((DM_Moab*)dm->data)->neleloc = 0;
1177   ((DM_Moab*)dm->data)->neleghost = 0;
1178   ((DM_Moab*)dm->data)->ltog_map = NULL;
1179   ((DM_Moab*)dm->data)->ltog_sendrecv = NULL;
1180 
1181   ((DM_Moab*)dm->data)->vlocal = new moab::Range();
1182   ((DM_Moab*)dm->data)->vowned = new moab::Range();
1183   ((DM_Moab*)dm->data)->vghost = new moab::Range();
1184   ((DM_Moab*)dm->data)->elocal = new moab::Range();
1185   ((DM_Moab*)dm->data)->eghost = new moab::Range();
1186 
1187   dm->ops->createglobalvector       = DMCreateGlobalVector_Moab;
1188   dm->ops->createlocalvector        = DMCreateLocalVector_Moab;
1189   dm->ops->creatematrix             = DMCreateMatrix_Moab;
1190   dm->ops->setup                    = DMSetUp_Moab;
1191   dm->ops->destroy                  = DMDestroy_Moab;
1192   dm->ops->coarsenhierarchy         = DMCoarsenHierarchy_Moab;
1193   dm->ops->refinehierarchy          = DMRefineHierarchy_Moab;
1194   dm->ops->createinterpolation      = DMCreateInterpolation_Moab;
1195   //dm->ops->getinjection             = DMCreateInjection_Moab;
1196   dm->ops->refine                   = DMRefine_Moab;
1197   dm->ops->coarsen                  = DMCoarsen_Moab;
1198   dm->ops->setfromoptions           = DMSetFromOptions_Moab;
1199   dm->ops->globaltolocalbegin       = DMGlobalToLocalBegin_Moab;
1200   dm->ops->globaltolocalend         = DMGlobalToLocalEnd_Moab;
1201   dm->ops->localtoglobalbegin       = DMLocalToGlobalBegin_Moab;
1202   dm->ops->localtoglobalend         = DMLocalToGlobalEnd_Moab;
1203   PetscFunctionReturn(0);
1204 }
1205 
1206