1 #include <petsc-private/dmmbimpl.h> /*I "petscdmmoab.h" I*/ 2 3 #include <petscdmmoab.h> 4 #include <MBTagConventions.hpp> 5 #include <moab/Skinner.hpp> 6 7 8 /*MC 9 DMMOAB = "moab" - A DM object that encapsulates an unstructured mesh described by the MOAB mesh database. 10 Direct access to the MOAB Interface and other mesh manipulation related objects are available 11 through public API. Ability to create global and local representation of Vecs containing all 12 unknowns in the interior and shared boundary via a transparent tag-data wrapper is provided 13 along with utility functions to traverse the mesh and assemble a discrete system via 14 field-based/blocked Vec(Get/Set) methods. Input from and output to different formats are 15 available. 16 17 Reference: http://www.mcs.anl.gov/~fathom/moab-docs/html/contents.html 18 19 Level: intermediate 20 21 .seealso: DMType, DMMoabCreate(), DMCreate(), DMSetType(), DMMoabCreateMoab() 22 M*/ 23 24 25 #undef __FUNCT__ 26 #define __FUNCT__ "DMMoabCreate" 27 /*@ 28 DMMoabCreate - Creates a DMMoab object, which encapsulates a moab instance 29 30 Collective on MPI_Comm 31 32 Input Parameter: 33 . comm - The communicator for the DMMoab object 34 35 Output Parameter: 36 . dmb - The DMMoab object 37 38 Level: beginner 39 40 .keywords: DMMoab, create 41 @*/ 42 PetscErrorCode DMMoabCreate(MPI_Comm comm, DM *dmb) 43 { 44 PetscErrorCode ierr; 45 46 PetscFunctionBegin; 47 PetscValidPointer(dmb,2); 48 ierr = DMCreate(comm, dmb);CHKERRQ(ierr); 49 ierr = DMSetType(*dmb, DMMOAB);CHKERRQ(ierr); 50 PetscFunctionReturn(0); 51 } 52 53 #undef __FUNCT__ 54 #define __FUNCT__ "DMMoabCreateMoab" 55 /*@ 56 DMMoabCreate - Creates a DMMoab object, optionally from an instance and other data 57 58 Collective on MPI_Comm 59 60 Input Parameter: 61 . comm - The communicator for the DMMoab object 62 . mbiface - (ptr to) the MOAB Instance; if passed in NULL, MOAB instance is created inside PETSc, and destroyed 63 along with the DMMoab 64 . pcomm - (ptr to) a ParallelComm; if NULL, creates one internally for the whole communicator 65 . ltog_tag - A tag to use to retrieve global id for an entity; if 0, will use GLOBAL_ID_TAG_NAME/tag 66 . range - If non-NULL, contains range of entities to which DOFs will be assigned 67 68 Output Parameter: 69 . dmb - The DMMoab object 70 71 Level: intermediate 72 73 .keywords: DMMoab, create 74 @*/ 75 PetscErrorCode DMMoabCreateMoab(MPI_Comm comm, moab::Interface *mbiface, moab::ParallelComm *pcomm, moab::Tag *ltog_tag, moab::Range *range, DM *dmb) 76 { 77 PetscErrorCode ierr; 78 moab::ErrorCode merr; 79 moab::EntityHandle partnset; 80 PetscInt rank, nprocs; 81 DM_Moab *dmmoab; 82 83 PetscFunctionBegin; 84 PetscValidPointer(dmb,6); 85 ierr = DMMoabCreate(comm, dmb);CHKERRQ(ierr); 86 dmmoab = (DM_Moab*)(*dmb)->data; 87 88 if (!mbiface) { 89 dmmoab->mbiface = new moab::Core(); 90 dmmoab->icreatedinstance = PETSC_TRUE; 91 } 92 else { 93 dmmoab->mbiface = mbiface; 94 dmmoab->icreatedinstance = PETSC_FALSE; 95 } 96 97 /* by default the fileset = root set. This set stores the hierarchy of entities belonging to current DM */ 98 dmmoab->fileset=0; 99 100 if (!pcomm) { 101 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 102 ierr = MPI_Comm_size(comm, &nprocs);CHKERRQ(ierr); 103 104 /* Create root sets for each mesh. Then pass these 105 to the load_file functions to be populated. */ 106 merr = dmmoab->mbiface->create_meshset(moab::MESHSET_SET, partnset);MBERR("Creating partition set failed", merr); 107 108 /* Create the parallel communicator object with the partition handle associated with MOAB */ 109 dmmoab->pcomm = moab::ParallelComm::get_pcomm(dmmoab->mbiface, partnset, &comm); 110 } 111 else { 112 ierr = DMMoabSetParallelComm(*dmb, pcomm);CHKERRQ(ierr); 113 } 114 115 /* do the remaining initializations for DMMoab */ 116 dmmoab->bs = 1; 117 dmmoab->numFields = 1; 118 119 /* set global ID tag handle */ 120 if (ltog_tag && *ltog_tag) { 121 ierr = DMMoabSetLocalToGlobalTag(*dmb, *ltog_tag);CHKERRQ(ierr); 122 } 123 else { 124 merr = dmmoab->mbiface->tag_get_handle(GLOBAL_ID_TAG_NAME, dmmoab->ltog_tag);MBERRNM(merr); 125 if (ltog_tag) *ltog_tag = dmmoab->ltog_tag; 126 } 127 128 /* set the local range of entities (vertices) of interest */ 129 if (range) { 130 ierr = DMMoabSetLocalVertices(*dmb, range);CHKERRQ(ierr); 131 } 132 PetscFunctionReturn(0); 133 } 134 135 #undef __FUNCT__ 136 #define __FUNCT__ "DMMoabSetParallelComm" 137 /*@ 138 DMMoabSetParallelComm - Set the ParallelComm used with this DMMoab 139 140 Collective on MPI_Comm 141 142 Input Parameter: 143 . dm - The DMMoab object being set 144 . pcomm - The ParallelComm being set on the DMMoab 145 146 Level: beginner 147 148 .keywords: DMMoab, create 149 @*/ 150 PetscErrorCode DMMoabSetParallelComm(DM dm,moab::ParallelComm *pcomm) 151 { 152 DM_Moab *dmmoab = (DM_Moab*)(dm)->data; 153 154 PetscFunctionBegin; 155 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 156 PetscValidPointer(pcomm,2); 157 dmmoab->pcomm = pcomm; 158 dmmoab->mbiface = pcomm->get_moab(); 159 dmmoab->icreatedinstance = PETSC_FALSE; 160 PetscFunctionReturn(0); 161 } 162 163 164 #undef __FUNCT__ 165 #define __FUNCT__ "DMMoabGetParallelComm" 166 /*@ 167 DMMoabGetParallelComm - Get the ParallelComm used with this DMMoab 168 169 Collective on MPI_Comm 170 171 Input Parameter: 172 . dm - The DMMoab object being set 173 174 Output Parameter: 175 . pcomm - The ParallelComm for the DMMoab 176 177 Level: beginner 178 179 .keywords: DMMoab, create 180 @*/ 181 PetscErrorCode DMMoabGetParallelComm(DM dm,moab::ParallelComm **pcomm) 182 { 183 PetscFunctionBegin; 184 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 185 *pcomm = ((DM_Moab*)(dm)->data)->pcomm; 186 PetscFunctionReturn(0); 187 } 188 189 190 #undef __FUNCT__ 191 #define __FUNCT__ "DMMoabSetInterface" 192 /*@ 193 DMMoabSetInterface - Set the MOAB instance used with this DMMoab 194 195 Collective on MPI_Comm 196 197 Input Parameter: 198 . dm - The DMMoab object being set 199 . mbiface - The MOAB instance being set on this DMMoab 200 201 Level: beginner 202 203 .keywords: DMMoab, create 204 @*/ 205 PetscErrorCode DMMoabSetInterface(DM dm,moab::Interface *mbiface) 206 { 207 DM_Moab *dmmoab = (DM_Moab*)(dm)->data; 208 209 PetscFunctionBegin; 210 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 211 PetscValidPointer(mbiface,2); 212 dmmoab->pcomm = NULL; 213 dmmoab->mbiface = mbiface; 214 dmmoab->icreatedinstance = PETSC_FALSE; 215 PetscFunctionReturn(0); 216 } 217 218 219 #undef __FUNCT__ 220 #define __FUNCT__ "DMMoabGetInterface" 221 /*@ 222 DMMoabGetInterface - Get the MOAB instance used with this DMMoab 223 224 Collective on MPI_Comm 225 226 Input Parameter: 227 . dm - The DMMoab object being set 228 229 Output Parameter: 230 . mbiface - The MOAB instance set on this DMMoab 231 232 Level: beginner 233 234 .keywords: DMMoab, create 235 @*/ 236 PetscErrorCode DMMoabGetInterface(DM dm,moab::Interface **mbiface) 237 { 238 PetscErrorCode ierr; 239 static PetscBool cite = PETSC_FALSE; 240 241 PetscFunctionBegin; 242 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 243 ierr = PetscCitationsRegister("@techreport{tautges_moab:_2004,\n type = {{SAND2004-1592}},\n title = {{MOAB:} A Mesh-Oriented Database}, institution = {Sandia National Laboratories},\n author = {Tautges, T. J. and Meyers, R. and Merkley, K. and Stimpson, C. and Ernst, C.},\n year = {2004}, note = {Report}\n}\n",&cite);CHKERRQ(ierr); 244 *mbiface = ((DM_Moab*)dm->data)->mbiface; 245 PetscFunctionReturn(0); 246 } 247 248 249 #undef __FUNCT__ 250 #define __FUNCT__ "DMMoabSetLocalVertices" 251 /*@ 252 DMMoabSetLocalVertices - Set the entities having DOFs on this DMMoab 253 254 Collective on MPI_Comm 255 256 Input Parameter: 257 . dm - The DMMoab object being set 258 . range - The entities treated by this DMMoab 259 260 Level: beginner 261 262 .keywords: DMMoab, create 263 @*/ 264 PetscErrorCode DMMoabSetLocalVertices(DM dm,moab::Range *range) 265 { 266 moab::ErrorCode merr; 267 PetscErrorCode ierr; 268 moab::Range tmpvtxs; 269 DM_Moab *dmmoab = (DM_Moab*)(dm)->data; 270 271 PetscFunctionBegin; 272 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 273 dmmoab->vlocal->clear(); 274 dmmoab->vowned->clear(); 275 276 dmmoab->vlocal->insert(range->begin(), range->end()); 277 278 /* filter based on parallel status */ 279 merr = dmmoab->pcomm->filter_pstatus(*dmmoab->vlocal,PSTATUS_NOT_OWNED,PSTATUS_NOT,-1,dmmoab->vowned);MBERRNM(merr); 280 281 /* filter all the non-owned and shared entities out of the list */ 282 tmpvtxs = moab::subtract(*dmmoab->vlocal, *dmmoab->vowned); 283 merr = dmmoab->pcomm->filter_pstatus(tmpvtxs,PSTATUS_INTERFACE,PSTATUS_OR,-1,dmmoab->vghost);MBERRNM(merr); 284 tmpvtxs = moab::subtract(tmpvtxs, *dmmoab->vghost); 285 *dmmoab->vlocal = moab::subtract(*dmmoab->vlocal, tmpvtxs); 286 287 /* compute and cache the sizes of local and ghosted entities */ 288 dmmoab->nloc = dmmoab->vowned->size(); 289 dmmoab->nghost = dmmoab->vghost->size(); 290 ierr = MPI_Allreduce(&dmmoab->nloc, &dmmoab->n, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr); 291 PetscFunctionReturn(0); 292 } 293 294 295 #undef __FUNCT__ 296 #define __FUNCT__ "DMMoabGetAllVertices" 297 /*@ 298 DMMoabGetAllVertices - Get the entities having DOFs on this DMMoab 299 300 Collective on MPI_Comm 301 302 Input Parameter: 303 . dm - The DMMoab object being set 304 305 Output Parameter: 306 . owned - The local vertex entities in this DMMoab = (owned+ghosted) 307 308 Level: beginner 309 310 .keywords: DMMoab, create 311 @*/ 312 PetscErrorCode DMMoabGetAllVertices(DM dm,moab::Range *local) 313 { 314 PetscFunctionBegin; 315 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 316 if (local) *local = *((DM_Moab*)dm->data)->vlocal; 317 PetscFunctionReturn(0); 318 } 319 320 321 322 #undef __FUNCT__ 323 #define __FUNCT__ "DMMoabGetLocalVertices" 324 /*@ 325 DMMoabGetLocalVertices - Get the entities having DOFs on this DMMoab 326 327 Collective on MPI_Comm 328 329 Input Parameter: 330 . dm - The DMMoab object being set 331 332 Output Parameter: 333 . owned - The owned vertex entities in this DMMoab 334 . ghost - The ghosted entities (non-owned) stored locally in this partition 335 336 Level: beginner 337 338 .keywords: DMMoab, create 339 @*/ 340 PetscErrorCode DMMoabGetLocalVertices(DM dm,const moab::Range **owned,const moab::Range **ghost) 341 { 342 PetscFunctionBegin; 343 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 344 if (owned) *owned = ((DM_Moab*)dm->data)->vowned; 345 if (ghost) *ghost = ((DM_Moab*)dm->data)->vghost; 346 PetscFunctionReturn(0); 347 } 348 349 #undef __FUNCT__ 350 #define __FUNCT__ "DMMoabGetLocalElements" 351 /*@ 352 DMMoabGetLocalElements - Get the higher-dimensional entities that are locally owned 353 354 Collective on MPI_Comm 355 356 Input Parameter: 357 . dm - The DMMoab object being set 358 359 Output Parameter: 360 . range - The entities owned locally 361 362 Level: beginner 363 364 .keywords: DMMoab, create 365 @*/ 366 PetscErrorCode DMMoabGetLocalElements(DM dm,const moab::Range **range) 367 { 368 PetscFunctionBegin; 369 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 370 if (range) *range = ((DM_Moab*)dm->data)->elocal; 371 PetscFunctionReturn(0); 372 } 373 374 375 #undef __FUNCT__ 376 #define __FUNCT__ "DMMoabSetLocalElements" 377 /*@ 378 DMMoabSetLocalElements - Set the entities having DOFs on this DMMoab 379 380 Collective on MPI_Comm 381 382 Input Parameter: 383 . dm - The DMMoab object being set 384 . range - The entities treated by this DMMoab 385 386 Level: beginner 387 388 .keywords: DMMoab, create 389 @*/ 390 PetscErrorCode DMMoabSetLocalElements(DM dm,moab::Range *range) 391 { 392 moab::ErrorCode merr; 393 PetscErrorCode ierr; 394 DM_Moab *dmmoab = (DM_Moab*)(dm)->data; 395 396 PetscFunctionBegin; 397 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 398 dmmoab->elocal->clear(); 399 dmmoab->eghost->clear(); 400 dmmoab->elocal->insert(range->begin(), range->end()); 401 merr = dmmoab->pcomm->filter_pstatus(*dmmoab->elocal,PSTATUS_NOT_OWNED,PSTATUS_NOT);MBERRNM(merr); 402 *dmmoab->eghost = moab::subtract(*range, *dmmoab->elocal); 403 dmmoab->neleloc=dmmoab->elocal->size(); 404 dmmoab->neleghost=dmmoab->eghost->size(); 405 ierr = MPI_Allreduce(&dmmoab->nele, &dmmoab->neleloc, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr); 406 PetscInfo2(dm, "Created %D local and %D global elements.\n", dmmoab->neleloc, dmmoab->nele); 407 PetscFunctionReturn(0); 408 } 409 410 411 #undef __FUNCT__ 412 #define __FUNCT__ "DMMoabSetLocalToGlobalTag" 413 /*@ 414 DMMoabSetLocalToGlobalTag - Set the tag used for local to global numbering 415 416 Collective on MPI_Comm 417 418 Input Parameter: 419 . dm - The DMMoab object being set 420 . ltogtag - The MOAB tag used for local to global ids 421 422 Level: beginner 423 424 .keywords: DMMoab, create 425 @*/ 426 PetscErrorCode DMMoabSetLocalToGlobalTag(DM dm,moab::Tag ltogtag) 427 { 428 PetscFunctionBegin; 429 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 430 ((DM_Moab*)dm->data)->ltog_tag = ltogtag; 431 PetscFunctionReturn(0); 432 } 433 434 435 #undef __FUNCT__ 436 #define __FUNCT__ "DMMoabGetLocalToGlobalTag" 437 /*@ 438 DMMoabGetLocalToGlobalTag - Get the tag used for local to global numbering 439 440 Collective on MPI_Comm 441 442 Input Parameter: 443 . dm - The DMMoab object being set 444 445 Output Parameter: 446 . ltogtag - The MOAB tag used for local to global ids 447 448 Level: beginner 449 450 .keywords: DMMoab, create 451 @*/ 452 PetscErrorCode DMMoabGetLocalToGlobalTag(DM dm,moab::Tag *ltog_tag) 453 { 454 PetscFunctionBegin; 455 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 456 *ltog_tag = ((DM_Moab*)dm->data)->ltog_tag; 457 PetscFunctionReturn(0); 458 } 459 460 461 #undef __FUNCT__ 462 #define __FUNCT__ "DMMoabSetBlockSize" 463 /*@ 464 DMMoabSetBlockSize - Set the block size used with this DMMoab 465 466 Collective on MPI_Comm 467 468 Input Parameter: 469 . dm - The DMMoab object being set 470 . bs - The block size used with this DMMoab 471 472 Level: beginner 473 474 .keywords: DMMoab, create 475 @*/ 476 PetscErrorCode DMMoabSetBlockSize(DM dm,PetscInt bs) 477 { 478 PetscFunctionBegin; 479 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 480 ((DM_Moab*)dm->data)->bs = bs; 481 PetscFunctionReturn(0); 482 } 483 484 485 #undef __FUNCT__ 486 #define __FUNCT__ "DMMoabGetBlockSize" 487 /*@ 488 DMMoabGetBlockSize - Get the block size used with this DMMoab 489 490 Collective on MPI_Comm 491 492 Input Parameter: 493 . dm - The DMMoab object being set 494 495 Output Parameter: 496 . bs - The block size used with this DMMoab 497 498 Level: beginner 499 500 .keywords: DMMoab, create 501 @*/ 502 PetscErrorCode DMMoabGetBlockSize(DM dm,PetscInt *bs) 503 { 504 PetscFunctionBegin; 505 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 506 *bs = ((DM_Moab*)dm->data)->bs; 507 PetscFunctionReturn(0); 508 } 509 510 511 #undef __FUNCT__ 512 #define __FUNCT__ "DMMoabGetSize" 513 /*@ 514 DMMoabGetSize - Get the global vertex size used with this DMMoab 515 516 Collective on DM 517 518 Input Parameter: 519 . dm - The DMMoab object being set 520 521 Output Parameter: 522 . neg - The number of global elements in the DMMoab instance 523 . nvg - The number of global vertices in the DMMoab instance 524 525 Level: beginner 526 527 .keywords: DMMoab, create 528 @*/ 529 PetscErrorCode DMMoabGetSize(DM dm,PetscInt *neg,PetscInt *nvg) 530 { 531 PetscFunctionBegin; 532 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 533 if(neg) *neg = ((DM_Moab*)dm->data)->nele; 534 if(nvg) *nvg = ((DM_Moab*)dm->data)->n; 535 PetscFunctionReturn(0); 536 } 537 538 539 #undef __FUNCT__ 540 #define __FUNCT__ "DMMoabGetLocalSize" 541 /*@ 542 DMMoabGetLocalSize - Get the local and ghosted vertex size used with this DMMoab 543 544 Collective on DM 545 546 Input Parameter: 547 . dm - The DMMoab object being set 548 549 Output Parameter: 550 + nel - The number of owned elements in this processor 551 . neg - The number of ghosted elements in this processor 552 . nvl - The number of owned vertices in this processor 553 . nvg - The number of ghosted vertices in this processor 554 555 Level: beginner 556 557 .keywords: DMMoab, create 558 @*/ 559 PetscErrorCode DMMoabGetLocalSize(DM dm,PetscInt *nel,PetscInt *neg,PetscInt *nvl,PetscInt *nvg) 560 { 561 PetscFunctionBegin; 562 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 563 if(nel) *nel = ((DM_Moab*)dm->data)->neleloc; 564 if(neg) *neg = ((DM_Moab*)dm->data)->neleghost; 565 if(nvl) *nvl = ((DM_Moab*)dm->data)->nloc; 566 if(nvg) *nvg = ((DM_Moab*)dm->data)->nghost; 567 PetscFunctionReturn(0); 568 } 569 570 571 #undef __FUNCT__ 572 #define __FUNCT__ "DMMoabGetOffset" 573 /*@ 574 DMMoabGetOffset - Get the local offset for the global vector 575 576 Collective on MPI_Comm 577 578 Input Parameter: 579 . dm - The DMMoab object being set 580 581 Output Parameter: 582 . offset - The local offset for the global vector 583 584 Level: beginner 585 586 .keywords: DMMoab, create 587 @*/ 588 PetscErrorCode DMMoabGetOffset(DM dm,PetscInt *offset) 589 { 590 PetscFunctionBegin; 591 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 592 *offset = ((DM_Moab*)dm->data)->vstart; 593 PetscFunctionReturn(0); 594 } 595 596 597 #undef __FUNCT__ 598 #define __FUNCT__ "DMMoabGetDimension" 599 /*@ 600 DMMoabGetDimension - Get the dimension of the DM Mesh 601 602 Collective on MPI_Comm 603 604 Input Parameter: 605 . dm - The DMMoab object being set 606 607 Output Parameter: 608 . dim - The dimension of DM 609 610 Level: beginner 611 612 .keywords: DMMoab, create 613 @*/ 614 PetscErrorCode DMMoabGetDimension(DM dm,PetscInt *dim) 615 { 616 PetscFunctionBegin; 617 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 618 *dim = ((DM_Moab*)dm->data)->dim; 619 PetscFunctionReturn(0); 620 } 621 622 623 624 #undef __FUNCT__ 625 #define __FUNCT__ "DMMoabGetVertexCoordinates" 626 PetscErrorCode DMMoabGetVertexCoordinates(DM dm,PetscInt nconn,const moab::EntityHandle *conn,PetscScalar *vpos) 627 { 628 DM_Moab *dmmoab; 629 PetscErrorCode ierr; 630 moab::ErrorCode merr; 631 632 PetscFunctionBegin; 633 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 634 PetscValidPointer(conn,3); 635 dmmoab = (DM_Moab*)(dm)->data; 636 637 if (!vpos) { 638 ierr = PetscMalloc(sizeof(PetscScalar)*nconn*3, &vpos);CHKERRQ(ierr); 639 } 640 641 /* Get connectivity information in MOAB canonical ordering */ 642 merr = dmmoab->mbiface->get_coords(conn, nconn, vpos);MBERRNM(merr); 643 PetscFunctionReturn(0); 644 } 645 646 647 #undef __FUNCT__ 648 #define __FUNCT__ "DMMoabGetVertexConnectivity" 649 PetscErrorCode DMMoabGetVertexConnectivity(DM dm,moab::EntityHandle ehandle,PetscInt* nconn, moab::EntityHandle **conn) 650 { 651 DM_Moab *dmmoab; 652 std::vector<moab::EntityHandle> adj_entities,connect; 653 PetscErrorCode ierr; 654 moab::ErrorCode merr; 655 656 PetscFunctionBegin; 657 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 658 PetscValidPointer(conn,4); 659 dmmoab = (DM_Moab*)(dm)->data; 660 661 /* Get connectivity information in MOAB canonical ordering */ 662 merr = dmmoab->mbiface->get_adjacencies(&ehandle, 1, 1, true, adj_entities, moab::Interface::UNION);MBERRNM(merr); 663 merr = dmmoab->mbiface->get_connectivity(&adj_entities[0],adj_entities.size(),connect);MBERRNM(merr); 664 665 if (conn) { 666 ierr = PetscMalloc(sizeof(moab::EntityHandle)*connect.size(), conn);CHKERRQ(ierr); 667 ierr = PetscMemcpy(*conn, &connect[0], sizeof(moab::EntityHandle)*connect.size());CHKERRQ(ierr); 668 } 669 if (nconn) *nconn=connect.size(); 670 PetscFunctionReturn(0); 671 } 672 673 674 #undef __FUNCT__ 675 #define __FUNCT__ "DMMoabRestoreVertexConnectivity" 676 PetscErrorCode DMMoabRestoreVertexConnectivity(DM dm,moab::EntityHandle ehandle,PetscInt* nconn, moab::EntityHandle **conn) 677 { 678 PetscErrorCode ierr; 679 680 PetscFunctionBegin; 681 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 682 PetscValidPointer(conn,4); 683 684 if (conn) { 685 ierr = PetscFree(*conn);CHKERRQ(ierr); 686 } 687 if (nconn) *nconn=0; 688 PetscFunctionReturn(0); 689 } 690 691 692 693 #undef __FUNCT__ 694 #define __FUNCT__ "DMMoabGetElementConnectivity" 695 PetscErrorCode DMMoabGetElementConnectivity(DM dm,moab::EntityHandle ehandle,PetscInt* nconn,const moab::EntityHandle **conn) 696 { 697 DM_Moab *dmmoab; 698 const moab::EntityHandle *connect; 699 moab::ErrorCode merr; 700 PetscInt nnodes; 701 702 PetscFunctionBegin; 703 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 704 PetscValidPointer(conn,4); 705 dmmoab = (DM_Moab*)(dm)->data; 706 707 /* Get connectivity information in MOAB canonical ordering */ 708 merr = dmmoab->mbiface->get_connectivity(ehandle, connect, nnodes);MBERRNM(merr); 709 if (conn) *conn=connect; 710 if (nconn) *nconn=nnodes; 711 PetscFunctionReturn(0); 712 } 713 714 715 #undef __FUNCT__ 716 #define __FUNCT__ "DMMoabIsEntityOnBoundary" 717 PetscErrorCode DMMoabIsEntityOnBoundary(DM dm,const moab::EntityHandle ent,PetscBool* ent_on_boundary) 718 { 719 moab::EntityType etype; 720 DM_Moab *dmmoab; 721 PetscInt edim; 722 723 PetscFunctionBegin; 724 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 725 PetscValidPointer(ent_on_boundary,3); 726 dmmoab = (DM_Moab*)(dm)->data; 727 728 /* get the entity type and handle accordingly */ 729 etype=dmmoab->mbiface->type_from_handle(ent); 730 if(etype >= moab::MBPOLYHEDRON) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Entity type on the boundary skin is invalid. EntityType = %D\n",etype); 731 732 /* get the entity dimension */ 733 edim=dmmoab->mbiface->dimension_from_handle(ent); 734 735 *ent_on_boundary=PETSC_FALSE; 736 if(etype == moab::MBVERTEX && edim == 0) { 737 if (dmmoab->bndyvtx->index(ent) >= 0) *ent_on_boundary=PETSC_TRUE; 738 } 739 else { 740 if (edim == dmmoab->dim) { /* check the higher-dimensional elements first */ 741 if (dmmoab->bndyelems->index(ent) >= 0) *ent_on_boundary=PETSC_TRUE; 742 } 743 else { /* next check the lower-dimensional faces */ 744 if (dmmoab->bndyfaces->index(ent) >= 0) *ent_on_boundary=PETSC_TRUE; 745 } 746 } 747 PetscFunctionReturn(0); 748 } 749 750 751 #undef __FUNCT__ 752 #define __FUNCT__ "DMMoabCheckBoundaryVertices" 753 PetscErrorCode DMMoabCheckBoundaryVertices(DM dm,PetscInt nconn,const moab::EntityHandle *cnt,PetscBool* isbdvtx) 754 { 755 DM_Moab *dmmoab; 756 PetscInt i; 757 758 PetscFunctionBegin; 759 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 760 PetscValidPointer(cnt,3); 761 PetscValidPointer(isbdvtx,4); 762 dmmoab = (DM_Moab*)(dm)->data; 763 764 for (i=0; i < nconn; ++i) { 765 isbdvtx[i]=(dmmoab->bndyvtx->index(cnt[i]) >= 0 ? PETSC_TRUE:PETSC_FALSE); 766 } 767 PetscFunctionReturn(0); 768 } 769 770 771 #undef __FUNCT__ 772 #define __FUNCT__ "DMMoabGetBoundaryMarkers" 773 PetscErrorCode DMMoabGetBoundaryMarkers(DM dm,const moab::Range **bdvtx,const moab::Range** bdelems,const moab::Range** bdfaces) 774 { 775 DM_Moab *dmmoab; 776 777 PetscFunctionBegin; 778 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 779 dmmoab = (DM_Moab*)(dm)->data; 780 781 if (bdvtx) *bdvtx = dmmoab->bndyvtx; 782 if (bdfaces) *bdfaces = dmmoab->bndyfaces; 783 if (bdelems) *bdfaces = dmmoab->bndyelems; 784 PetscFunctionReturn(0); 785 } 786 787 788 #undef __FUNCT__ 789 #define __FUNCT__ "DMDestroy_Moab" 790 PETSC_EXTERN PetscErrorCode DMDestroy_Moab(DM dm) 791 { 792 PetscErrorCode ierr; 793 DM_Moab *dmmoab = (DM_Moab*)dm->data; 794 795 PetscFunctionBegin; 796 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 797 if (dmmoab->icreatedinstance) { 798 delete dmmoab->mbiface; 799 } 800 dmmoab->mbiface = NULL; 801 dmmoab->pcomm = NULL; 802 delete dmmoab->vlocal; 803 delete dmmoab->vowned; 804 delete dmmoab->vghost; 805 delete dmmoab->elocal; 806 delete dmmoab->eghost; 807 delete dmmoab->bndyvtx; 808 delete dmmoab->bndyfaces; 809 delete dmmoab->bndyelems; 810 811 ierr = PetscFree(dmmoab->gsindices);CHKERRQ(ierr); 812 ierr = PetscFree(dmmoab->lidmap);CHKERRQ(ierr); 813 ierr = PetscFree(dmmoab->gidmap);CHKERRQ(ierr); 814 ierr = PetscFree(dmmoab->llmap);CHKERRQ(ierr); 815 ierr = PetscFree(dmmoab->lgmap);CHKERRQ(ierr); 816 ierr = VecScatterDestroy(&dmmoab->ltog_sendrecv);CHKERRQ(ierr); 817 ierr = ISLocalToGlobalMappingDestroy(&dmmoab->ltog_map);CHKERRQ(ierr); 818 ierr = PetscFree(dm->data);CHKERRQ(ierr); 819 PetscFunctionReturn(0); 820 } 821 822 823 #undef __FUNCT__ 824 #define __FUNCT__ "DMSetUp_Moab" 825 PETSC_EXTERN PetscErrorCode DMSetUp_Moab(DM dm) 826 { 827 PetscErrorCode ierr; 828 moab::ErrorCode merr; 829 Vec local, global; 830 IS from,to; 831 moab::Range::iterator iter; 832 PetscInt i,j,f,bs,gmin,lmin,lmax,vent,totsize; 833 DM_Moab *dmmoab = (DM_Moab*)dm->data; 834 moab::Range adjs; 835 836 PetscFunctionBegin; 837 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 838 /* Get the local and shared vertices and cache it */ 839 if (dmmoab->mbiface == PETSC_NULL || dmmoab->pcomm == PETSC_NULL) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ORDER, "Set the MOAB Interface and ParallelComm objects before calling SetUp."); 840 841 /* Get the entities recursively in the current part of the mesh, if user did not set the local vertices explicitly */ 842 if (dmmoab->vlocal->empty()) 843 { 844 merr = dmmoab->mbiface->get_entities_by_type(dmmoab->fileset,moab::MBVERTEX,*dmmoab->vlocal,true);MBERRNM(merr); 845 846 /* filter based on parallel status */ 847 merr = dmmoab->pcomm->filter_pstatus(*dmmoab->vlocal,PSTATUS_NOT_OWNED,PSTATUS_NOT,-1,dmmoab->vowned);MBERRNM(merr); 848 849 /* filter all the non-owned and shared entities out of the list */ 850 adjs = moab::subtract(*dmmoab->vlocal, *dmmoab->vowned); 851 merr = dmmoab->pcomm->filter_pstatus(adjs,PSTATUS_INTERFACE,PSTATUS_OR,-1,dmmoab->vghost);MBERRNM(merr); 852 adjs = moab::subtract(adjs, *dmmoab->vghost); 853 *dmmoab->vlocal = moab::subtract(*dmmoab->vlocal, adjs); 854 855 /* compute and cache the sizes of local and ghosted entities */ 856 dmmoab->nloc = dmmoab->vowned->size(); 857 dmmoab->nghost = dmmoab->vghost->size(); 858 ierr = MPI_Allreduce(&dmmoab->nloc, &dmmoab->n, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr); 859 } 860 861 { 862 /* get the information about the local elements in the mesh */ 863 dmmoab->eghost->clear(); 864 865 /* first decipher the leading dimension */ 866 for (i=3;i>0;i--) { 867 dmmoab->elocal->clear(); 868 merr = dmmoab->mbiface->get_entities_by_dimension(dmmoab->fileset, i, *dmmoab->elocal, true);CHKERRQ(merr); 869 870 /* store the current mesh dimension */ 871 if (dmmoab->elocal->size()) { 872 dmmoab->dim=i; 873 break; 874 } 875 } 876 877 /* filter the ghosted and owned element list */ 878 *dmmoab->eghost = *dmmoab->elocal; 879 merr = dmmoab->pcomm->filter_pstatus(*dmmoab->elocal,PSTATUS_NOT_OWNED,PSTATUS_NOT);MBERRNM(merr); 880 *dmmoab->eghost = moab::subtract(*dmmoab->eghost, *dmmoab->elocal); 881 882 dmmoab->neleloc = dmmoab->elocal->size(); 883 dmmoab->neleghost = dmmoab->eghost->size(); 884 ierr = MPI_Allreduce(&dmmoab->neleloc, &dmmoab->nele, 1, MPI_INTEGER, MPI_SUM, ((PetscObject)dm)->comm);CHKERRQ(ierr); 885 } 886 887 bs = dmmoab->bs; 888 if (!dmmoab->ltog_tag) { 889 /* Get the global ID tag. The global ID tag is applied to each 890 vertex. It acts as an global identifier which MOAB uses to 891 assemble the individual pieces of the mesh */ 892 merr = dmmoab->mbiface->tag_get_handle(GLOBAL_ID_TAG_NAME, dmmoab->ltog_tag);MBERRNM(merr); 893 } 894 895 totsize=dmmoab->vlocal->size(); 896 if (totsize != dmmoab->nloc+dmmoab->nghost) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Mismatch between local and owned+ghost vertices. %D != %D.",totsize,dmmoab->nloc+dmmoab->nghost); 897 ierr = PetscMalloc(totsize*sizeof(PetscInt), &dmmoab->gsindices);CHKERRQ(ierr); 898 { 899 /* first get the local indices */ 900 merr = dmmoab->mbiface->tag_get_data(dmmoab->ltog_tag,*dmmoab->vowned,&dmmoab->gsindices[0]);MBERRNM(merr); 901 /* next get the ghosted indices */ 902 if (dmmoab->nghost) { 903 merr = dmmoab->mbiface->tag_get_data(dmmoab->ltog_tag,*dmmoab->vghost,&dmmoab->gsindices[dmmoab->nloc]);MBERRNM(merr); 904 } 905 906 /* find out the local and global minima of GLOBAL_ID */ 907 lmin=lmax=dmmoab->gsindices[0]; 908 for (i=0; i<totsize; ++i) { 909 if(lmin>dmmoab->gsindices[i]) lmin=dmmoab->gsindices[i]; 910 if(lmax<dmmoab->gsindices[i]) lmax=dmmoab->gsindices[i]; 911 } 912 913 ierr = MPI_Allreduce(&lmin, &gmin, 1, MPI_INT, MPI_MIN, ((PetscObject)dm)->comm);CHKERRQ(ierr); 914 915 /* set the GID map */ 916 for (i=0; i<totsize; ++i) { 917 dmmoab->gsindices[i]-=gmin; /* zero based index needed for IS */ 918 } 919 lmin-=gmin; 920 lmax-=gmin; 921 922 PetscInfo3(NULL, "GLOBAL_ID: Local minima - %D, Local maxima - %D, Global minima - %D.\n", lmin, lmax, gmin); 923 } 924 925 { 926 ierr = PetscMalloc(((PetscInt)(dmmoab->vlocal->back())+1)*sizeof(PetscInt), &dmmoab->gidmap);CHKERRQ(ierr); 927 ierr = PetscMalloc(((PetscInt)(dmmoab->vlocal->back())+1)*sizeof(PetscInt), &dmmoab->lidmap);CHKERRQ(ierr); 928 ierr = PetscMalloc(totsize*dmmoab->numFields*sizeof(PetscInt), &dmmoab->llmap);CHKERRQ(ierr); 929 ierr = PetscMalloc(totsize*dmmoab->numFields*sizeof(PetscInt), &dmmoab->lgmap);CHKERRQ(ierr); 930 931 i=j=0; 932 /* set the owned vertex data first */ 933 for(moab::Range::iterator iter = dmmoab->vowned->begin(); iter != dmmoab->vowned->end(); iter++,i++) { 934 vent=(PetscInt)(*iter); 935 dmmoab->gidmap[vent]=dmmoab->gsindices[i]; 936 dmmoab->lidmap[vent]=i; 937 if (bs > 1) { 938 for (f=0;f<dmmoab->numFields;f++,j++) { 939 dmmoab->lgmap[j]=dmmoab->gsindices[i]*dmmoab->numFields+f; 940 dmmoab->llmap[j]=i*dmmoab->numFields+f; 941 } 942 } 943 else { 944 for (f=0;f<dmmoab->numFields;f++,j++) { 945 dmmoab->lgmap[j]=totsize*f+dmmoab->gsindices[i]; 946 dmmoab->llmap[j]=totsize*f+i; 947 } 948 } 949 } 950 /* next arrange all the ghosted data information */ 951 for(moab::Range::iterator iter = dmmoab->vghost->begin(); iter != dmmoab->vghost->end(); iter++,i++) { 952 vent=(PetscInt)(*iter); 953 dmmoab->gidmap[vent]=dmmoab->gsindices[i]; 954 dmmoab->lidmap[vent]=i; 955 if (bs > 1) { 956 for (f=0;f<dmmoab->numFields;f++,j++) { 957 dmmoab->lgmap[j]=dmmoab->gsindices[i]*dmmoab->numFields+f; 958 dmmoab->llmap[j]=i*dmmoab->numFields+f; 959 } 960 } 961 else { 962 for (f=0;f<dmmoab->numFields;f++,j++) { 963 dmmoab->lgmap[j]=totsize*f+dmmoab->gsindices[i]; 964 dmmoab->llmap[j]=totsize*f+i; 965 } 966 } 967 } 968 969 /* We need to create the Global to Local Vector Scatter Contexts 970 1) First create a local and global vector 971 2) Create a local and global IS 972 3) Create VecScatter and LtoGMapping objects 973 4) Cleanup the IS and Vec objects 974 */ 975 ierr = DMCreateGlobalVector(dm, &global);CHKERRQ(ierr); 976 ierr = DMCreateLocalVector(dm, &local);CHKERRQ(ierr); 977 978 ierr = VecGetOwnershipRange(global, &dmmoab->vstart, &dmmoab->vend);CHKERRQ(ierr); 979 PetscInfo3(NULL, "Total-size = %D\t Owned = %D, Ghosted = %D.\n", totsize, dmmoab->nloc, dmmoab->nghost); 980 981 /* global to local must retrieve ghost points */ 982 ierr = ISCreateStride(((PetscObject)dm)->comm,dmmoab->nloc*dmmoab->numFields,dmmoab->vstart,1,&from);CHKERRQ(ierr); 983 ierr = ISSetBlockSize(from,bs);CHKERRQ(ierr); 984 985 ierr = ISCreateGeneral(((PetscObject)dm)->comm,dmmoab->nloc*dmmoab->numFields,&dmmoab->lgmap[0],PETSC_COPY_VALUES,&to);CHKERRQ(ierr); 986 ierr = ISSetBlockSize(to,bs);CHKERRQ(ierr); 987 988 if (!dmmoab->ltog_map) { 989 /* create to the local to global mapping for vectors in order to use VecSetValuesLocal */ 990 ierr = ISLocalToGlobalMappingCreate(((PetscObject)dm)->comm,totsize*dmmoab->numFields,dmmoab->lgmap, 991 PETSC_COPY_VALUES,&dmmoab->ltog_map);CHKERRQ(ierr); 992 } 993 994 /* now create the scatter object from local to global vector */ 995 ierr = VecScatterCreate(local,from,global,to,&dmmoab->ltog_sendrecv);CHKERRQ(ierr); 996 997 /* clean up IS, Vec */ 998 ierr = ISDestroy(&from);CHKERRQ(ierr); 999 ierr = ISDestroy(&to);CHKERRQ(ierr); 1000 ierr = VecDestroy(&local);CHKERRQ(ierr); 1001 ierr = VecDestroy(&global);CHKERRQ(ierr); 1002 } 1003 1004 /* skin the boundary and store nodes */ 1005 { 1006 /* get the skin vertices of boundary faces for the current partition and then filter 1007 the local, boundary faces, vertices and elements alone via PSTATUS flags; 1008 this should not give us any ghosted boundary, but if user needs such a functionality 1009 it would be easy to add it based on the find_skin query below */ 1010 moab::Skinner skinner(dmmoab->mbiface); 1011 1012 dmmoab->bndyvtx = new moab::Range(); 1013 dmmoab->bndyfaces = new moab::Range(); 1014 dmmoab->bndyelems = new moab::Range(); 1015 1016 /* get the entities on the skin - only the faces */ 1017 merr = skinner.find_skin(dmmoab->fileset, *dmmoab->elocal, false, *dmmoab->bndyfaces, NULL, false, true, false);MBERRNM(merr); // 'false' param indicates we want faces back, not vertices 1018 1019 /* filter all the non-owned and shared entities out of the list */ 1020 merr = dmmoab->pcomm->filter_pstatus(*dmmoab->bndyfaces,PSTATUS_NOT_OWNED,PSTATUS_NOT);MBERRNM(merr); 1021 merr = dmmoab->pcomm->filter_pstatus(*dmmoab->bndyfaces,PSTATUS_SHARED,PSTATUS_NOT);MBERRNM(merr); 1022 1023 /* get all the nodes via connectivity and the parent elements via adjacency information */ 1024 merr = dmmoab->mbiface->get_connectivity(*dmmoab->bndyfaces, *dmmoab->bndyvtx, false);MBERRNM(ierr); 1025 merr = dmmoab->mbiface->get_adjacencies(*dmmoab->bndyfaces, dmmoab->dim, false, *dmmoab->bndyelems, moab::Interface::UNION);MBERRNM(ierr); 1026 PetscInfo3(NULL, "Found %D boundary vertices, %D boundary faces and %D boundary elements.\n", dmmoab->bndyvtx->size(), dmmoab->bndyvtx->size(), dmmoab->bndyelems->size()); 1027 } 1028 PetscFunctionReturn(0); 1029 } 1030 1031 1032 #undef __FUNCT__ 1033 #define __FUNCT__ "DMCreate_Moab" 1034 PETSC_EXTERN PetscErrorCode DMCreate_Moab(DM dm) 1035 { 1036 PetscErrorCode ierr; 1037 1038 PetscFunctionBegin; 1039 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1040 ierr = PetscNewLog(dm,DM_Moab,&dm->data);CHKERRQ(ierr); 1041 1042 ((DM_Moab*)dm->data)->bs = 1; 1043 ((DM_Moab*)dm->data)->numFields = 1; 1044 ((DM_Moab*)dm->data)->n = 0; 1045 ((DM_Moab*)dm->data)->nloc = 0; 1046 ((DM_Moab*)dm->data)->nghost = 0; 1047 ((DM_Moab*)dm->data)->nele = 0; 1048 ((DM_Moab*)dm->data)->neleloc = 0; 1049 ((DM_Moab*)dm->data)->neleghost = 0; 1050 ((DM_Moab*)dm->data)->ltog_map = PETSC_NULL; 1051 ((DM_Moab*)dm->data)->ltog_sendrecv = PETSC_NULL; 1052 1053 ((DM_Moab*)dm->data)->vlocal = new moab::Range(); 1054 ((DM_Moab*)dm->data)->vowned = new moab::Range(); 1055 ((DM_Moab*)dm->data)->vghost = new moab::Range(); 1056 ((DM_Moab*)dm->data)->elocal = new moab::Range(); 1057 ((DM_Moab*)dm->data)->eghost = new moab::Range(); 1058 1059 dm->ops->createglobalvector = DMCreateGlobalVector_Moab; 1060 dm->ops->createlocalvector = DMCreateLocalVector_Moab; 1061 dm->ops->creatematrix = DMCreateMatrix_Moab; 1062 dm->ops->setup = DMSetUp_Moab; 1063 dm->ops->destroy = DMDestroy_Moab; 1064 dm->ops->globaltolocalbegin = DMGlobalToLocalBegin_Moab; 1065 dm->ops->globaltolocalend = DMGlobalToLocalEnd_Moab; 1066 dm->ops->localtoglobalbegin = DMLocalToGlobalBegin_Moab; 1067 dm->ops->localtoglobalend = DMLocalToGlobalEnd_Moab; 1068 PetscFunctionReturn(0); 1069 } 1070 1071