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