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 #include <sstream> 7 8 9 // declare for use later but before they're defined 10 static PetscErrorCode DMMoab_VecUserDestroy(void *user); 11 static PetscErrorCode DMMoab_VecDuplicate(Vec x,Vec *y); 12 static PetscErrorCode DMMoab_VecCreateTagName_Private(moab::ParallelComm *pcomm,char** tag_name); 13 14 #undef __FUNCT__ 15 #define __FUNCT__ "DMMoab_CreateVector_Private" 16 PetscErrorCode DMMoab_CreateVector_Private(DM dm,moab::Tag tag,PetscInt tag_size,moab::Range* userrange,PetscBool is_global_vec,PetscBool destroy_tag,Vec *vec) 17 { 18 PetscErrorCode ierr; 19 moab::ErrorCode merr; 20 PetscBool is_newtag; 21 moab::Range *range; 22 PetscInt *gindices,*gsindices; 23 PetscInt i,count,icount,dof; 24 PetscInt size,rank; 25 PetscScalar *data_ptr; 26 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 Vec_MOAB *vmoab; 33 34 PetscFunctionBegin; 35 // if(!range) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Range cannot be empty."); 36 if(!userrange) range = dmmoab->vowned; 37 else range = userrange; 38 39 if (!tag) { 40 // get the new name for the anonymous MOABVec -> the tag_name will be destroyed along with Tag 41 char *tag_name = PETSC_NULL; 42 ierr = DMMoab_VecCreateTagName_Private(pcomm,&tag_name);CHKERRQ(ierr); 43 is_newtag = PETSC_TRUE; 44 45 // Create the default value for the tag (all zeros): 46 std::vector<PetscScalar> default_value(tag_size, 0.0); 47 48 // Create the tag: 49 merr = mbiface->tag_get_handle(tag_name,tag_size,moab::MB_TYPE_DOUBLE,tag, 50 moab::MB_TAG_DENSE|moab::MB_TAG_CREAT,default_value.data());MBERRNM(merr); 51 ierr = PetscFree(tag_name);CHKERRQ(ierr); 52 } 53 else { 54 // Make sure the tag data is of type "double": 55 moab::DataType tag_type; 56 merr = mbiface->tag_get_data_type(tag, tag_type);MBERRNM(merr); 57 if(tag_type != moab::MB_TYPE_DOUBLE) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Tag data type must be MB_TYPE_DOUBLE"); 58 is_newtag = destroy_tag; 59 } 60 61 // Create the MOAB internal data object 62 ierr = PetscNew(Vec_MOAB,&vmoab);CHKERRQ(ierr); 63 vmoab->tag = tag; 64 vmoab->mbiface = mbiface; 65 vmoab->pcomm = pcomm; 66 vmoab->new_tag = is_newtag; 67 vmoab->is_global_vec = is_global_vec; 68 merr = mbiface->tag_get_length(tag,vmoab->tag_size);MBERR("tag_get_size", merr); 69 70 // set the reference for vector range 71 vmoab->tag_range = new moab::Range(*range); 72 73 // Call tag_iterate. This will cause MOAB to allocate memory for the 74 // tag data if it hasn't already happened: 75 merr = mbiface->tag_iterate(tag,range->begin(),range->end(),count,(void*&)data_ptr);MBERRNM(merr); 76 77 // Check to make sure the tag data is in a single sequence: 78 if ((unsigned)count != range->size()) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only create MOAB Vector for single sequence"); 79 80 ierr = MPI_Comm_size(((PetscObject)dm)->comm, &size);CHKERRQ(ierr); 81 ierr = MPI_Comm_rank(((PetscObject)dm)->comm, &rank);CHKERRQ(ierr); 82 83 // VSM:: 84 // TODO: Need to query MOAB mesh to see if we have ghosted entities -> then decide accordingly whether 85 // to create a serial, parallel or ghosted vector 86 // Also assert if the tag_range has the right count accordingly. 87 // Create the PETSc Vector: 88 89 /* check if we have ghosted entities in the mesh 90 -> if we do, create a ghosted vector to map correctly to the same layout 91 -> else, create a non-ghosted parallel vector */ 92 if (!is_global_vec && (size>1) && dmmoab->nghost) { 93 moab::Range::iterator iter; 94 ierr = PetscMalloc(dmmoab->nghost*sizeof(PetscInt), &gsindices);CHKERRQ(ierr); 95 for(iter = dmmoab->vghost->begin(),icount=0; iter != dmmoab->vghost->end(); iter++) { 96 merr = mbiface->tag_get_data(ltog_tag,&(*iter),1,&dof);MBERRNM(merr); 97 // PetscPrintf(PETSC_COMM_SELF, "\n [%D] Setting ghost index for dof = %D, at count = [%D, %D] for new entry = %D", rank, dof, count, icount, dof*vmoab->tag_size); 98 gsindices[icount++] = dof; 99 } 100 // ierr = PetscPrintf(PETSC_COMM_WORLD, "\n VecCreateGhostBlockWithArray: Creating Ghost MPI vector with array: Global=%D, Local=%D, Ghosted=%D", dmmoab->n, dmmoab->nloc, dmmoab->nghost); 101 // ierr = PetscPrintf(PETSC_COMM_WORLD, "\n VecCreateGhostBlockWithArray: Creating Ghost MPI vector with array: Local=%D, Ghosted=%D", dmmoab->vowned->size(), dmmoab->vghost->size()); 102 103 // This is an MPI Vector with ghosted padding 104 ierr = VecCreateGhostBlockWithArray(vmoab->pcomm->comm(),vmoab->tag_size,vmoab->tag_size*dmmoab->nloc, 105 vmoab->tag_size*dmmoab->n,dmmoab->nghost,gsindices,data_ptr,vec);CHKERRQ(ierr); 106 107 ierr = PetscFree(gsindices);CHKERRQ(ierr); 108 } 109 else if (size>1) { 110 // This is an MPI Vector without ghosted padding 111 // ierr = PetscPrintf(PETSC_COMM_WORLD, "\n VecCreateMPIWithArray: Creating MPI vector with array"); 112 ierr = VecCreateMPIWithArray(vmoab->pcomm->comm(),vmoab->tag_size,vmoab->tag_size*range->size(), 113 PETSC_DECIDE,data_ptr,vec);CHKERRQ(ierr); 114 115 // Vector created, manually set local to global mapping: 116 // ierr = PetscMalloc(range->size()*sizeof(PetscInt)*vmoab->tag_size, &gindices);CHKERRQ(ierr); 117 // moab::Range::iterator iter; 118 // for(iter = range->begin(),count=0; iter != range->end(); iter++,count+=vmoab->tag_size) { 119 // merr = mbiface->tag_get_data(ltog_tag,&(*iter),1,&dof);MBERRNM(merr); 120 // for(i=0; i<vmoab->tag_size; ++i) 121 // gindices[count+i] = (dof)*vmoab->tag_size+i; 122 // } 123 // 124 // ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,range->size(),gindices, 125 // PETSC_COPY_VALUES,<og);CHKERRQ(ierr); 126 // ierr = VecSetLocalToGlobalMappingBlock(*vec,ltog);CHKERRQ(ierr); 127 // 128 // // Clean up: 129 // ierr = ISLocalToGlobalMappingDestroy(<og);CHKERRQ(ierr); 130 // ierr = PetscFree(gindices);CHKERRQ(ierr); 131 132 } 133 else { 134 // ierr = PetscPrintf(PETSC_COMM_WORLD, "\n VecCreateSeqWithArray: Creating Serial vector with array"); 135 136 // This is a serial vector - valid only for the single processor case since MOAB tags are always partitioned 137 // and we cannot define a Vec using the Tag array with size>1 to be of full length. 138 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,vmoab->tag_size,vmoab->tag_size*dmmoab->n,data_ptr,vec);CHKERRQ(ierr); 139 } 140 141 PetscContainer moabdata; 142 ierr = PetscContainerCreate(PETSC_COMM_SELF,&moabdata);CHKERRQ(ierr); 143 ierr = PetscContainerSetPointer(moabdata,vmoab);CHKERRQ(ierr); 144 ierr = PetscContainerSetUserDestroy(moabdata,DMMoab_VecUserDestroy);CHKERRQ(ierr); 145 ierr = PetscObjectCompose((PetscObject)*vec,"MOABData",(PetscObject)moabdata);CHKERRQ(ierr); 146 (*vec)->ops->duplicate = DMMoab_VecDuplicate; 147 ierr = PetscContainerDestroy(&moabdata);CHKERRQ(ierr); 148 149 if (!dmmoab->ltog_map) { 150 // Vector created, manually set local to global mapping: 151 ierr = PetscMalloc(range->size()*sizeof(PetscInt)*vmoab->tag_size, &gindices);CHKERRQ(ierr); 152 moab::Range::iterator iter; 153 for(iter = range->begin(),count=0; iter != range->end(); iter++,count+=vmoab->tag_size) { 154 merr = mbiface->tag_get_data(ltog_tag,&(*iter),1,&dof);MBERRNM(merr); 155 for(i=0; i<vmoab->tag_size; ++i) 156 gindices[count+i] = (dof)*vmoab->tag_size+i; 157 } 158 159 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,range->size(),gindices, 160 PETSC_COPY_VALUES,&dmmoab->ltog_map);CHKERRQ(ierr); 161 162 ierr = VecSetLocalToGlobalMappingBlock(*vec,dmmoab->ltog_map);CHKERRQ(ierr); 163 164 // Clean up: 165 ierr = PetscFree(gindices);CHKERRQ(ierr); 166 } 167 else { 168 ierr = VecSetLocalToGlobalMappingBlock(*vec,dmmoab->ltog_map);CHKERRQ(ierr); 169 } 170 171 /* set the DM reference to the vector */ 172 ierr = VecSetDM(*vec, dm);CHKERRQ(ierr); 173 PetscFunctionReturn(0); 174 } 175 176 177 #undef __FUNCT__ 178 #define __FUNCT__ "DMMoabCreateVector" 179 /*@ 180 DMMoabCreateVector - Create a Vec from either an existing tag, or a specified tag size, and a range of entities 181 182 Collective on MPI_Comm 183 184 Input Parameter: 185 . dm - The DMMoab object being set 186 . tag - If non-zero, block size will be taken from the tag size 187 . tag_size - If tag was zero, this parameter specifies the block size; unique tag name will be generated automatically 188 . range - If non-empty, Vec corresponds to these entities, otherwise to the entities set on the DMMoab 189 . is_global_vec - If true, this is a local representation of the Vec (including ghosts in parallel), otherwise a truly parallel one 190 . destroy_tag - If true, MOAB tag is destroyed with Vec, otherwise it is left on MOAB 191 192 Output Parameter: 193 . vec - The created vector 194 195 Level: beginner 196 197 .keywords: DMMoab, create 198 @*/ 199 PetscErrorCode DMMoabCreateVector(DM dm,moab::Tag tag,PetscInt tag_size,moab::Range* range,PetscBool is_global_vec,PetscBool destroy_tag,Vec *vec) 200 { 201 PetscErrorCode ierr; 202 203 PetscFunctionBegin; 204 if(!tag && !tag_size) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Both tag_size and tag cannot be null."); 205 206 ierr = DMMoab_CreateVector_Private(dm,tag,tag_size,range,is_global_vec,destroy_tag,vec);CHKERRQ(ierr); 207 PetscFunctionReturn(0); 208 } 209 210 211 #undef __FUNCT__ 212 #define __FUNCT__ "DMCreateGlobalVector_Moab" 213 PetscErrorCode DMCreateGlobalVector_Moab(DM dm,Vec *gvec) 214 { 215 PetscErrorCode ierr; 216 DM_Moab *dmmoab = (DM_Moab*)dm->data; 217 218 PetscFunctionBegin; 219 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 220 PetscValidPointer(gvec,2); 221 ierr = DMMoab_CreateVector_Private(dm,PETSC_NULL,dmmoab->bs,dmmoab->vowned,PETSC_TRUE,PETSC_TRUE,gvec);CHKERRQ(ierr); 222 PetscFunctionReturn(0); 223 } 224 225 226 #undef __FUNCT__ 227 #define __FUNCT__ "DMCreateLocalVector_Moab" 228 PetscErrorCode DMCreateLocalVector_Moab(DM dm,Vec *lvec) 229 { 230 PetscErrorCode ierr; 231 moab::Range vlocal; 232 DM_Moab *dmmoab = (DM_Moab*)dm->data; 233 234 PetscFunctionBegin; 235 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 236 PetscValidPointer(lvec,2); 237 vlocal = *dmmoab->vowned; 238 vlocal.merge(*dmmoab->vghost); 239 ierr = DMMoab_CreateVector_Private(dm,PETSC_NULL,dmmoab->bs,dmmoab->vowned,PETSC_FALSE,PETSC_TRUE,lvec);CHKERRQ(ierr); 240 PetscFunctionReturn(0); 241 } 242 243 244 #undef __FUNCT__ 245 #define __FUNCT__ "DMMoabGetVecTag" 246 /*@ 247 DMMoabGetVecTag - Get the MOAB tag associated with this Vec 248 249 Collective on MPI_Comm 250 251 Input Parameter: 252 . vec - Vec being queried 253 254 Output Parameter: 255 . tag - Tag associated with this Vec 256 257 Level: beginner 258 259 .keywords: DMMoab, create 260 @*/ 261 PetscErrorCode DMMoabGetVecTag(Vec vec,moab::Tag *tag) 262 { 263 PetscContainer moabdata; 264 Vec_MOAB *vmoab; 265 PetscErrorCode ierr; 266 267 PetscFunctionBegin; 268 PetscValidPointer(tag,2); 269 270 // Get the MOAB private data: 271 ierr = PetscObjectQuery((PetscObject)vec,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr); 272 ierr = PetscContainerGetPointer(moabdata, (void**) &vmoab);CHKERRQ(ierr); 273 274 *tag = vmoab->tag; 275 PetscFunctionReturn(0); 276 } 277 278 279 #undef __FUNCT__ 280 #define __FUNCT__ "DMMoabGetVecRange" 281 /*@ 282 DMMoabGetVecRange - Get the MOAB entities associated with this Vec 283 284 Collective on MPI_Comm 285 286 Input Parameter: 287 . vec - Vec being queried 288 289 Output Parameter: 290 . range - Entities associated with this Vec 291 292 Level: beginner 293 294 .keywords: DMMoab, create 295 @*/ 296 PetscErrorCode DMMoabGetVecRange(Vec vec,moab::Range *range) 297 { 298 PetscContainer moabdata; 299 Vec_MOAB *vmoab; 300 PetscErrorCode ierr; 301 302 PetscFunctionBegin; 303 PetscValidPointer(range,2); 304 305 // Get the MOAB private data handle 306 ierr = PetscObjectQuery((PetscObject)vec,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr); 307 ierr = PetscContainerGetPointer(moabdata, (void**) &vmoab);CHKERRQ(ierr); 308 309 *range = *vmoab->tag_range; 310 PetscFunctionReturn(0); 311 } 312 313 314 #undef __FUNCT__ 315 #define __FUNCT__ "DMMoab_VecDuplicate" 316 PetscErrorCode DMMoab_VecDuplicate(Vec x,Vec *y) 317 { 318 PetscErrorCode ierr; 319 DM dm; 320 PetscContainer moabdata; 321 Vec_MOAB *vmoab; 322 // DM_Moab *dmmoab; 323 324 PetscFunctionBegin; 325 PetscValidHeaderSpecific(x,VEC_CLASSID,1); 326 PetscValidPointer(y,2); 327 328 // Get the Vec_MOAB struct for the original vector 329 ierr = PetscObjectQuery((PetscObject)x,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr); 330 ierr = PetscContainerGetPointer(moabdata, (void**)&vmoab);CHKERRQ(ierr); 331 332 ierr = VecGetDM(x, &dm);CHKERRQ(ierr); 333 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 334 // dmmoab = (DM_Moab*)dm->data; 335 336 ierr = DMMoab_CreateVector_Private(dm,PETSC_NULL,vmoab->tag_size,vmoab->tag_range,vmoab->is_global_vec,PETSC_TRUE,y);CHKERRQ(ierr); 337 // ierr = DMMoabCreateVector(dm,PETSC_NULL,dmmoab->bs,dmmoab->vowned,vmoab->is_global_vec,PETSC_TRUE,y);CHKERRQ(ierr); 338 339 // ierr = DMMoabCreateVector(dm,PETSC_NULL,vmoab->tag_size,vmoab->tag_range,vmoab->is_global_vec,PETSC_TRUE,y);CHKERRQ(ierr); 340 341 ierr = VecSetDM(*y, dm);CHKERRQ(ierr); 342 343 // ierr = PetscObjectQuery((PetscObject)*y,"MOABData", (PetscObject*) &moabdata);CHKERRQ(ierr); 344 // ierr = PetscContainerGetPointer(moabdata, (void**)&vmoab);CHKERRQ(ierr); 345 // PetscPrintf(PETSC_COMM_WORLD, "\n In VecDuplicate: new tag range pointer = %u \n", vmoab->tag_range); 346 // vmoab->tag_range->print("test"); 347 348 PetscFunctionReturn(0); 349 } 350 351 352 #undef __FUNCT__ 353 #define __FUNCT__ "DMMoab_VecCreateTagName_Private" 354 /* DMMoab_VecCreateTagName_Private 355 * 356 * Creates a unique tag name that will be shared across processes. If 357 * pcomm is NULL, then this is a serial vector. A unique tag name 358 * will be returned in tag_name in either case. 359 * 360 * The tag names have the format _PETSC_VEC_N where N is some integer. 361 * 362 * NOTE: The tag_name is allocated in this routine; The user needs to free 363 * the character array. 364 */ 365 PetscErrorCode DMMoab_VecCreateTagName_Private(moab::ParallelComm *pcomm,char** tag_name) 366 { 367 moab::ErrorCode mberr; 368 PetscErrorCode ierr; 369 PetscInt n,global_n; 370 moab::Tag indexTag; 371 372 PetscFunctionBegin; 373 const char* PVEC_PREFIX = "__PETSC_VEC_"; 374 ierr = PetscMalloc(PETSC_MAX_PATH_LEN, tag_name);CHKERRQ(ierr); 375 376 // Check to see if there are any PETSc vectors defined: 377 moab::Interface *mbiface = pcomm->get_moab(); 378 moab::EntityHandle rootset = mbiface->get_root_set(); 379 380 // Create a tag in MOAB mesh to index and keep track of number of Petsc vec tags 381 mberr = mbiface->tag_get_handle("__PETSC_VECS__",1,moab::MB_TYPE_INTEGER,indexTag, 382 moab::MB_TAG_SPARSE | moab::MB_TAG_CREAT,0);MBERRNM(mberr); 383 mberr = mbiface->tag_get_data(indexTag, &rootset, 1, &n); 384 if (mberr == moab::MB_TAG_NOT_FOUND) n=0; /* this is the first temporary vector */ 385 else MBERRNM(mberr); 386 387 /* increment the new value of n */ 388 ++n; 389 390 // Make sure that n is consistent across all processes: 391 ierr = MPI_Allreduce(&n,&global_n,1,MPI_INT,MPI_MAX,pcomm->comm());CHKERRQ(ierr); 392 393 // Set the new name accordingly and return: 394 ierr = PetscSNPrintf(*tag_name, PETSC_MAX_PATH_LEN-1, "%s_%D", PVEC_PREFIX, global_n);CHKERRQ(ierr); 395 mberr = mbiface->tag_set_data(indexTag, &rootset, 1, (const void*)&global_n);MBERRNM(mberr); 396 // ierr = PetscSNPrintf(*tag_name, PETSC_MAX_PATH_LEN-1, "%s_%D", PVEC_PREFIX, n);CHKERRQ(ierr); 397 // mberr = mbiface->tag_set_data(indexTag, &rootset, 1, &n);MBERRNM(mberr); 398 PetscFunctionReturn(0); 399 } 400 401 402 #undef __FUNCT__ 403 #define __FUNCT__ "DMMoab_VecUserDestroy" 404 PetscErrorCode DMMoab_VecUserDestroy(void *user) 405 { 406 Vec_MOAB *vmoab; 407 PetscErrorCode ierr; 408 moab::ErrorCode merr; 409 410 PetscFunctionBegin; 411 vmoab = (Vec_MOAB*)user; 412 413 if(vmoab->new_tag && vmoab->tag) { 414 // Tag created via a call to VecDuplicate, delete the underlying tag in MOAB... 415 merr = vmoab->mbiface->tag_delete(vmoab->tag);MBERRNM(merr); 416 } 417 delete vmoab->tag_range; 418 vmoab->tag = PETSC_NULL; 419 vmoab->mbiface = PETSC_NULL; 420 vmoab->pcomm = PETSC_NULL; 421 ierr = PetscFree(vmoab);CHKERRQ(ierr); 422 PetscFunctionReturn(0); 423 } 424 425