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