xref: /petsc/src/dm/impls/moab/dmmoab.cxx (revision 351b8a77a14151428d13df3ba225e6b91f8e3db7)
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,const moab::Range **owned,const 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,const 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 DM
796 
797   Input Parameter:
798 . dm - The DMMoab object being set
799 
800   Output Parameter:
801 . neg - The number of global elements in the DMMoab instance
802 . nvg - The number of global vertices in the DMMoab instance
803 
804   Level: beginner
805 
806 .keywords: DMMoab, create
807 @*/
808 PetscErrorCode DMMoabGetSize(DM dm,PetscInt *neg,PetscInt *nvg)
809 {
810   PetscFunctionBegin;
811   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
812   if(neg) *neg = ((DM_Moab*)dm->data)->nele;
813   if(nvg) *nvg = ((DM_Moab*)dm->data)->n;
814   PetscFunctionReturn(0);
815 }
816 
817 
818 #undef __FUNCT__
819 #define __FUNCT__ "DMMoabGetLocalSize"
820 /*@
821   DMMoabGetLocalSize - Get the local and ghosted vertex size used with this DMMoab
822 
823   Collective on DM
824 
825   Input Parameter:
826 . dm - The DMMoab object being set
827 
828   Output Parameter:
829 . nel - The number of owned elements in this processor
830 . neg - The number of ghosted elements in this processor
831 . nvl - The number of owned vertices in this processor
832 . nvg - The number of ghosted vertices in this processor
833 
834   Level: beginner
835 
836 .keywords: DMMoab, create
837 @*/
838 PetscErrorCode DMMoabGetLocalSize(DM dm,PetscInt *nel,PetscInt *neg,PetscInt *nvl,PetscInt *nvg)
839 {
840   PetscFunctionBegin;
841   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
842   if(nel) *nel = ((DM_Moab*)dm->data)->neleloc;
843   if(neg) *neg = ((DM_Moab*)dm->data)->neleghost;
844   if(nvl) *nvl = ((DM_Moab*)dm->data)->nloc;
845   if(nvg) *nvg = ((DM_Moab*)dm->data)->nghost;
846   PetscFunctionReturn(0);
847 }
848 
849 
850 #undef __FUNCT__
851 #define __FUNCT__ "DMMoabGetOffset"
852 /*@
853   DMMoabGetOffset - Get the local offset for the global vector
854 
855   Collective on MPI_Comm
856 
857   Input Parameter:
858 . dm - The DMMoab object being set
859 
860   Output Parameter:
861 . offset - The local offset for the global vector
862 
863   Level: beginner
864 
865 .keywords: DMMoab, create
866 @*/
867 PetscErrorCode DMMoabGetOffset(DM dm,PetscInt *offset)
868 {
869   PetscFunctionBegin;
870   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
871   *offset = ((DM_Moab*)dm->data)->vstart;
872   PetscFunctionReturn(0);
873 }
874 
875 
876 #undef __FUNCT__
877 #define __FUNCT__ "DMMoabGetDimension"
878 /*@
879   DMMoabGetDimension - Get the dimension of the DM Mesh
880 
881   Collective on MPI_Comm
882 
883   Input Parameter:
884 . dm - The DMMoab object being set
885 
886   Output Parameter:
887 . dim - The dimension of DM
888 
889   Level: beginner
890 
891 .keywords: DMMoab, create
892 @*/
893 PetscErrorCode DMMoabGetDimension(DM dm,PetscInt *dim)
894 {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
897   *dim = ((DM_Moab*)dm->data)->dim;
898   PetscFunctionReturn(0);
899 }
900 
901 
902 
903 #undef __FUNCT__
904 #define __FUNCT__ "DMMoabGetVertexCoordinates"
905 PetscErrorCode DMMoabGetVertexCoordinates(DM dm,PetscInt nconn,const moab::EntityHandle *conn,PetscScalar *vpos)
906 {
907   DM_Moab         *dmmoab;
908   PetscErrorCode  ierr;
909   moab::ErrorCode merr;
910 
911   PetscFunctionBegin;
912   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
913   PetscValidPointer(conn,3);
914   dmmoab = (DM_Moab*)(dm)->data;
915 
916   if (!vpos) {
917     ierr = PetscMalloc(sizeof(PetscScalar)*nconn*3, &vpos);CHKERRQ(ierr);
918   }
919 
920   /* Get connectivity information in MOAB canonical ordering */
921   merr = dmmoab->mbiface->get_coords(conn, nconn, vpos);MBERRNM(merr);
922   PetscFunctionReturn(0);
923 }
924 
925 
926 #undef __FUNCT__
927 #define __FUNCT__ "DMMoabGetVertexConnectivity"
928 PetscErrorCode DMMoabGetVertexConnectivity(DM dm,moab::EntityHandle ehandle,PetscInt* nconn, moab::EntityHandle **conn)
929 {
930   DM_Moab        *dmmoab;
931   std::vector<moab::EntityHandle> adj_entities,connect;
932   PetscErrorCode  ierr;
933   moab::ErrorCode merr;
934 
935   PetscFunctionBegin;
936   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
937   PetscValidPointer(conn,4);
938   dmmoab = (DM_Moab*)(dm)->data;
939 
940   /* Get connectivity information in MOAB canonical ordering */
941   merr = dmmoab->mbiface->get_adjacencies(&ehandle, 1, 1, true, adj_entities, moab::Interface::UNION);MBERRNM(merr);
942   merr = dmmoab->mbiface->get_connectivity(&adj_entities[0],adj_entities.size(),connect);MBERRNM(merr);
943 
944   if (conn) {
945     ierr = PetscMalloc(sizeof(moab::EntityHandle)*connect.size(), conn);CHKERRQ(ierr);
946     ierr = PetscMemcpy(*conn, &connect[0], sizeof(moab::EntityHandle)*connect.size());CHKERRQ(ierr);
947   }
948   if (nconn) *nconn=connect.size();
949   PetscFunctionReturn(0);
950 }
951 
952 
953 #undef __FUNCT__
954 #define __FUNCT__ "DMMoabRestoreVertexConnectivity"
955 PetscErrorCode DMMoabRestoreVertexConnectivity(DM dm,moab::EntityHandle ehandle,PetscInt* nconn, moab::EntityHandle **conn)
956 {
957   PetscErrorCode  ierr;
958 
959   PetscFunctionBegin;
960   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
961   PetscValidPointer(conn,4);
962 
963   if (conn) {
964     ierr = PetscFree(*conn);CHKERRQ(ierr);
965   }
966   if (nconn) *nconn=0;
967   PetscFunctionReturn(0);
968 }
969 
970 
971 
972 #undef __FUNCT__
973 #define __FUNCT__ "DMMoabGetElementConnectivity"
974 PetscErrorCode DMMoabGetElementConnectivity(DM dm,moab::EntityHandle ehandle,PetscInt* nconn,const moab::EntityHandle **conn)
975 {
976   DM_Moab        *dmmoab;
977   const moab::EntityHandle *connect;
978   moab::ErrorCode merr;
979   PetscInt nnodes;
980 
981   PetscFunctionBegin;
982   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
983   PetscValidPointer(conn,4);
984   dmmoab = (DM_Moab*)(dm)->data;
985 
986   /* Get connectivity information in MOAB canonical ordering */
987   merr = dmmoab->mbiface->get_connectivity(ehandle, connect, nnodes);MBERRNM(merr);
988   if (conn) *conn=connect;
989   if (nconn) *nconn=nnodes;
990   PetscFunctionReturn(0);
991 }
992 
993 
994 #undef __FUNCT__
995 #define __FUNCT__ "DMMoabIsEntityOnBoundary"
996 PetscErrorCode DMMoabIsEntityOnBoundary(DM dm,const moab::EntityHandle ent,PetscBool* ent_on_boundary)
997 {
998   moab::EntityType etype;
999   DM_Moab         *dmmoab;
1000   PetscInt         edim;
1001 
1002   PetscFunctionBegin;
1003   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1004   PetscValidPointer(ent_on_boundary,3);
1005   dmmoab = (DM_Moab*)(dm)->data;
1006 
1007   /* get the entity type and handle accordingly */
1008   etype=dmmoab->mbiface->type_from_handle(ent);
1009   if(etype >= moab::MBPOLYHEDRON) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Entity type on the boundary skin is invalid. EntityType = %D\n",etype);
1010 
1011   /* get the entity dimension */
1012   edim=dmmoab->mbiface->dimension_from_handle(ent);
1013 
1014   *ent_on_boundary=PETSC_FALSE;
1015   if(etype == moab::MBVERTEX && edim == 0) {
1016     if (dmmoab->bndyvtx->index(ent) >= 0) *ent_on_boundary=PETSC_TRUE;
1017   }
1018   else {
1019     if (edim == dmmoab->dim) {  /* check the higher-dimensional elements first */
1020       if (dmmoab->bndyelems->index(ent) >= 0) *ent_on_boundary=PETSC_TRUE;
1021     }
1022     else {                      /* next check the lower-dimensional faces */
1023       if (dmmoab->bndyfaces->index(ent) >= 0) *ent_on_boundary=PETSC_TRUE;
1024     }
1025   }
1026   PetscFunctionReturn(0);
1027 }
1028 
1029 
1030 #undef __FUNCT__
1031 #define __FUNCT__ "DMMoabCheckBoundaryVertices"
1032 PetscErrorCode DMMoabCheckBoundaryVertices(DM dm,PetscInt nconn,const moab::EntityHandle *cnt,PetscBool* isbdvtx)
1033 {
1034   DM_Moab        *dmmoab;
1035   PetscInt       i;
1036 
1037   PetscFunctionBegin;
1038   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1039   PetscValidPointer(cnt,3);
1040   PetscValidPointer(isbdvtx,4);
1041   dmmoab = (DM_Moab*)(dm)->data;
1042 
1043   for (i=0; i < nconn; ++i) {
1044     isbdvtx[i]=(dmmoab->bndyvtx->index(cnt[i]) >= 0 ? PETSC_TRUE:PETSC_FALSE);
1045   }
1046   PetscFunctionReturn(0);
1047 }
1048 
1049 
1050 #undef __FUNCT__
1051 #define __FUNCT__ "DMMoabGetBoundaryMarkers"
1052 PetscErrorCode DMMoabGetBoundaryMarkers(DM dm,const moab::Range **bdvtx,const moab::Range** bdelems,const moab::Range** bdfaces)
1053 {
1054   DM_Moab        *dmmoab;
1055 
1056   PetscFunctionBegin;
1057   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1058   dmmoab = (DM_Moab*)(dm)->data;
1059 
1060   if (bdvtx)  *bdvtx = dmmoab->bndyvtx;
1061   if (bdfaces)  *bdfaces = dmmoab->bndyfaces;
1062   if (bdelems)  *bdfaces = dmmoab->bndyelems;
1063   PetscFunctionReturn(0);
1064 }
1065 
1066