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