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