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