xref: /petsc/src/dm/impls/moab/dmmoab.cxx (revision 853cdec3194134057905d1a28d2ce93e6a3dcb13)
1 #include <petsc-private/dmimpl.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 <sstream>
7 
8 typedef struct {
9   PetscInt bs; /* Number of degrees of freedom on each entity, aka tag size in moab */
10   PetscBool icreatedinstance; /* true if DM created moab instance internally, will destroy instance in DMDestroy */
11   moab::ParallelComm *pcomm;
12   moab::Interface *mbiface;
13   moab::Tag ltog_tag; /* moab supports "global id" tags, which are usually local to global numbering */
14   moab::Range range;
15 } DM_Moab;
16 
17 typedef struct {
18   moab::Interface    *mbiface;
19   moab::ParallelComm *pcomm;
20   moab::Range         tag_range; /* entities to which this tag applies */
21   moab::Tag           tag;
22   moab::Tag           ltog_tag;
23   PetscInt            tag_size;
24   PetscBool           new_tag;
25   PetscBool           serial;
26 
27 } Vec_MOAB;
28 
29 #undef __FUNCT__
30 #define __FUNCT__ "DMCreateGlobalVector_Moab"
31 PetscErrorCode DMCreateGlobalVector_Moab(DM dm,Vec *gvec)
32 {
33   PetscErrorCode  ierr;
34   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
35 
36   PetscFunctionBegin;
37   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
38   PetscValidPointer(gvec,2);
39   PetscInt block_size = ((DM_Moab*)dm->data)->bs;
40   moab::Tag tag = 0;
41   ierr = DMMoabCreateVector(dm,tag,block_size,dmmoab->range,PETSC_FALSE,PETSC_TRUE,gvec);CHKERRQ(ierr);
42   PetscFunctionReturn(0);
43 }
44 
45 
46 #undef __FUNCT__
47 #define __FUNCT__ "DMCreateLocalVector_Moab"
48 PetscErrorCode DMCreateLocalVector_Moab(DM dm,Vec *gvec)
49 {
50   PetscErrorCode  ierr;
51   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
52 
53   PetscFunctionBegin;
54   PetscInt bs = 1;
55   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
56   PetscValidPointer(gvec,2);
57   moab::Tag tag = 0;
58   ierr = DMMoabCreateVector(dm,tag,bs,dmmoab->range,PETSC_TRUE,PETSC_TRUE,gvec);CHKERRQ(ierr);
59   PetscFunctionReturn(0);
60 }
61 
62 #undef __FUNCT__
63 #define __FUNCT__ "DMDestroy_Moab"
64 PetscErrorCode DMDestroy_Moab(DM dm)
65 {
66   PetscErrorCode ierr;
67 
68   PetscFunctionBegin;
69   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
70   if (((DM_Moab*)dm->data)->icreatedinstance) {
71     delete ((DM_Moab*)dm->data)->mbiface;
72     ((DM_Moab*)dm->data)->mbiface = NULL;
73     ((DM_Moab*)dm->data)->pcomm = NULL;
74     ((DM_Moab*)dm->data)->range.~Range();
75   }
76   ierr = PetscFree(dm->data);CHKERRQ(ierr);
77   PetscFunctionReturn(0);
78 }
79 
80 #undef __FUNCT__
81 #define __FUNCT__ "DMCreate_Moab"
82 PETSC_EXTERN PetscErrorCode DMCreate_Moab(DM dm)
83 {
84   DM_Moab        *moab;
85   PetscErrorCode ierr;
86 
87   PetscFunctionBegin;
88   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
89   ierr = PetscNewLog(dm,DM_Moab,&moab);CHKERRQ(ierr);
90   dm->data = moab;
91   new (moab) DM_Moab();
92 
93   PetscFunctionReturn(0);
94 }
95 
96 #undef __FUNCT__
97 #define __FUNCT__ "DMMoabCreate"
98 /*@
99   DMMoabCreate - Creates a DMMoab object, which encapsulates a moab instance
100 
101   Collective on MPI_Comm
102 
103   Input Parameter:
104 . comm - The communicator for the DMMoab object
105 
106   Output Parameter:
107 . moab  - The DMMoab object
108 
109   Level: beginner
110 
111 .keywords: DMMoab, create
112 @*/
113 PetscErrorCode DMMoabCreate(MPI_Comm comm, DM *moab)
114 {
115   PetscErrorCode ierr;
116 
117   PetscFunctionBegin;
118   PetscValidPointer(moab,2);
119   ierr = DMCreate(comm, moab);CHKERRQ(ierr);
120   ierr = DMSetType(*moab, DMMOAB);CHKERRQ(ierr);
121   PetscFunctionReturn(0);
122 }
123 
124 #undef __FUNCT__
125 #define __FUNCT__ "DMMoabCreateMoab"
126 /*@
127   DMMoabCreate - Creates a DMMoab object, optionally from an instance and other data
128 
129   Collective on MPI_Comm
130 
131   Input Parameter:
132 . comm - The communicator for the DMMoab object
133 . moab - (ptr to) the MOAB Instance; if passed in NULL, MOAB instance is created inside PETSc, and destroyed
134          along with the DMMoab
135 . pcomm - (ptr to) a ParallelComm; if NULL, creates one internally for the whole communicator
136 . ltog_tag - A tag to use to retrieve global id for an entity; if 0, will use GLOBAL_ID_TAG_NAME/tag
137 . range - If non-NULL, contains range of entities to which DOFs will be assigned
138 
139   Output Parameter:
140 . moab  - The DMMoab object
141 
142   Level: beginner
143 
144 .keywords: DMMoab, create
145 @*/
146 PetscErrorCode DMMoabCreateMoab(MPI_Comm comm, moab::Interface *mbiface, moab::ParallelComm *pcomm, moab::Tag ltog_tag, moab::Range *range, DM *moab)
147 {
148   PetscErrorCode ierr;
149   DM_Moab        *dmmoab;
150 
151   PetscFunctionBegin;
152   PetscValidPointer(moab,2);
153   ierr = DMMoabCreate(comm, moab);CHKERRQ(ierr);
154   dmmoab = (DM_Moab*)(*moab)->data;
155 
156   if (!mbiface) {
157     mbiface = new moab::Core();
158     dmmoab->icreatedinstance = PETSC_TRUE;
159   }
160   else
161     dmmoab->icreatedinstance = PETSC_FALSE;
162 
163   if (!pcomm) {
164     PetscInt rank, nprocs;
165     MPI_Comm_rank(comm, &rank);
166     MPI_Comm_size(comm, &nprocs);
167     pcomm = new moab::ParallelComm(mbiface, comm);
168   }
169 
170     // do the initialization of the DM
171   dmmoab->bs       = 0;
172   dmmoab->pcomm    = pcomm;
173   dmmoab->mbiface    = mbiface;
174   dmmoab->ltog_tag = ltog_tag;
175 
176     // initialize various functions
177   (*moab)->ops->createglobalvector              = DMCreateGlobalVector_Moab;
178   (*moab)->ops->createlocalvector               = DMCreateLocalVector_Moab;
179   (*moab)->ops->destroy                         = DMDestroy_Moab;
180 
181   ierr = DMMoabSetInterface(*moab, mbiface);CHKERRQ(ierr);
182   if (!pcomm) pcomm = new moab::ParallelComm(mbiface, comm);
183   ierr = DMMoabSetParallelComm(*moab, pcomm);CHKERRQ(ierr);
184   if (!ltog_tag) {
185     moab::ErrorCode merr = mbiface->tag_get_handle(GLOBAL_ID_TAG_NAME, ltog_tag);MBERRNM(merr);
186   }
187   if (ltog_tag) {
188     ierr = DMMoabSetLocalToGlobalTag(*moab, ltog_tag);CHKERRQ(ierr);
189   }
190   if (range) {
191     ierr = DMMoabSetRange(*moab, *range);CHKERRQ(ierr);
192   }
193   PetscFunctionReturn(0);
194 }
195 
196 #undef __FUNCT__
197 #define __FUNCT__ "DMMoabSetParallelComm"
198 /*@
199   DMMoabSetParallelComm - Set the ParallelComm used with this DMMoab
200 
201   Collective on MPI_Comm
202 
203   Input Parameter:
204 . dm    - The DMMoab object being set
205 . pcomm - The ParallelComm being set on the DMMoab
206 
207   Level: beginner
208 
209 .keywords: DMMoab, create
210 @*/
211 PetscErrorCode DMMoabSetParallelComm(DM dm,moab::ParallelComm *pcomm)
212 {
213   PetscFunctionBegin;
214   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
215   ((DM_Moab*)dm->data)->pcomm = pcomm;
216   ((DM_Moab*)dm->data)->mbiface = pcomm->get_moab();
217   PetscFunctionReturn(0);
218 }
219 
220 
221 #undef __FUNCT__
222 #define __FUNCT__ "DMMoabGetParallelComm"
223 /*@
224   DMMoabGetParallelComm - Get the ParallelComm used with this DMMoab
225 
226   Collective on MPI_Comm
227 
228   Input Parameter:
229 . dm    - The DMMoab object being set
230 
231   Output Parameter:
232 . pcomm - The ParallelComm for the DMMoab
233 
234   Level: beginner
235 
236 .keywords: DMMoab, create
237 @*/
238 PetscErrorCode DMMoabGetParallelComm(DM dm,moab::ParallelComm **pcomm)
239 {
240   PetscFunctionBegin;
241   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
242   *pcomm = ((DM_Moab*)dm->data)->pcomm;
243   PetscFunctionReturn(0);
244 }
245 
246 
247 #undef __FUNCT__
248 #define __FUNCT__ "DMMoabSetInterface"
249 /*@
250   DMMoabSetInterface - Set the MOAB instance used with this DMMoab
251 
252   Collective on MPI_Comm
253 
254   Input Parameter:
255 . dm      - The DMMoab object being set
256 . mbiface - The MOAB instance being set on this DMMoab
257 
258   Level: beginner
259 
260 .keywords: DMMoab, create
261 @*/
262 PetscErrorCode DMMoabSetInterface(DM dm,moab::Interface *mbiface)
263 {
264   PetscFunctionBegin;
265   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
266   ((DM_Moab*)dm->data)->pcomm = NULL;
267   ((DM_Moab*)dm->data)->mbiface = mbiface;
268   PetscFunctionReturn(0);
269 }
270 
271 
272 #undef __FUNCT__
273 #define __FUNCT__ "DMMoabGetInterface"
274 /*@
275   DMMoabGetInterface - Get the MOAB instance used with this DMMoab
276 
277   Collective on MPI_Comm
278 
279   Input Parameter:
280 . dm      - The DMMoab object being set
281 
282   Output Parameter:
283 . mbiface - The MOAB instance set on this DMMoab
284 
285   Level: beginner
286 
287 .keywords: DMMoab, create
288 @*/
289 PetscErrorCode DMMoabGetInterface(DM dm,moab::Interface **mbiface)
290 {
291   PetscFunctionBegin;
292   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
293   *mbiface = ((DM_Moab*)dm->data)->mbiface;
294   PetscFunctionReturn(0);
295 }
296 
297 
298 #undef __FUNCT__
299 #define __FUNCT__ "DMMoabSetRange"
300 /*@
301   DMMoabSetRange - Set the entities having DOFs on this DMMoab
302 
303   Collective on MPI_Comm
304 
305   Input Parameter:
306 . dm    - The DMMoab object being set
307 . range - The entities treated by this DMMoab
308 
309   Level: beginner
310 
311 .keywords: DMMoab, create
312 @*/
313 PetscErrorCode DMMoabSetRange(DM dm,moab::Range range)
314 {
315   PetscFunctionBegin;
316   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
317   ((DM_Moab*)dm->data)->range = range;
318   PetscFunctionReturn(0);
319 }
320 
321 
322 #undef __FUNCT__
323 #define __FUNCT__ "DMMoabGetRange"
324 /*@
325   DMMoabGetRange - Get the entities having DOFs on this DMMoab
326 
327   Collective on MPI_Comm
328 
329   Input Parameter:
330 . dm    - The DMMoab object being set
331 
332   Output Parameter:
333 . range - The entities treated by this DMMoab
334 
335   Level: beginner
336 
337 .keywords: DMMoab, create
338 @*/
339 PetscErrorCode DMMoabGetRange(DM dm,moab::Range *range)
340 {
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
343   *range = ((DM_Moab*)dm->data)->range;
344   PetscFunctionReturn(0);
345 }
346 
347 #undef __FUNCT__
348 #define __FUNCT__ "DMMoabSetLocalToGlobalTag"
349 /*@
350   DMMoabSetLocalToGlobalTag - Set the tag used for local to global numbering
351 
352   Collective on MPI_Comm
353 
354   Input Parameter:
355 . dm      - The DMMoab object being set
356 . ltogtag - The MOAB tag used for local to global ids
357 
358   Level: beginner
359 
360 .keywords: DMMoab, create
361 @*/
362 PetscErrorCode DMMoabSetLocalToGlobalTag(DM dm,moab::Tag ltogtag)
363 {
364   PetscFunctionBegin;
365   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
366   ((DM_Moab*)dm->data)->ltog_tag = ltogtag;
367   PetscFunctionReturn(0);
368 }
369 
370 
371 #undef __FUNCT__
372 #define __FUNCT__ "DMMoabGetLocalToGlobalTag"
373 /*@
374   DMMoabGetLocalToGlobalTag - Get the tag used for local to global numbering
375 
376   Collective on MPI_Comm
377 
378   Input Parameter:
379 . dm      - The DMMoab object being set
380 
381   Output Parameter:
382 . ltogtag - The MOAB tag used for local to global ids
383 
384   Level: beginner
385 
386 .keywords: DMMoab, create
387 @*/
388 PetscErrorCode DMMoabGetLocalToGlobalTag(DM dm,moab::Tag *ltog_tag)
389 {
390   PetscFunctionBegin;
391   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
392   *ltog_tag = ((DM_Moab*)dm->data)->ltog_tag;
393   PetscFunctionReturn(0);
394 }
395 
396 
397 #undef __FUNCT__
398 #define __FUNCT__ "DMMoabSetBlockSize"
399 /*@
400   DMMoabSetBlockSize - Set the block size used with this DMMoab
401 
402   Collective on MPI_Comm
403 
404   Input Parameter:
405 . dm - The DMMoab object being set
406 . bs - The block size used with this DMMoab
407 
408   Level: beginner
409 
410 .keywords: DMMoab, create
411 @*/
412 PetscErrorCode DMMoabSetBlockSize(DM dm,PetscInt bs)
413 {
414   PetscFunctionBegin;
415   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
416   ((DM_Moab*)dm->data)->bs = bs;
417   PetscFunctionReturn(0);
418 }
419 
420 
421 #undef __FUNCT__
422 #define __FUNCT__ "DMMoabGetBlockSize"
423 /*@
424   DMMoabGetBlockSize - Get the block size used with this DMMoab
425 
426   Collective on MPI_Comm
427 
428   Input Parameter:
429 . dm - The DMMoab object being set
430 
431   Output Parameter:
432 . bs - The block size used with this DMMoab
433 
434   Level: beginner
435 
436 .keywords: DMMoab, create
437 @*/
438 PetscErrorCode DMMoabGetBlockSize(DM dm,PetscInt *bs)
439 {
440   PetscFunctionBegin;
441   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
442   *bs = ((DM_Moab*)dm->data)->bs;
443   PetscFunctionReturn(0);
444 }
445 
446 
447 // declare for use later but before they're defined
448 PetscErrorCode DMMoab_VecUserDestroy(void *user);
449 PetscErrorCode DMMoab_VecDuplicate(Vec x,Vec *y);
450 PetscErrorCode DMMoab_CreateTagName(const moab::ParallelComm *pcomm,std::string& tag_name);
451 PetscErrorCode DMMoab_CreateVector(moab::Interface *iface,moab::ParallelComm *pcomm,moab::Tag tag,PetscInt tag_size,moab::Tag ltog_tag,moab::Range range,PetscBool serial, PetscBool destroy_tag,Vec *vec);
452 
453 #undef __FUNCT__
454 #define __FUNCT__ "DMMoabCreateVector"
455 /*@
456   DMMoabCreateVector - Create a Vec from either an existing tag, or a specified tag size, and a range of entities
457 
458   Collective on MPI_Comm
459 
460   Input Parameter:
461 . dm          - The DMMoab object being set
462 . tag         - If non-zero, block size will be taken from the tag size
463 . tag_size    - If tag was zero, this parameter specifies the block size; unique tag name will be generated automatically
464 . range       - If non-empty, Vec corresponds to these entities, otherwise to the entities set on the DMMoab
465 . serial      - If true, this is a serial Vec, otherwise a parallel one
466 . destroy_tag - If true, MOAB tag is destroyed with Vec, otherwise it is left on MOAB
467 
468   Output Parameter:
469 . vec         - The created vector
470 
471   Level: beginner
472 
473 .keywords: DMMoab, create
474 @*/
475 PetscErrorCode DMMoabCreateVector(DM dm,moab::Tag tag,PetscInt tag_size,moab::Range range,PetscBool serial, PetscBool destroy_tag,Vec *vec)
476 {
477   PetscErrorCode     ierr;
478 
479   PetscFunctionBegin;
480 
481   DM_Moab *dmmoab = (DM_Moab*)dm->data;
482   moab::ParallelComm *pcomm = dmmoab->pcomm;
483   moab::Interface *mbiface = dmmoab->mbiface;
484   moab::Tag ltog_tag = dmmoab->ltog_tag;
485 
486   if (!tag && !tag_size) {
487     PetscFunctionReturn(PETSC_ERR_ARG_WRONG);
488   }
489   else {
490     ierr = DMMoab_CreateVector(mbiface,pcomm,tag,tag_size,ltog_tag,range,serial,destroy_tag,vec);CHKERRQ(ierr);
491   }
492   PetscFunctionReturn(0);
493 }
494 
495 
496 #undef __FUNCT__
497 #define __FUNCT__ "DMMoab_CreateVector"
498 PetscErrorCode DMMoab_CreateVector(moab::Interface *mbiface,moab::ParallelComm *pcomm,moab::Tag tag,PetscInt tag_size,moab::Tag ltog_tag,moab::Range range,PetscBool serial, PetscBool destroy_tag,Vec *vec)
499 {
500   PetscErrorCode     ierr;
501   moab::ErrorCode    merr;
502 
503   PetscFunctionBegin;
504 
505   if (!tag) {
506     std::string tag_name;
507     ierr = DMMoab_CreateTagName(pcomm,tag_name);CHKERRQ(ierr);
508 
509       // Create the default value for the tag (all zeros):
510     std::vector<PetscScalar> default_value(tag_size, 0.0);
511 
512       // Create the tag:
513     merr = mbiface->tag_get_handle(tag_name.c_str(),tag_size,moab::MB_TYPE_DOUBLE,tag,
514                                    moab::MB_TAG_DENSE | moab::MB_TAG_CREAT,default_value.data());MBERRNM(merr);
515   }
516   else {
517 
518       // Make sure the tag data is of type "double":
519     moab::DataType tag_type;
520     merr = mbiface->tag_get_data_type(tag, tag_type);MBERRNM(merr);
521     if(tag_type != moab::MB_TYPE_DOUBLE) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Tag data type must be MB_TYPE_DOUBLE");
522   }
523 
524     // Create the MOAB internal data object
525   Vec_MOAB *vmoab;
526   ierr = PetscMalloc(sizeof(Vec_MOAB),&vmoab);CHKERRQ(ierr);
527   new (vmoab) Vec_MOAB();
528   vmoab->tag = tag;
529   vmoab->ltog_tag = ltog_tag;
530   vmoab->mbiface = mbiface;
531   vmoab->pcomm = pcomm;
532   vmoab->tag_range = range;
533   vmoab->new_tag = destroy_tag;
534   vmoab->serial = serial;
535   merr = mbiface->tag_get_length(tag,vmoab->tag_size);MBERR("tag_get_size", merr);
536 
537     // Call tag_iterate. This will cause MOAB to allocate memory for the
538     // tag data if it hasn't already happened:
539   int  count;
540   void *void_ptr;
541   merr = mbiface->tag_iterate(tag,range.begin(),range.end(),count,void_ptr);MBERRNM(merr);
542 
543     // Check to make sure the tag data is in a single sequence:
544   if ((unsigned)count != range.size()) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only create MOAB Vector for single sequence");
545   PetscScalar *data_ptr = (PetscScalar*)void_ptr;
546 
547     // Create the PETSc Vector:
548   if(!serial) {
549       // This is an MPI Vector:
550     ierr = VecCreateMPIWithArray(vmoab->pcomm->comm(),vmoab->tag_size,vmoab->tag_size*range.size(),
551                                  PETSC_DECIDE,data_ptr,vec);CHKERRQ(ierr);
552 
553       // Vector created, manually set local to global mapping:
554     ISLocalToGlobalMapping ltog;
555     PetscInt               *gindices = new PetscInt[range.size()];
556     PetscInt               count = 0;
557     moab::Range::iterator  iter;
558     for(iter = range.begin(); iter != range.end(); iter++) {
559       int dof;
560       merr = mbiface->tag_get_data(ltog_tag,&(*iter),1,&dof);MBERRNM(merr);
561       gindices[count] = dof;
562       count++;
563     }
564 
565     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,range.size(),gindices,
566                                         PETSC_COPY_VALUES,&ltog);CHKERRQ(ierr);
567     ierr = VecSetLocalToGlobalMappingBlock(*vec,ltog);CHKERRQ(ierr);
568 
569       // Clean up:
570     ierr = ISLocalToGlobalMappingDestroy(&ltog);CHKERRQ(ierr);
571     delete [] gindices;
572   } else {
573       // This is a serial vector:
574     ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,vmoab->tag_size,vmoab->tag_size*range.size(),data_ptr,vec);CHKERRQ(ierr);
575   }
576 
577 
578   PetscContainer moabdata;
579   ierr = PetscContainerCreate(PETSC_COMM_SELF,&moabdata);CHKERRQ(ierr);
580   ierr = PetscContainerSetPointer(moabdata,vmoab);CHKERRQ(ierr);
581   ierr = PetscContainerSetUserDestroy(moabdata,DMMoab_VecUserDestroy);CHKERRQ(ierr);
582   ierr = PetscObjectCompose((PetscObject)*vec,"MOABData",(PetscObject)moabdata);CHKERRQ(ierr);
583   (*vec)->ops->duplicate = DMMoab_VecDuplicate;
584 
585   ierr = PetscContainerDestroy(&moabdata);CHKERRQ(ierr);
586   PetscFunctionReturn(0);
587 }
588 
589 #undef __FUNCT__
590 #define __FUNCT__ "DMMoabGetVecTag"
591 /*@
592   DMMoabGetVecTag - Get the MOAB tag associated with this Vec
593 
594   Collective on MPI_Comm
595 
596   Input Parameter:
597 . vec - Vec being queried
598 
599   Output Parameter:
600 . tag - Tag associated with this Vec
601 
602   Level: beginner
603 
604 .keywords: DMMoab, create
605 @*/
606 PetscErrorCode DMMoabGetVecTag(Vec vec,moab::Tag *tag)
607 {
608   PetscContainer  moabdata;
609   Vec_MOAB        *vmoab;
610   PetscErrorCode  ierr;
611 
612   PetscFunctionBegin;
613 
614   // Get the MOAB private data:
615   ierr = PetscObjectQuery((PetscObject)vec,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
616   ierr = PetscContainerGetPointer(moabdata, (void**) &vmoab);CHKERRQ(ierr);
617 
618   *tag = vmoab->tag;
619 
620   PetscFunctionReturn(0);
621 }
622 
623 
624 #undef __FUNCT__
625 #define __FUNCT__ "DMMoabGetVecRange"
626 /*@
627   DMMoabGetVecRange - Get the MOAB entities associated with this Vec
628 
629   Collective on MPI_Comm
630 
631   Input Parameter:
632 . vec   - Vec being queried
633 
634   Output Parameter:
635 . range - Entities associated with this Vec
636 
637   Level: beginner
638 
639 .keywords: DMMoab, create
640 @*/
641 PetscErrorCode DMMoabGetVecRange(Vec vec,moab::Range *range)
642 {
643   PetscContainer  moabdata;
644   Vec_MOAB        *vmoab;
645   PetscErrorCode  ierr;
646 
647   PetscFunctionBegin;
648 
649   // Get the MOAB private data:
650   ierr = PetscObjectQuery((PetscObject)vec,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
651   ierr = PetscContainerGetPointer(moabdata, (void**) &vmoab);CHKERRQ(ierr);
652 
653   *range = vmoab->tag_range;
654 
655   PetscFunctionReturn(0);
656 }
657 
658 
659 #undef __FUNCT__
660 #define __FUNCT__ "DMMoab_VecDuplicate"
661 PetscErrorCode DMMoab_VecDuplicate(Vec x,Vec *y)
662 {
663   PetscErrorCode ierr;
664   PetscFunctionBegin;
665   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
666   PetscValidPointer(y,2);
667 
668   // Get the Vec_MOAB struct for the original vector:
669   PetscContainer  moabdata;
670   Vec_MOAB        *vmoab;
671   ierr = PetscObjectQuery((PetscObject)x,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
672   ierr = PetscContainerGetPointer(moabdata, (void**)&vmoab);CHKERRQ(ierr);
673 
674   ierr = DMMoab_CreateVector(vmoab->mbiface,vmoab->pcomm,0,vmoab->tag_size,vmoab->ltog_tag,vmoab->tag_range,vmoab->serial,PETSC_TRUE,y);CHKERRQ(ierr);
675   PetscFunctionReturn(0);
676 }
677 
678 
679 #undef __FUNCT__
680 #define __FUNCT__ "DMMoab_CreateTagName"
681 /*  DMMoab_CreateTagName
682  *
683  *  Creates a unique tag name that will be shared across processes. If
684  *  pcomm is NULL, then this is a serial vector. A unique tag name
685  *  will be returned in tag_name in either case.
686  *
687  *  The tag names have the format _PETSC_VEC_N where N is some integer.
688  */
689 PetscErrorCode DMMoab_CreateTagName(const moab::ParallelComm *pcomm,std::string& tag_name)
690 {
691   moab::ErrorCode mberr;
692   PetscErrorCode  ierr;
693 
694   PetscFunctionBegin;
695   const std::string PVEC_PREFIX      = "_PETSC_VEC_";
696   const PetscInt    PVEC_PREFIX_SIZE = PVEC_PREFIX.size();
697 
698   // Check to see if there are any PETSc vectors defined:
699   const moab::Interface  *mbiface = pcomm->get_moab();
700   std::vector<moab::Tag> tags;
701   PetscInt               n = 0;
702   mberr = mbiface->tag_get_tags(tags);MBERRNM(mberr);
703   for(unsigned i = 0; i < tags.size(); i++) {
704     std::string s;
705     mberr = mbiface->tag_get_name(tags[i],s);MBERRNM(mberr);
706     if(s.find(PVEC_PREFIX) != std::string::npos){
707       // This tag represents a PETSc vector. Find the vector number:
708       PetscInt m;
709       std::istringstream(s.substr(PVEC_PREFIX_SIZE)) >> m;
710       if(m >= n) n = m+1;
711     }
712   }
713 
714   // Make sure that n is consistent across all processes:
715   PetscInt global_n;
716   MPI_Comm comm = PETSC_COMM_SELF;
717   if(pcomm) comm = pcomm->comm();
718   ierr = MPI_Allreduce(&n,&global_n,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
719 
720   // Set the answer and return:
721   std::ostringstream ss;
722   ss << PVEC_PREFIX << global_n;
723   tag_name = ss.str();
724   PetscFunctionReturn(0);
725 }
726 
727 
728 #undef __FUNCT__
729 #define __FUNCT__ "DMMoab_VecUserDestroy"
730 PetscErrorCode DMMoab_VecUserDestroy(void *user)
731 {
732   Vec_MOAB        *vmoab;
733   PetscErrorCode  ierr;
734   moab::ErrorCode merr;
735 
736   PetscFunctionBegin;
737   vmoab = (Vec_MOAB*)user;
738   vmoab->tag_range.~Range();
739   if(vmoab->new_tag) {
740     // Tag created via a call to VecDuplicate, delete the underlying tag in MOAB...
741     merr = vmoab->mbiface->tag_delete(vmoab->tag);MBERRNM(merr);
742   }
743 
744   ierr = PetscFree(vmoab);CHKERRQ(ierr);
745   PetscFunctionReturn(0);
746 }
747 
748