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