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