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