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