xref: /petsc/src/dm/impls/moab/dmmbvec.cxx (revision 609bdbee21ea3be08735c64dbe00a9ab27759925)
1 #include <petsc/private/dmmbimpl.h> /*I  "petscdmmoab.h"   I*/
2 #include <petsc/private/vecimpl.h>
3 
4 #include <petscdmmoab.h>
5 #include <MBTagConventions.hpp>
6 
7 /* declare some private DMMoab specific overrides */
8 static PetscErrorCode DMCreateVector_Moab_Private(DM dm,moab::Tag tag,const moab::Range* userrange,PetscBool is_global_vec,PetscBool destroy_tag,Vec *vec);
9 static PetscErrorCode DMVecUserDestroy_Moab(void *user);
10 static PetscErrorCode DMVecDuplicate_Moab(Vec x,Vec *y);
11 static PetscErrorCode DMVecCreateTagName_Moab_Private(moab::ParallelComm *pcomm,char** tag_name);
12 
13 /*@C
14   DMMoabCreateVector - Create a Vec from either an existing tag, or a specified tag size, and a range of entities
15 
16   Collective on MPI_Comm
17 
18   Input Parameter:
19 + dm              - The DMMoab object being set
20 . tag             - If non-zero, block size will be taken from the tag size
21 . range           - If non-empty, Vec corresponds to these entities, otherwise to the entities set on the DMMoab
22 . is_global_vec   - If true, this is a local representation of the Vec (including ghosts in parallel), otherwise a truly parallel one
23 . destroy_tag     - If true, MOAB tag is destroyed with Vec, otherwise it is left on MOAB
24 
25   Output Parameter:
26 . vec             - The created vector
27 
28   Level: beginner
29 
30 .keywords: Vec, create
31 
32 .seealso: VecCreate()
33 @*/
34 PetscErrorCode DMMoabCreateVector(DM dm,moab::Tag tag,const moab::Range* range,PetscBool is_global_vec,PetscBool destroy_tag,Vec *vec)
35 {
36   PetscErrorCode     ierr;
37 
38   PetscFunctionBegin;
39   if(!tag && (!range || range->empty())) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Both tag and range cannot be null.");
40 
41   ierr = DMCreateVector_Moab_Private(dm,tag,range,is_global_vec,destroy_tag,vec);CHKERRQ(ierr);
42   PetscFunctionReturn(0);
43 }
44 
45 
46 /*@C
47   DMMoabGetVecTag - Get the MOAB tag associated with this Vec
48 
49   Input Parameter:
50 . vec - Vec being queried
51 
52   Output Parameter:
53 . tag - Tag associated with this Vec. NULL if vec is a native PETSc Vec.
54 
55   Level: beginner
56 
57 .keywords: DMMoab, MOAB tag
58 
59 .seealso: DMMoabCreateVector(), DMMoabGetVecRange()
60 @*/
61 PetscErrorCode DMMoabGetVecTag(Vec vec,moab::Tag *tag)
62 {
63   PetscContainer  moabdata;
64   Vec_MOAB        *vmoab;
65   PetscErrorCode  ierr;
66 
67   PetscFunctionBegin;
68   PetscValidPointer(tag,2);
69 
70   /* Get the MOAB private data */
71   ierr = PetscObjectQuery((PetscObject)vec,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
72   ierr = PetscContainerGetPointer(moabdata, (void**) &vmoab);CHKERRQ(ierr);
73 
74   *tag = vmoab->tag;
75   PetscFunctionReturn(0);
76 }
77 
78 
79 /*@C
80   DMMoabGetVecRange - Get the MOAB entities associated with this Vec
81 
82   Input Parameter:
83 . vec   - Vec being queried
84 
85   Output Parameter:
86 . range - Entities associated with this Vec. NULL if vec is a native PETSc Vec.
87 
88   Level: beginner
89 
90 .keywords: DMMoab, MOAB range
91 
92 .seealso: DMMoabCreateVector(), DMMoabGetVecTag()
93 @*/
94 PetscErrorCode DMMoabGetVecRange(Vec vec,moab::Range *range)
95 {
96   PetscContainer  moabdata;
97   Vec_MOAB        *vmoab;
98   PetscErrorCode  ierr;
99 
100   PetscFunctionBegin;
101   PetscValidPointer(range,2);
102 
103   /* Get the MOAB private data handle */
104   ierr = PetscObjectQuery((PetscObject)vec,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
105   ierr = PetscContainerGetPointer(moabdata, (void**) &vmoab);CHKERRQ(ierr);
106 
107   *range = *vmoab->tag_range;
108   PetscFunctionReturn(0);
109 }
110 
111 
112 /*@C
113   DMMoabVecGetArray - Returns the writable direct access array to the local representation of MOAB tag data for the underlying vector using locally owned+ghosted range of entities
114 
115   Collective on MPI_Comm
116 
117   Input Parameter:
118 . dm              - The DMMoab object being set
119 . vec             - The Vector whose underlying data is requested
120 
121   Output Parameter:
122 . array           - The local data array
123 
124   Level: intermediate
125 
126 .keywords: MOAB, distributed array
127 
128 .seealso: DMMoabVecRestoreArray(), DMMoabVecGetArrayRead(), DMMoabVecRestoreArrayRead()
129 @*/
130 PetscErrorCode  DMMoabVecGetArray(DM dm,Vec vec,void* array)
131 {
132   DM_Moab        *dmmoab;
133   moab::ErrorCode merr;
134   PetscErrorCode  ierr;
135   PetscInt        count,i,f;
136   moab::Tag       vtag;
137   PetscScalar     **varray;
138   PetscScalar     *marray;
139   PetscContainer  moabdata;
140   Vec_MOAB        *vmoab,*xmoab;
141 
142   PetscFunctionBegin;
143   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
144   PetscValidHeaderSpecific(vec,VEC_CLASSID,2);
145   PetscValidPointer(array,3);
146   dmmoab=(DM_Moab*)dm->data;
147 
148   /* Get the Vec_MOAB struct for the original vector */
149   ierr = PetscObjectQuery((PetscObject)vec,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
150   ierr = PetscContainerGetPointer(moabdata, (void**)&vmoab);CHKERRQ(ierr);
151 
152   /* Get the real scalar array handle */
153   varray = reinterpret_cast<PetscScalar**>(array);
154 
155   if (vmoab->is_native_vec) {
156 
157     /* get the local representation of the arrays from Vectors */
158     ierr = DMGetLocalVector(dm,&vmoab->local);CHKERRQ(ierr);
159     ierr = DMGlobalToLocalBegin(dm,vec,INSERT_VALUES,vmoab->local);CHKERRQ(ierr);
160     ierr = DMGlobalToLocalEnd(dm,vec,INSERT_VALUES,vmoab->local);CHKERRQ(ierr);
161 
162     /* Get the Vec_MOAB struct for the original vector */
163     ierr = PetscObjectQuery((PetscObject)vmoab->local,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
164     ierr = PetscContainerGetPointer(moabdata, (void**)&xmoab);CHKERRQ(ierr);
165 
166     /* get the local representation of the arrays from Vectors */
167     ierr = VecGhostGetLocalForm(vmoab->local,&xmoab->local);CHKERRQ(ierr);
168     ierr = VecGhostUpdateBegin(vmoab->local,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
169     ierr = VecGhostUpdateEnd(vmoab->local,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
170 
171     ierr = VecGetArray(xmoab->local, varray);CHKERRQ(ierr);
172   }
173   else {
174 
175     /* Get the MOAB private data */
176     ierr = DMMoabGetVecTag(vec,&vtag);CHKERRQ(ierr);
177 
178     /* exchange the data into ghost cells first */
179     merr = dmmoab->pcomm->exchange_tags(vtag,*dmmoab->vlocal);MBERRNM(merr);
180 
181     ierr = PetscMalloc1((dmmoab->nloc+dmmoab->nghost)*dmmoab->numFields,varray);CHKERRQ(ierr);
182 
183     /* Get the array data for local entities */
184     merr = dmmoab->mbiface->tag_iterate(vtag,dmmoab->vlocal->begin(),dmmoab->vlocal->end(),count,reinterpret_cast<void*&>(marray),false);MBERRNM(merr);
185     if (count!=dmmoab->nloc+dmmoab->nghost) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mismatch between local vertices and tag partition for Vec. %D != %D.",count,dmmoab->nloc+dmmoab->nghost);
186 
187     i=0;
188     for(moab::Range::iterator iter = dmmoab->vlocal->begin(); iter != dmmoab->vlocal->end(); iter++) {
189       for (f=0;f<dmmoab->numFields;f++,i++)
190         (*varray)[dmmoab->lidmap[(PetscInt)*iter]*dmmoab->numFields+f]=marray[i];
191     }
192   }
193   PetscFunctionReturn(0);
194 }
195 
196 
197 /*@C
198   DMMoabVecRestoreArray - Restores the writable direct access array obtained via DMMoabVecGetArray
199 
200   Collective on MPI_Comm
201 
202   Input Parameter:
203 + dm              - The DMMoab object being set
204 . vec             - The Vector whose underlying data is requested
205 . array           - The local data array
206 
207   Level: intermediate
208 
209 .keywords: MOAB, distributed array
210 
211 .seealso: DMMoabVecGetArray(), DMMoabVecGetArrayRead(), DMMoabVecRestoreArrayRead()
212 @*/
213 PetscErrorCode  DMMoabVecRestoreArray(DM dm,Vec vec,void* array)
214 {
215   DM_Moab        *dmmoab;
216   moab::ErrorCode merr;
217   PetscErrorCode  ierr;
218   moab::Tag       vtag;
219   PetscInt        count,i,f;
220   PetscScalar     **varray;
221   PetscScalar     *marray;
222   PetscContainer  moabdata;
223   Vec_MOAB        *vmoab,*xmoab;
224 
225   PetscFunctionBegin;
226   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
227   PetscValidHeaderSpecific(vec,VEC_CLASSID,2);
228   PetscValidPointer(array,3);
229   dmmoab=(DM_Moab*)dm->data;
230 
231   /* Get the Vec_MOAB struct for the original vector */
232   ierr = PetscObjectQuery((PetscObject)vec,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
233   ierr = PetscContainerGetPointer(moabdata, (void**)&vmoab);CHKERRQ(ierr);
234 
235   /* Get the real scalar array handle */
236   varray = reinterpret_cast<PetscScalar**>(array);
237 
238   if (vmoab->is_native_vec) {
239 
240     /* Get the Vec_MOAB struct for the original vector */
241     ierr = PetscObjectQuery((PetscObject)vmoab->local,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
242     ierr = PetscContainerGetPointer(moabdata, (void**)&xmoab);CHKERRQ(ierr);
243 
244     /* get the local representation of the arrays from Vectors */
245     ierr = VecRestoreArray(xmoab->local, varray);CHKERRQ(ierr);
246     ierr = VecGhostUpdateBegin(vmoab->local,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
247     ierr = VecGhostUpdateEnd(vmoab->local,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
248     ierr = VecGhostRestoreLocalForm(vmoab->local,&xmoab->local);CHKERRQ(ierr);
249 
250     /* restore local pieces */
251     ierr = DMLocalToGlobalBegin(dm,vmoab->local,INSERT_VALUES,vec);CHKERRQ(ierr);
252     ierr = DMLocalToGlobalEnd(dm,vmoab->local,INSERT_VALUES,vec);CHKERRQ(ierr);
253     ierr = DMRestoreLocalVector(dm, &vmoab->local);CHKERRQ(ierr);
254   }
255   else {
256 
257     /* Get the MOAB private data */
258     ierr = DMMoabGetVecTag(vec,&vtag);CHKERRQ(ierr);
259 
260     /* Get the array data for local entities */
261     merr = dmmoab->mbiface->tag_iterate(vtag,dmmoab->vlocal->begin(),dmmoab->vlocal->end(),count,reinterpret_cast<void*&>(marray),false);MBERRNM(merr);
262     if (count!=dmmoab->nloc+dmmoab->nghost) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mismatch between local vertices and tag partition for Vec. %D != %D.",count,dmmoab->nloc+dmmoab->nghost);
263 
264     i=0;
265     for(moab::Range::iterator iter = dmmoab->vlocal->begin(); iter != dmmoab->vlocal->end(); iter++) {
266       for (f=0;f<dmmoab->numFields;f++,i++)
267       marray[i] = (*varray)[dmmoab->lidmap[(PetscInt)*iter]*dmmoab->numFields+f];
268     }
269 
270     /* reduce the tags correctly -> should probably let the user choose how to reduce in the future
271       For all FEM residual based assembly calculations, MPI_SUM should serve well */
272     merr = dmmoab->pcomm->reduce_tags(vtag,MPI_SUM,*dmmoab->vlocal);MBERRV(dmmoab->mbiface,merr);
273 
274     ierr = PetscFree(*varray);CHKERRQ(ierr);
275   }
276   PetscFunctionReturn(0);
277 }
278 
279 /*@C
280   DMMoabVecGetArrayRead - Returns the read-only direct access array to the local representation of MOAB tag data for the underlying vector using locally owned+ghosted range of entities
281 
282   Collective on MPI_Comm
283 
284   Input Parameter:
285 + dm              - The DMMoab object being set
286 . vec             - The Vector whose underlying data is requested
287 
288   Output Parameter:
289 . array           - The local data array
290 
291   Level: intermediate
292 
293 .keywords: MOAB, distributed array
294 
295 .seealso: DMMoabVecRestoreArrayRead(), DMMoabVecGetArray(), DMMoabVecRestoreArray()
296 @*/
297 PetscErrorCode  DMMoabVecGetArrayRead(DM dm,Vec vec,void* array)
298 {
299   DM_Moab        *dmmoab;
300   moab::ErrorCode merr;
301   PetscErrorCode  ierr;
302   PetscInt        count,i,f;
303   moab::Tag       vtag;
304   PetscScalar     **varray;
305   PetscScalar     *marray;
306   PetscContainer  moabdata;
307   Vec_MOAB        *vmoab,*xmoab;
308 
309   PetscFunctionBegin;
310   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
311   PetscValidHeaderSpecific(vec,VEC_CLASSID,2);
312   PetscValidPointer(array,3);
313   dmmoab=(DM_Moab*)dm->data;
314 
315   /* Get the Vec_MOAB struct for the original vector */
316   ierr = PetscObjectQuery((PetscObject)vec,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
317   ierr = PetscContainerGetPointer(moabdata, (void**)&vmoab);CHKERRQ(ierr);
318 
319   /* Get the real scalar array handle */
320   varray = reinterpret_cast<PetscScalar**>(array);
321 
322   if (vmoab->is_native_vec) {
323     /* get the local representation of the arrays from Vectors */
324     ierr = DMGetLocalVector(dm,&vmoab->local);CHKERRQ(ierr);
325     ierr = DMGlobalToLocalBegin(dm,vec,INSERT_VALUES,vmoab->local);CHKERRQ(ierr);
326     ierr = DMGlobalToLocalEnd(dm,vec,INSERT_VALUES,vmoab->local);CHKERRQ(ierr);
327 
328     /* Get the Vec_MOAB struct for the original vector */
329     ierr = PetscObjectQuery((PetscObject)vmoab->local,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
330     ierr = PetscContainerGetPointer(moabdata, (void**)&xmoab);CHKERRQ(ierr);
331 
332     /* get the local representation of the arrays from Vectors */
333     ierr = VecGhostGetLocalForm(vmoab->local,&xmoab->local);CHKERRQ(ierr);
334     ierr = VecGhostUpdateBegin(vmoab->local,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
335     ierr = VecGhostUpdateEnd(vmoab->local,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
336     ierr = VecGetArray(xmoab->local, varray);CHKERRQ(ierr);
337   }
338   else {
339     /* Get the MOAB private data */
340     ierr = DMMoabGetVecTag(vec,&vtag);CHKERRQ(ierr);
341 
342     /* exchange the data into ghost cells first */
343     merr = dmmoab->pcomm->exchange_tags(vtag,*dmmoab->vlocal);MBERRNM(merr);
344 
345     ierr = PetscMalloc1((dmmoab->nloc+dmmoab->nghost)*dmmoab->numFields,varray);CHKERRQ(ierr);
346 
347     /* Get the array data for local entities */
348     merr = dmmoab->mbiface->tag_iterate(vtag,dmmoab->vlocal->begin(),dmmoab->vlocal->end(),count,reinterpret_cast<void*&>(marray),false);MBERRNM(merr);
349     if (count!=dmmoab->nloc+dmmoab->nghost) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mismatch between local vertices and tag partition for Vec. %D != %D.",count,dmmoab->nloc+dmmoab->nghost);
350 
351     i=0;
352     for(moab::Range::iterator iter = dmmoab->vlocal->begin(); iter != dmmoab->vlocal->end(); iter++) {
353       for (f=0;f<dmmoab->numFields;f++,i++)
354         (*varray)[dmmoab->lidmap[(PetscInt)*iter]*dmmoab->numFields+f]=marray[i];
355     }
356   }
357   PetscFunctionReturn(0);
358 }
359 
360 
361 /*@C
362   DMMoabVecRestoreArray - Restores the read-only direct access array obtained via DMMoabVecGetArray
363 
364   Collective on MPI_Comm
365 
366   Input Parameter:
367 + dm              - The DMMoab object being set
368 . vec             - The Vector whose underlying data is requested
369 . array           - The local data array
370 
371   Level: intermediate
372 
373 .keywords: MOAB, distributed array
374 
375 .seealso: DMMoabVecGetArrayRead(), DMMoabVecGetArray(), DMMoabVecRestoreArray()
376 @*/
377 PetscErrorCode  DMMoabVecRestoreArrayRead(DM dm,Vec vec,void* array)
378 {
379   PetscErrorCode  ierr;
380   PetscScalar     **varray;
381   PetscContainer  moabdata;
382   Vec_MOAB        *vmoab,*xmoab;
383 
384   PetscFunctionBegin;
385   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
386   PetscValidHeaderSpecific(vec,VEC_CLASSID,2);
387   PetscValidPointer(array,3);
388 
389   /* Get the Vec_MOAB struct for the original vector */
390   ierr = PetscObjectQuery((PetscObject)vec,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
391   ierr = PetscContainerGetPointer(moabdata, (void**)&vmoab);CHKERRQ(ierr);
392 
393   /* Get the real scalar array handle */
394   varray = reinterpret_cast<PetscScalar**>(array);
395 
396   if (vmoab->is_native_vec) {
397     /* Get the Vec_MOAB struct for the original vector */
398     ierr = PetscObjectQuery((PetscObject)vmoab->local,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
399     ierr = PetscContainerGetPointer(moabdata, (void**)&xmoab);CHKERRQ(ierr);
400 
401     /* restore the local representation of the arrays from Vectors */
402     ierr = VecRestoreArray(xmoab->local, varray);CHKERRQ(ierr);
403     ierr = VecGhostRestoreLocalForm(vmoab->local,&xmoab->local);CHKERRQ(ierr);
404 
405     /* restore local pieces */
406     ierr = DMRestoreLocalVector(dm, &vmoab->local);CHKERRQ(ierr);
407   }
408   else {
409     /* Nothing to do but just free the memory allocated before */
410     ierr = PetscFree(*varray);CHKERRQ(ierr);
411 
412   }
413   PetscFunctionReturn(0);
414 }
415 
416 
417 PetscErrorCode DMCreateVector_Moab_Private(DM dm,moab::Tag tag,const moab::Range* userrange,PetscBool is_global_vec,PetscBool destroy_tag,Vec *vec)
418 {
419   PetscErrorCode    ierr;
420   moab::ErrorCode   merr;
421   PetscBool         is_newtag;
422   const moab::Range *range;
423   PetscInt          count,lnative_vec,gnative_vec;
424   std::string       ttname;
425   PetscScalar       *data_ptr,*defaultvals;
426 
427   Vec_MOAB *vmoab;
428   DM_Moab *dmmoab = (DM_Moab*)dm->data;
429   moab::ParallelComm *pcomm = dmmoab->pcomm;
430   moab::Interface *mbiface = dmmoab->mbiface;
431 
432   PetscFunctionBegin;
433   if(sizeof(PetscReal) != sizeof(PetscScalar)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "MOAB tags only support Real types (Complex-type unsupported)");
434   if(!userrange) range = dmmoab->vowned;
435   else range = userrange;
436   if(!range) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Input range cannot be empty or call DMSetUp first.");
437 
438   /* If the tag data is in a single sequence, use PETSc native vector since tag_iterate isn't useful anymore */
439   lnative_vec=(range->psize()-1);
440 
441 #if 0
442 //  lnative_vec=1; /* NOTE: Testing PETSc vector: will force to create native vector all the time */
443 //  lnative_vec=0; /* NOTE: Testing MOAB vector: will force to create MOAB tag_iterate based vector all the time */
444 #endif
445   ierr = MPIU_Allreduce(&lnative_vec, &gnative_vec, 1, MPI_INT, MPI_MAX, pcomm->comm());CHKERRQ(ierr);
446 
447   /* Create the MOAB internal data object */
448   ierr = PetscNew(&vmoab);CHKERRQ(ierr);
449   vmoab->is_native_vec=(gnative_vec>0?PETSC_TRUE:PETSC_FALSE);
450 
451   if (!vmoab->is_native_vec) {
452     merr = mbiface->tag_get_name(tag, ttname);
453     if (!ttname.length() && merr !=moab::MB_SUCCESS) {
454       /* get the new name for the anonymous MOABVec -> the tag_name will be destroyed along with Tag */
455       char *tag_name = NULL;
456       ierr = DMVecCreateTagName_Moab_Private(pcomm,&tag_name);CHKERRQ(ierr);
457       is_newtag = PETSC_TRUE;
458 
459       /* Create the default value for the tag (all zeros) */
460       ierr = PetscCalloc1(dmmoab->numFields,&defaultvals);CHKERRQ(ierr);
461 
462       /* Create the tag */
463       merr = mbiface->tag_get_handle(tag_name,dmmoab->numFields,moab::MB_TYPE_DOUBLE,tag,
464                                     moab::MB_TAG_DENSE|moab::MB_TAG_CREAT,defaultvals);MBERRNM(merr);
465       ierr = PetscFree(tag_name);CHKERRQ(ierr);
466       ierr = PetscFree(defaultvals);CHKERRQ(ierr);
467     }
468     else {
469       /* Make sure the tag data is of type "double" */
470       moab::DataType tag_type;
471       merr = mbiface->tag_get_data_type(tag, tag_type);MBERRNM(merr);
472       if(tag_type != moab::MB_TYPE_DOUBLE) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Tag data type must be MB_TYPE_DOUBLE");
473       is_newtag = destroy_tag;
474     }
475 
476     vmoab->tag = tag;
477     vmoab->new_tag = is_newtag;
478   }
479   vmoab->mbiface = mbiface;
480   vmoab->pcomm = pcomm;
481   vmoab->is_global_vec = is_global_vec;
482   vmoab->tag_size=dmmoab->bs;
483 
484   if (vmoab->is_native_vec) {
485 
486     /* Create the PETSc Vector directly and attach our functions accordingly */
487     if (!is_global_vec) {
488       /* This is an MPI Vector with ghosted padding */
489       ierr = VecCreateGhostBlock(pcomm->comm(),dmmoab->bs,dmmoab->numFields*dmmoab->nloc,
490                                  dmmoab->numFields*dmmoab->n,dmmoab->nghost,&dmmoab->gsindices[dmmoab->nloc],vec);CHKERRQ(ierr);
491     }
492     else {
493       /* This is an MPI/SEQ Vector */
494       ierr = VecCreate(pcomm->comm(),vec);CHKERRQ(ierr);
495       ierr = VecSetSizes(*vec,dmmoab->numFields*dmmoab->nloc,PETSC_DECIDE);CHKERRQ(ierr);
496       ierr = VecSetBlockSize(*vec,dmmoab->bs);CHKERRQ(ierr);
497       ierr = VecSetType(*vec, VECMPI);CHKERRQ(ierr);
498     }
499   }
500   else {
501     /* Call tag_iterate. This will cause MOAB to allocate memory for the
502        tag data if it hasn't already happened */
503     merr = mbiface->tag_iterate(tag,range->begin(),range->end(),count,(void*&)data_ptr);MBERRNM(merr);
504 
505     /* set the reference for vector range */
506     vmoab->tag_range = new moab::Range(*range);
507     merr = mbiface->tag_get_length(tag,dmmoab->numFields);MBERRNM(merr);
508 
509     /* Create the PETSc Vector
510       Query MOAB mesh to check if there are any ghosted entities
511         -> if we do, create a ghosted vector to map correctly to the same layout
512         -> else, create a non-ghosted parallel vector */
513     if (!is_global_vec) {
514       /* This is an MPI Vector with ghosted padding */
515       ierr = VecCreateGhostBlockWithArray(pcomm->comm(),dmmoab->bs,dmmoab->numFields*dmmoab->nloc,
516                                 dmmoab->numFields*dmmoab->n,dmmoab->nghost,&dmmoab->gsindices[dmmoab->nloc],data_ptr,vec);CHKERRQ(ierr);
517     }
518     else {
519       /* This is an MPI Vector without ghosted padding */
520       ierr = VecCreateMPIWithArray(pcomm->comm(),dmmoab->bs,dmmoab->numFields*range->size(),
521                                 PETSC_DECIDE,data_ptr,vec);CHKERRQ(ierr);
522     }
523   }
524   ierr = VecSetFromOptions(*vec);CHKERRQ(ierr);
525 
526   /* create a container and store the internal MOAB data for faster access based on Entities etc */
527   PetscContainer moabdata;
528   ierr = PetscContainerCreate(PETSC_COMM_WORLD,&moabdata);CHKERRQ(ierr);
529   ierr = PetscContainerSetPointer(moabdata,vmoab);CHKERRQ(ierr);
530   ierr = PetscContainerSetUserDestroy(moabdata,DMVecUserDestroy_Moab);CHKERRQ(ierr);
531   ierr = PetscObjectCompose((PetscObject)*vec,"MOABData",(PetscObject)moabdata);CHKERRQ(ierr);
532   (*vec)->ops->duplicate = DMVecDuplicate_Moab;
533   ierr = PetscContainerDestroy(&moabdata);CHKERRQ(ierr);
534 
535   /* Vector created, manually set local to global mapping */
536   if (dmmoab->ltog_map) {
537     ierr = VecSetLocalToGlobalMapping(*vec,dmmoab->ltog_map);CHKERRQ(ierr);
538   }
539 
540   /* set the DM reference to the vector */
541   ierr = VecSetDM(*vec, dm);CHKERRQ(ierr);
542   PetscFunctionReturn(0);
543 }
544 
545 
546 /*  DMVecCreateTagName_Moab_Private
547  *
548  *  Creates a unique tag name that will be shared across processes. If
549  *  pcomm is NULL, then this is a serial vector. A unique tag name
550  *  will be returned in tag_name in either case.
551  *
552  *  The tag names have the format _PETSC_VEC_N where N is some integer.
553  *
554  *  NOTE: The tag_name is allocated in this routine; The user needs to free
555  *        the character array.
556  */
557 PetscErrorCode DMVecCreateTagName_Moab_Private(moab::ParallelComm *pcomm,char** tag_name)
558 {
559   moab::ErrorCode mberr;
560   PetscErrorCode  ierr;
561   PetscInt        n,global_n;
562   moab::Tag indexTag;
563 
564   PetscFunctionBegin;
565   const char*       PVEC_PREFIX      = "__PETSC_VEC_";
566   ierr = PetscMalloc1(PETSC_MAX_PATH_LEN, tag_name);CHKERRQ(ierr);
567 
568   /* Check to see if there are any PETSc vectors defined */
569   moab::Interface  *mbiface = pcomm->get_moab();
570   moab::EntityHandle rootset = mbiface->get_root_set();
571 
572   /* Create a tag in MOAB mesh to index and keep track of number of Petsc vec tags */
573   mberr = mbiface->tag_get_handle("__PETSC_VECS__",1,moab::MB_TYPE_INTEGER,indexTag,
574                                   moab::MB_TAG_SPARSE | moab::MB_TAG_CREAT,0);MBERRNM(mberr);
575   mberr = mbiface->tag_get_data(indexTag, &rootset, 1, &n);
576   if (mberr == moab::MB_TAG_NOT_FOUND) n=0;  /* this is the first temporary vector */
577   else MBERRNM(mberr);
578 
579   /* increment the new value of n */
580   ++n;
581 
582   /* Make sure that n is consistent across all processes */
583   ierr = MPIU_Allreduce(&n,&global_n,1,MPI_INT,MPI_MAX,pcomm->comm());CHKERRQ(ierr);
584 
585   /* Set the new name accordingly and return */
586   ierr = PetscSNPrintf(*tag_name, PETSC_MAX_PATH_LEN-1, "%s_%D", PVEC_PREFIX, global_n);CHKERRQ(ierr);
587   mberr = mbiface->tag_set_data(indexTag, &rootset, 1, (const void*)&global_n);MBERRNM(mberr);
588   PetscFunctionReturn(0);
589 }
590 
591 
592 PetscErrorCode DMCreateGlobalVector_Moab(DM dm,Vec *gvec)
593 {
594   PetscErrorCode  ierr;
595   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
596 
597   PetscFunctionBegin;
598   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
599   PetscValidPointer(gvec,2);
600   ierr = DMCreateVector_Moab_Private(dm,NULL,dmmoab->vowned,PETSC_TRUE,PETSC_TRUE,gvec);CHKERRQ(ierr);
601   PetscFunctionReturn(0);
602 }
603 
604 
605 PetscErrorCode DMCreateLocalVector_Moab(DM dm,Vec *lvec)
606 {
607   PetscErrorCode  ierr;
608   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
609 
610   PetscFunctionBegin;
611   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
612   PetscValidPointer(lvec,2);
613   ierr = DMCreateVector_Moab_Private(dm,NULL,dmmoab->vlocal,PETSC_FALSE,PETSC_TRUE,lvec);CHKERRQ(ierr);
614   PetscFunctionReturn(0);
615 }
616 
617 
618 PetscErrorCode DMVecDuplicate_Moab(Vec x,Vec *y)
619 {
620   PetscErrorCode ierr;
621   DM             dm;
622   PetscContainer  moabdata;
623   Vec_MOAB        *vmoab;
624 
625   PetscFunctionBegin;
626   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
627   PetscValidPointer(y,2);
628 
629   /* Get the Vec_MOAB struct for the original vector */
630   ierr = PetscObjectQuery((PetscObject)x,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr);
631   ierr = PetscContainerGetPointer(moabdata, (void**)&vmoab);CHKERRQ(ierr);
632 
633   ierr = VecGetDM(x, &dm);CHKERRQ(ierr);
634   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
635 
636   ierr = DMCreateVector_Moab_Private(dm,NULL,vmoab->tag_range,vmoab->is_global_vec,PETSC_TRUE,y);CHKERRQ(ierr);
637   ierr = VecSetDM(*y, dm);CHKERRQ(ierr);
638   PetscFunctionReturn(0);
639 }
640 
641 
642 PetscErrorCode DMVecUserDestroy_Moab(void *user)
643 {
644   Vec_MOAB        *vmoab=(Vec_MOAB*)user;
645   PetscErrorCode  ierr;
646   moab::ErrorCode merr;
647 
648   PetscFunctionBegin;
649   if(vmoab->new_tag && vmoab->tag) {
650     /* Tag was created via a call to VecDuplicate, delete the underlying tag in MOAB */
651     merr = vmoab->mbiface->tag_delete(vmoab->tag);MBERRNM(merr);
652   }
653   delete vmoab->tag_range;
654   vmoab->tag = NULL;
655   vmoab->mbiface = NULL;
656   vmoab->pcomm = NULL;
657   ierr = PetscFree(vmoab);CHKERRQ(ierr);
658   PetscFunctionReturn(0);
659 }
660 
661 
662 PetscErrorCode  DMGlobalToLocalBegin_Moab(DM dm,Vec g,InsertMode mode,Vec l)
663 {
664   PetscErrorCode    ierr;
665   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
666 
667   PetscFunctionBegin;
668   ierr = VecScatterBegin(dmmoab->ltog_sendrecv,g,l,mode,SCATTER_REVERSE);CHKERRQ(ierr);
669   PetscFunctionReturn(0);
670 }
671 
672 
673 PetscErrorCode  DMGlobalToLocalEnd_Moab(DM dm,Vec g,InsertMode mode,Vec l)
674 {
675   PetscErrorCode    ierr;
676   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
677 
678   PetscFunctionBegin;
679   ierr = VecScatterEnd(dmmoab->ltog_sendrecv,g,l,mode,SCATTER_REVERSE);CHKERRQ(ierr);
680   PetscFunctionReturn(0);
681 }
682 
683 
684 PetscErrorCode  DMLocalToGlobalBegin_Moab(DM dm,Vec l,InsertMode mode,Vec g)
685 {
686   PetscErrorCode    ierr;
687   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
688 
689   PetscFunctionBegin;
690   ierr = VecScatterBegin(dmmoab->ltog_sendrecv,l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr);
691   PetscFunctionReturn(0);
692 }
693 
694 
695 PetscErrorCode  DMLocalToGlobalEnd_Moab(DM dm,Vec l,InsertMode mode,Vec g)
696 {
697   PetscErrorCode    ierr;
698   DM_Moab         *dmmoab = (DM_Moab*)dm->data;
699 
700   PetscFunctionBegin;
701   ierr = VecScatterEnd(dmmoab->ltog_sendrecv,l,g,mode,SCATTER_FORWARD);CHKERRQ(ierr);
702   PetscFunctionReturn(0);
703 }
704 
705