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