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