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