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