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