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