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