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