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