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