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