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