1 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/ 2 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 3 #include <petscsf.h> 4 #include <petscds.h> 5 6 PetscClassId DM_CLASSID; 7 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal, DM_LocatePoints, DM_Coarsen, DM_CreateInterpolation, DM_CreateRestriction; 8 9 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DM_BOUNDARY_",0}; 10 11 #undef __FUNCT__ 12 #define __FUNCT__ "DMCreate" 13 /*@ 14 DMCreate - Creates an empty DM object. The type can then be set with DMSetType(). 15 16 If you never call DMSetType() it will generate an 17 error when you try to use the vector. 18 19 Collective on MPI_Comm 20 21 Input Parameter: 22 . comm - The communicator for the DM object 23 24 Output Parameter: 25 . dm - The DM object 26 27 Level: beginner 28 29 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK 30 @*/ 31 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm) 32 { 33 DM v; 34 PetscErrorCode ierr; 35 36 PetscFunctionBegin; 37 PetscValidPointer(dm,2); 38 *dm = NULL; 39 ierr = PetscSysInitializePackage();CHKERRQ(ierr); 40 ierr = VecInitializePackage();CHKERRQ(ierr); 41 ierr = MatInitializePackage();CHKERRQ(ierr); 42 ierr = DMInitializePackage();CHKERRQ(ierr); 43 44 ierr = PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr); 45 46 v->ltogmap = NULL; 47 v->bs = 1; 48 v->coloringtype = IS_COLORING_GLOBAL; 49 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr); 50 ierr = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr); 51 v->labels = NULL; 52 v->depthLabel = NULL; 53 v->defaultSection = NULL; 54 v->defaultGlobalSection = NULL; 55 v->defaultConstraintSection = NULL; 56 v->defaultConstraintMat = NULL; 57 v->L = NULL; 58 v->maxCell = NULL; 59 v->bdtype = NULL; 60 v->dimEmbed = PETSC_DEFAULT; 61 { 62 PetscInt i; 63 for (i = 0; i < 10; ++i) { 64 v->nullspaceConstructors[i] = NULL; 65 } 66 } 67 ierr = PetscDSCreate(comm, &v->prob);CHKERRQ(ierr); 68 v->dmBC = NULL; 69 v->coarseMesh = NULL; 70 v->outputSequenceNum = -1; 71 v->outputSequenceVal = 0.0; 72 ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr); 73 ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr); 74 ierr = PetscNew(&(v->labels));CHKERRQ(ierr); 75 v->labels->refct = 1; 76 ierr = PetscNew(&(v->boundary));CHKERRQ(ierr); 77 v->boundary->refct = 1; 78 *dm = v; 79 PetscFunctionReturn(0); 80 } 81 82 #undef __FUNCT__ 83 #define __FUNCT__ "DMClone" 84 /*@ 85 DMClone - Creates a DM object with the same topology as the original. 86 87 Collective on MPI_Comm 88 89 Input Parameter: 90 . dm - The original DM object 91 92 Output Parameter: 93 . newdm - The new DM object 94 95 Level: beginner 96 97 .keywords: DM, topology, create 98 @*/ 99 PetscErrorCode DMClone(DM dm, DM *newdm) 100 { 101 PetscSF sf; 102 Vec coords; 103 void *ctx; 104 PetscInt dim; 105 PetscErrorCode ierr; 106 107 PetscFunctionBegin; 108 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 109 PetscValidPointer(newdm,2); 110 ierr = DMCreate(PetscObjectComm((PetscObject) dm), newdm);CHKERRQ(ierr); 111 ierr = PetscFree((*newdm)->labels);CHKERRQ(ierr); 112 dm->labels->refct++; 113 (*newdm)->labels = dm->labels; 114 (*newdm)->depthLabel = dm->depthLabel; 115 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 116 ierr = DMSetDimension(*newdm, dim);CHKERRQ(ierr); 117 if (dm->ops->clone) { 118 ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr); 119 } 120 (*newdm)->setupcalled = dm->setupcalled; 121 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 122 ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr); 123 ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr); 124 ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr); 125 if (dm->coordinateDM) { 126 DM ncdm; 127 PetscSection cs; 128 PetscInt pEnd = -1; 129 130 ierr = DMGetDefaultSection(dm->coordinateDM, &cs);CHKERRQ(ierr); 131 if (cs) {ierr = PetscSectionGetChart(cs, NULL, &pEnd);CHKERRQ(ierr);} 132 if (pEnd >= 0) { 133 ierr = DMClone(dm->coordinateDM, &ncdm);CHKERRQ(ierr); 134 ierr = DMSetDefaultSection(ncdm, cs);CHKERRQ(ierr); 135 ierr = DMSetCoordinateDM(*newdm, ncdm);CHKERRQ(ierr); 136 ierr = DMDestroy(&ncdm);CHKERRQ(ierr); 137 } 138 } 139 ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr); 140 if (coords) { 141 ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr); 142 } else { 143 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 144 if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);} 145 } 146 if (dm->maxCell) { 147 const PetscReal *maxCell, *L; 148 const DMBoundaryType *bd; 149 ierr = DMGetPeriodicity(dm, &maxCell, &L, &bd);CHKERRQ(ierr); 150 ierr = DMSetPeriodicity(*newdm, maxCell, L, bd);CHKERRQ(ierr); 151 } 152 PetscFunctionReturn(0); 153 } 154 155 #undef __FUNCT__ 156 #define __FUNCT__ "DMSetVecType" 157 /*@C 158 DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 159 160 Logically Collective on DM 161 162 Input Parameter: 163 + da - initial distributed array 164 . ctype - the vector type, currently either VECSTANDARD or VECCUSP 165 166 Options Database: 167 . -dm_vec_type ctype 168 169 Level: intermediate 170 171 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType() 172 @*/ 173 PetscErrorCode DMSetVecType(DM da,VecType ctype) 174 { 175 PetscErrorCode ierr; 176 177 PetscFunctionBegin; 178 PetscValidHeaderSpecific(da,DM_CLASSID,1); 179 ierr = PetscFree(da->vectype);CHKERRQ(ierr); 180 ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr); 181 PetscFunctionReturn(0); 182 } 183 184 #undef __FUNCT__ 185 #define __FUNCT__ "DMGetVecType" 186 /*@C 187 DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 188 189 Logically Collective on DM 190 191 Input Parameter: 192 . da - initial distributed array 193 194 Output Parameter: 195 . ctype - the vector type 196 197 Level: intermediate 198 199 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType 200 @*/ 201 PetscErrorCode DMGetVecType(DM da,VecType *ctype) 202 { 203 PetscFunctionBegin; 204 PetscValidHeaderSpecific(da,DM_CLASSID,1); 205 *ctype = da->vectype; 206 PetscFunctionReturn(0); 207 } 208 209 #undef __FUNCT__ 210 #define __FUNCT__ "VecGetDM" 211 /*@ 212 VecGetDM - Gets the DM defining the data layout of the vector 213 214 Not collective 215 216 Input Parameter: 217 . v - The Vec 218 219 Output Parameter: 220 . dm - The DM 221 222 Level: intermediate 223 224 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 225 @*/ 226 PetscErrorCode VecGetDM(Vec v, DM *dm) 227 { 228 PetscErrorCode ierr; 229 230 PetscFunctionBegin; 231 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 232 PetscValidPointer(dm,2); 233 ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 234 PetscFunctionReturn(0); 235 } 236 237 #undef __FUNCT__ 238 #define __FUNCT__ "VecSetDM" 239 /*@ 240 VecSetDM - Sets the DM defining the data layout of the vector. 241 242 Not collective 243 244 Input Parameters: 245 + v - The Vec 246 - dm - The DM 247 248 Note: This is NOT the same as DMCreateGlobalVector() since it does not change the view methods or perform other customization, but merely sets the DM member. 249 250 Level: intermediate 251 252 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 253 @*/ 254 PetscErrorCode VecSetDM(Vec v, DM dm) 255 { 256 PetscErrorCode ierr; 257 258 PetscFunctionBegin; 259 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 260 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 261 ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 262 PetscFunctionReturn(0); 263 } 264 265 #undef __FUNCT__ 266 #define __FUNCT__ "DMSetMatType" 267 /*@C 268 DMSetMatType - Sets the type of matrix created with DMCreateMatrix() 269 270 Logically Collective on DM 271 272 Input Parameter: 273 + dm - the DM context 274 . ctype - the matrix type 275 276 Options Database: 277 . -dm_mat_type ctype 278 279 Level: intermediate 280 281 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType() 282 @*/ 283 PetscErrorCode DMSetMatType(DM dm,MatType ctype) 284 { 285 PetscErrorCode ierr; 286 287 PetscFunctionBegin; 288 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 289 ierr = PetscFree(dm->mattype);CHKERRQ(ierr); 290 ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr); 291 PetscFunctionReturn(0); 292 } 293 294 #undef __FUNCT__ 295 #define __FUNCT__ "DMGetMatType" 296 /*@C 297 DMGetMatType - Gets the type of matrix created with DMCreateMatrix() 298 299 Logically Collective on DM 300 301 Input Parameter: 302 . dm - the DM context 303 304 Output Parameter: 305 . ctype - the matrix type 306 307 Options Database: 308 . -dm_mat_type ctype 309 310 Level: intermediate 311 312 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType() 313 @*/ 314 PetscErrorCode DMGetMatType(DM dm,MatType *ctype) 315 { 316 PetscFunctionBegin; 317 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 318 *ctype = dm->mattype; 319 PetscFunctionReturn(0); 320 } 321 322 #undef __FUNCT__ 323 #define __FUNCT__ "MatGetDM" 324 /*@ 325 MatGetDM - Gets the DM defining the data layout of the matrix 326 327 Not collective 328 329 Input Parameter: 330 . A - The Mat 331 332 Output Parameter: 333 . dm - The DM 334 335 Level: intermediate 336 337 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType() 338 @*/ 339 PetscErrorCode MatGetDM(Mat A, DM *dm) 340 { 341 PetscErrorCode ierr; 342 343 PetscFunctionBegin; 344 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 345 PetscValidPointer(dm,2); 346 ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 347 PetscFunctionReturn(0); 348 } 349 350 #undef __FUNCT__ 351 #define __FUNCT__ "MatSetDM" 352 /*@ 353 MatSetDM - Sets the DM defining the data layout of the matrix 354 355 Not collective 356 357 Input Parameters: 358 + A - The Mat 359 - dm - The DM 360 361 Level: intermediate 362 363 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType() 364 @*/ 365 PetscErrorCode MatSetDM(Mat A, DM dm) 366 { 367 PetscErrorCode ierr; 368 369 PetscFunctionBegin; 370 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 371 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 372 ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 373 PetscFunctionReturn(0); 374 } 375 376 #undef __FUNCT__ 377 #define __FUNCT__ "DMSetOptionsPrefix" 378 /*@C 379 DMSetOptionsPrefix - Sets the prefix used for searching for all 380 DM options in the database. 381 382 Logically Collective on DM 383 384 Input Parameter: 385 + da - the DM context 386 - prefix - the prefix to prepend to all option names 387 388 Notes: 389 A hyphen (-) must NOT be given at the beginning of the prefix name. 390 The first character of all runtime options is AUTOMATICALLY the hyphen. 391 392 Level: advanced 393 394 .keywords: DM, set, options, prefix, database 395 396 .seealso: DMSetFromOptions() 397 @*/ 398 PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[]) 399 { 400 PetscErrorCode ierr; 401 402 PetscFunctionBegin; 403 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 404 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 405 if (dm->sf) { 406 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);CHKERRQ(ierr); 407 } 408 if (dm->defaultSF) { 409 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->defaultSF,prefix);CHKERRQ(ierr); 410 } 411 PetscFunctionReturn(0); 412 } 413 414 #undef __FUNCT__ 415 #define __FUNCT__ "DMAppendOptionsPrefix" 416 /*@C 417 DMAppendOptionsPrefix - Appends to the prefix used for searching for all 418 DM options in the database. 419 420 Logically Collective on DM 421 422 Input Parameters: 423 + dm - the DM context 424 - prefix - the prefix string to prepend to all DM option requests 425 426 Notes: 427 A hyphen (-) must NOT be given at the beginning of the prefix name. 428 The first character of all runtime options is AUTOMATICALLY the hyphen. 429 430 Level: advanced 431 432 .keywords: DM, append, options, prefix, database 433 434 .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix() 435 @*/ 436 PetscErrorCode DMAppendOptionsPrefix(DM dm,const char prefix[]) 437 { 438 PetscErrorCode ierr; 439 440 PetscFunctionBegin; 441 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 442 ierr = PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 443 PetscFunctionReturn(0); 444 } 445 446 #undef __FUNCT__ 447 #define __FUNCT__ "DMGetOptionsPrefix" 448 /*@C 449 DMGetOptionsPrefix - Gets the prefix used for searching for all 450 DM options in the database. 451 452 Not Collective 453 454 Input Parameters: 455 . dm - the DM context 456 457 Output Parameters: 458 . prefix - pointer to the prefix string used is returned 459 460 Notes: On the fortran side, the user should pass in a string 'prefix' of 461 sufficient length to hold the prefix. 462 463 Level: advanced 464 465 .keywords: DM, set, options, prefix, database 466 467 .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix() 468 @*/ 469 PetscErrorCode DMGetOptionsPrefix(DM dm,const char *prefix[]) 470 { 471 PetscErrorCode ierr; 472 473 PetscFunctionBegin; 474 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 475 ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 476 PetscFunctionReturn(0); 477 } 478 479 #undef __FUNCT__ 480 #define __FUNCT__ "DMCountNonCyclicReferences" 481 static PetscErrorCode DMCountNonCyclicReferences(DM dm, PetscBool recurseCoarse, PetscBool recurseFine, PetscInt *ncrefct) 482 { 483 PetscInt i, refct = ((PetscObject) dm)->refct; 484 DMNamedVecLink nlink; 485 PetscErrorCode ierr; 486 487 PetscFunctionBegin; 488 /* count all the circular references of DM and its contained Vecs */ 489 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 490 if (dm->localin[i]) refct--; 491 if (dm->globalin[i]) refct--; 492 } 493 for (nlink=dm->namedglobal; nlink; nlink=nlink->next) refct--; 494 for (nlink=dm->namedlocal; nlink; nlink=nlink->next) refct--; 495 if (dm->x) { 496 DM obj; 497 ierr = VecGetDM(dm->x, &obj);CHKERRQ(ierr); 498 if (obj == dm) refct--; 499 } 500 if (dm->coarseMesh && dm->coarseMesh->fineMesh == dm) { 501 refct--; 502 if (recurseCoarse) { 503 PetscInt coarseCount; 504 505 ierr = DMCountNonCyclicReferences(dm->coarseMesh, PETSC_TRUE, PETSC_FALSE,&coarseCount);CHKERRQ(ierr); 506 refct += coarseCount; 507 } 508 } 509 if (dm->fineMesh && dm->fineMesh->coarseMesh == dm) { 510 refct--; 511 if (recurseFine) { 512 PetscInt fineCount; 513 514 ierr = DMCountNonCyclicReferences(dm->fineMesh, PETSC_FALSE, PETSC_TRUE,&fineCount);CHKERRQ(ierr); 515 refct += fineCount; 516 } 517 } 518 *ncrefct = refct; 519 PetscFunctionReturn(0); 520 } 521 522 PetscErrorCode DMBoundaryDestroy(DMBoundaryLinkList *boundary); 523 524 #undef __FUNCT__ 525 #define __FUNCT__ "DMDestroyLabelLinkList" 526 PetscErrorCode DMDestroyLabelLinkList(DM dm) 527 { 528 PetscErrorCode ierr; 529 530 PetscFunctionBegin; 531 if (!--(dm->labels->refct)) { 532 DMLabelLink next = dm->labels->next; 533 534 /* destroy the labels */ 535 while (next) { 536 DMLabelLink tmp = next->next; 537 538 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 539 ierr = PetscFree(next);CHKERRQ(ierr); 540 next = tmp; 541 } 542 ierr = PetscFree(dm->labels);CHKERRQ(ierr); 543 } 544 PetscFunctionReturn(0); 545 } 546 547 #undef __FUNCT__ 548 #define __FUNCT__ "DMDestroy" 549 /*@ 550 DMDestroy - Destroys a vector packer or DM. 551 552 Collective on DM 553 554 Input Parameter: 555 . dm - the DM object to destroy 556 557 Level: developer 558 559 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 560 561 @*/ 562 PetscErrorCode DMDestroy(DM *dm) 563 { 564 PetscInt i, cnt; 565 DMNamedVecLink nlink,nnext; 566 PetscErrorCode ierr; 567 568 PetscFunctionBegin; 569 if (!*dm) PetscFunctionReturn(0); 570 PetscValidHeaderSpecific((*dm),DM_CLASSID,1); 571 572 /* count all non-cyclic references in the doubly-linked list of coarse<->fine meshes */ 573 ierr = DMCountNonCyclicReferences(*dm,PETSC_TRUE,PETSC_TRUE,&cnt);CHKERRQ(ierr); 574 --((PetscObject)(*dm))->refct; 575 if (--cnt > 0) {*dm = 0; PetscFunctionReturn(0);} 576 /* 577 Need this test because the dm references the vectors that 578 reference the dm, so destroying the dm calls destroy on the 579 vectors that cause another destroy on the dm 580 */ 581 if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0); 582 ((PetscObject) (*dm))->refct = 0; 583 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 584 if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()"); 585 ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr); 586 } 587 nnext=(*dm)->namedglobal; 588 (*dm)->namedglobal = NULL; 589 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */ 590 nnext = nlink->next; 591 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 592 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 593 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 594 ierr = PetscFree(nlink);CHKERRQ(ierr); 595 } 596 nnext=(*dm)->namedlocal; 597 (*dm)->namedlocal = NULL; 598 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */ 599 nnext = nlink->next; 600 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 601 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 602 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 603 ierr = PetscFree(nlink);CHKERRQ(ierr); 604 } 605 606 /* Destroy the list of hooks */ 607 { 608 DMCoarsenHookLink link,next; 609 for (link=(*dm)->coarsenhook; link; link=next) { 610 next = link->next; 611 ierr = PetscFree(link);CHKERRQ(ierr); 612 } 613 (*dm)->coarsenhook = NULL; 614 } 615 { 616 DMRefineHookLink link,next; 617 for (link=(*dm)->refinehook; link; link=next) { 618 next = link->next; 619 ierr = PetscFree(link);CHKERRQ(ierr); 620 } 621 (*dm)->refinehook = NULL; 622 } 623 { 624 DMSubDomainHookLink link,next; 625 for (link=(*dm)->subdomainhook; link; link=next) { 626 next = link->next; 627 ierr = PetscFree(link);CHKERRQ(ierr); 628 } 629 (*dm)->subdomainhook = NULL; 630 } 631 { 632 DMGlobalToLocalHookLink link,next; 633 for (link=(*dm)->gtolhook; link; link=next) { 634 next = link->next; 635 ierr = PetscFree(link);CHKERRQ(ierr); 636 } 637 (*dm)->gtolhook = NULL; 638 } 639 { 640 DMLocalToGlobalHookLink link,next; 641 for (link=(*dm)->ltoghook; link; link=next) { 642 next = link->next; 643 ierr = PetscFree(link);CHKERRQ(ierr); 644 } 645 (*dm)->ltoghook = NULL; 646 } 647 /* Destroy the work arrays */ 648 { 649 DMWorkLink link,next; 650 if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out"); 651 for (link=(*dm)->workin; link; link=next) { 652 next = link->next; 653 ierr = PetscFree(link->mem);CHKERRQ(ierr); 654 ierr = PetscFree(link);CHKERRQ(ierr); 655 } 656 (*dm)->workin = NULL; 657 } 658 if (!--((*dm)->labels->refct)) { 659 DMLabelLink next = (*dm)->labels->next; 660 661 /* destroy the labels */ 662 while (next) { 663 DMLabelLink tmp = next->next; 664 665 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 666 ierr = PetscFree(next);CHKERRQ(ierr); 667 next = tmp; 668 } 669 ierr = PetscFree((*dm)->labels);CHKERRQ(ierr); 670 } 671 ierr = DMBoundaryDestroy(&(*dm)->boundary);CHKERRQ(ierr); 672 673 ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr); 674 ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr); 675 ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr); 676 677 if ((*dm)->ctx && (*dm)->ctxdestroy) { 678 ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr); 679 } 680 ierr = VecDestroy(&(*dm)->x);CHKERRQ(ierr); 681 ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr); 682 ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr); 683 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr); 684 ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr); 685 ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr); 686 687 ierr = PetscSectionDestroy(&(*dm)->defaultSection);CHKERRQ(ierr); 688 ierr = PetscSectionDestroy(&(*dm)->defaultGlobalSection);CHKERRQ(ierr); 689 ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr); 690 ierr = PetscSectionDestroy(&(*dm)->defaultConstraintSection);CHKERRQ(ierr); 691 ierr = MatDestroy(&(*dm)->defaultConstraintMat);CHKERRQ(ierr); 692 ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr); 693 ierr = PetscSFDestroy(&(*dm)->defaultSF);CHKERRQ(ierr); 694 ierr = PetscSFDestroy(&(*dm)->sfNatural);CHKERRQ(ierr); 695 696 if ((*dm)->coarseMesh && (*dm)->coarseMesh->fineMesh == *dm) { 697 ierr = DMSetFineDM((*dm)->coarseMesh,NULL);CHKERRQ(ierr); 698 } 699 ierr = DMDestroy(&(*dm)->coarseMesh);CHKERRQ(ierr); 700 if ((*dm)->fineMesh && (*dm)->fineMesh->coarseMesh == *dm) { 701 ierr = DMSetCoarseDM((*dm)->fineMesh,NULL);CHKERRQ(ierr); 702 } 703 ierr = DMDestroy(&(*dm)->fineMesh);CHKERRQ(ierr); 704 ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr); 705 ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr); 706 ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr); 707 ierr = PetscFree3((*dm)->L,(*dm)->maxCell,(*dm)->bdtype);CHKERRQ(ierr); 708 709 ierr = PetscDSDestroy(&(*dm)->prob);CHKERRQ(ierr); 710 ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr); 711 /* if memory was published with SAWs then destroy it */ 712 ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr); 713 714 ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr); 715 /* We do not destroy (*dm)->data here so that we can reference count backend objects */ 716 ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr); 717 PetscFunctionReturn(0); 718 } 719 720 #undef __FUNCT__ 721 #define __FUNCT__ "DMSetUp" 722 /*@ 723 DMSetUp - sets up the data structures inside a DM object 724 725 Collective on DM 726 727 Input Parameter: 728 . dm - the DM object to setup 729 730 Level: developer 731 732 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 733 734 @*/ 735 PetscErrorCode DMSetUp(DM dm) 736 { 737 PetscErrorCode ierr; 738 739 PetscFunctionBegin; 740 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 741 if (dm->setupcalled) PetscFunctionReturn(0); 742 if (dm->ops->setup) { 743 ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr); 744 } 745 dm->setupcalled = PETSC_TRUE; 746 PetscFunctionReturn(0); 747 } 748 749 #undef __FUNCT__ 750 #define __FUNCT__ "DMSetFromOptions" 751 /*@ 752 DMSetFromOptions - sets parameters in a DM from the options database 753 754 Collective on DM 755 756 Input Parameter: 757 . dm - the DM object to set options for 758 759 Options Database: 760 + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 761 . -dm_vec_type <type> - type of vector to create inside DM 762 . -dm_mat_type <type> - type of matrix to create inside DM 763 - -dm_coloring_type - <global or ghosted> 764 765 Level: developer 766 767 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 768 769 @*/ 770 PetscErrorCode DMSetFromOptions(DM dm) 771 { 772 char typeName[256]; 773 PetscBool flg; 774 PetscErrorCode ierr; 775 776 PetscFunctionBegin; 777 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 778 if (dm->sf) { 779 ierr = PetscSFSetFromOptions(dm->sf);CHKERRQ(ierr); 780 } 781 if (dm->defaultSF) { 782 ierr = PetscSFSetFromOptions(dm->defaultSF);CHKERRQ(ierr); 783 } 784 ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr); 785 ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr); 786 ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr); 787 if (flg) { 788 ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr); 789 } 790 ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr); 791 if (flg) { 792 ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr); 793 } 794 ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","ISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr); 795 if (dm->ops->setfromoptions) { 796 ierr = (*dm->ops->setfromoptions)(PetscOptionsObject,dm);CHKERRQ(ierr); 797 } 798 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 799 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) dm);CHKERRQ(ierr); 800 ierr = PetscOptionsEnd();CHKERRQ(ierr); 801 PetscFunctionReturn(0); 802 } 803 804 #undef __FUNCT__ 805 #define __FUNCT__ "DMView" 806 /*@C 807 DMView - Views a DM 808 809 Collective on DM 810 811 Input Parameter: 812 + dm - the DM object to view 813 - v - the viewer 814 815 Level: beginner 816 817 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 818 819 @*/ 820 PetscErrorCode DMView(DM dm,PetscViewer v) 821 { 822 PetscErrorCode ierr; 823 PetscBool isbinary; 824 825 PetscFunctionBegin; 826 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 827 if (!v) { 828 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr); 829 } 830 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr); 831 ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 832 if (isbinary) { 833 PetscInt classid = DM_FILE_CLASSID; 834 char type[256]; 835 836 ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 837 ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr); 838 ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 839 } 840 if (dm->ops->view) { 841 ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr); 842 } 843 PetscFunctionReturn(0); 844 } 845 846 #undef __FUNCT__ 847 #define __FUNCT__ "DMCreateGlobalVector" 848 /*@ 849 DMCreateGlobalVector - Creates a global vector from a DM object 850 851 Collective on DM 852 853 Input Parameter: 854 . dm - the DM object 855 856 Output Parameter: 857 . vec - the global vector 858 859 Level: beginner 860 861 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 862 863 @*/ 864 PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec) 865 { 866 PetscErrorCode ierr; 867 868 PetscFunctionBegin; 869 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 870 ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr); 871 PetscFunctionReturn(0); 872 } 873 874 #undef __FUNCT__ 875 #define __FUNCT__ "DMCreateLocalVector" 876 /*@ 877 DMCreateLocalVector - Creates a local vector from a DM object 878 879 Not Collective 880 881 Input Parameter: 882 . dm - the DM object 883 884 Output Parameter: 885 . vec - the local vector 886 887 Level: beginner 888 889 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 890 891 @*/ 892 PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec) 893 { 894 PetscErrorCode ierr; 895 896 PetscFunctionBegin; 897 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 898 ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr); 899 PetscFunctionReturn(0); 900 } 901 902 #undef __FUNCT__ 903 #define __FUNCT__ "DMGetLocalToGlobalMapping" 904 /*@ 905 DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM. 906 907 Collective on DM 908 909 Input Parameter: 910 . dm - the DM that provides the mapping 911 912 Output Parameter: 913 . ltog - the mapping 914 915 Level: intermediate 916 917 Notes: 918 This mapping can then be used by VecSetLocalToGlobalMapping() or 919 MatSetLocalToGlobalMapping(). 920 921 .seealso: DMCreateLocalVector() 922 @*/ 923 PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog) 924 { 925 PetscErrorCode ierr; 926 927 PetscFunctionBegin; 928 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 929 PetscValidPointer(ltog,2); 930 if (!dm->ltogmap) { 931 PetscSection section, sectionGlobal; 932 933 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 934 if (section) { 935 PetscInt *ltog; 936 PetscInt pStart, pEnd, size, p, l; 937 938 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 939 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 940 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 941 ierr = PetscMalloc1(size, <og);CHKERRQ(ierr); /* We want the local+overlap size */ 942 for (p = pStart, l = 0; p < pEnd; ++p) { 943 PetscInt dof, off, c; 944 945 /* Should probably use constrained dofs */ 946 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 947 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 948 for (c = 0; c < dof; ++c, ++l) { 949 ltog[l] = off+c; 950 } 951 } 952 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1,size, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr); 953 ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr); 954 } else { 955 if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping"); 956 ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr); 957 } 958 } 959 *ltog = dm->ltogmap; 960 PetscFunctionReturn(0); 961 } 962 963 #undef __FUNCT__ 964 #define __FUNCT__ "DMGetBlockSize" 965 /*@ 966 DMGetBlockSize - Gets the inherent block size associated with a DM 967 968 Not Collective 969 970 Input Parameter: 971 . dm - the DM with block structure 972 973 Output Parameter: 974 . bs - the block size, 1 implies no exploitable block structure 975 976 Level: intermediate 977 978 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping() 979 @*/ 980 PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs) 981 { 982 PetscFunctionBegin; 983 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 984 PetscValidPointer(bs,2); 985 if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet"); 986 *bs = dm->bs; 987 PetscFunctionReturn(0); 988 } 989 990 #undef __FUNCT__ 991 #define __FUNCT__ "DMCreateInterpolation" 992 /*@ 993 DMCreateInterpolation - Gets interpolation matrix between two DM objects 994 995 Collective on DM 996 997 Input Parameter: 998 + dm1 - the DM object 999 - dm2 - the second, finer DM object 1000 1001 Output Parameter: 1002 + mat - the interpolation 1003 - vec - the scaling (optional) 1004 1005 Level: developer 1006 1007 Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1008 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 1009 1010 For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors 1011 EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic. 1012 1013 1014 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateRestriction() 1015 1016 @*/ 1017 PetscErrorCode DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec) 1018 { 1019 PetscErrorCode ierr; 1020 1021 PetscFunctionBegin; 1022 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 1023 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 1024 ierr = PetscLogEventBegin(DM_CreateInterpolation,dm1,dm2,0,0);CHKERRQ(ierr); 1025 ierr = (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr); 1026 ierr = PetscLogEventEnd(DM_CreateInterpolation,dm1,dm2,0,0);CHKERRQ(ierr); 1027 PetscFunctionReturn(0); 1028 } 1029 1030 #undef __FUNCT__ 1031 #define __FUNCT__ "DMCreateRestriction" 1032 /*@ 1033 DMCreateRestriction - Gets restriction matrix between two DM objects 1034 1035 Collective on DM 1036 1037 Input Parameter: 1038 + dm1 - the DM object 1039 - dm2 - the second, finer DM object 1040 1041 Output Parameter: 1042 . mat - the restriction 1043 1044 1045 Level: developer 1046 1047 Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1048 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 1049 1050 1051 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen(), DMCreateInterpolation() 1052 1053 @*/ 1054 PetscErrorCode DMCreateRestriction(DM dm1,DM dm2,Mat *mat) 1055 { 1056 PetscErrorCode ierr; 1057 1058 PetscFunctionBegin; 1059 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 1060 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 1061 ierr = PetscLogEventBegin(DM_CreateRestriction,dm1,dm2,0,0);CHKERRQ(ierr); 1062 ierr = (*dm1->ops->createrestriction)(dm1,dm2,mat);CHKERRQ(ierr); 1063 ierr = PetscLogEventEnd(DM_CreateRestriction,dm1,dm2,0,0);CHKERRQ(ierr); 1064 PetscFunctionReturn(0); 1065 } 1066 1067 #undef __FUNCT__ 1068 #define __FUNCT__ "DMCreateInjection" 1069 /*@ 1070 DMCreateInjection - Gets injection matrix between two DM objects 1071 1072 Collective on DM 1073 1074 Input Parameter: 1075 + dm1 - the DM object 1076 - dm2 - the second, finer DM object 1077 1078 Output Parameter: 1079 . mat - the injection 1080 1081 Level: developer 1082 1083 Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 1084 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection. 1085 1086 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation() 1087 1088 @*/ 1089 PetscErrorCode DMCreateInjection(DM dm1,DM dm2,Mat *mat) 1090 { 1091 PetscErrorCode ierr; 1092 1093 PetscFunctionBegin; 1094 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 1095 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 1096 if (!*dm1->ops->getinjection) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_SUP,"DMCreateInjection not implemented for this type"); 1097 ierr = (*dm1->ops->getinjection)(dm1,dm2,mat);CHKERRQ(ierr); 1098 PetscFunctionReturn(0); 1099 } 1100 1101 #undef __FUNCT__ 1102 #define __FUNCT__ "DMCreateColoring" 1103 /*@ 1104 DMCreateColoring - Gets coloring for a DM 1105 1106 Collective on DM 1107 1108 Input Parameter: 1109 + dm - the DM object 1110 - ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL 1111 1112 Output Parameter: 1113 . coloring - the coloring 1114 1115 Level: developer 1116 1117 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType() 1118 1119 @*/ 1120 PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring) 1121 { 1122 PetscErrorCode ierr; 1123 1124 PetscFunctionBegin; 1125 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1126 if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet"); 1127 ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr); 1128 PetscFunctionReturn(0); 1129 } 1130 1131 #undef __FUNCT__ 1132 #define __FUNCT__ "DMCreateMatrix" 1133 /*@ 1134 DMCreateMatrix - Gets empty Jacobian for a DM 1135 1136 Collective on DM 1137 1138 Input Parameter: 1139 . dm - the DM object 1140 1141 Output Parameter: 1142 . mat - the empty Jacobian 1143 1144 Level: beginner 1145 1146 Notes: This properly preallocates the number of nonzeros in the sparse matrix so you 1147 do not need to do it yourself. 1148 1149 By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 1150 the nonzero pattern call DMDASetMatPreallocateOnly() 1151 1152 For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used 1153 internally by PETSc. 1154 1155 For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 1156 the indices for the global numbering for DMDAs which is complicated. 1157 1158 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType() 1159 1160 @*/ 1161 PetscErrorCode DMCreateMatrix(DM dm,Mat *mat) 1162 { 1163 PetscErrorCode ierr; 1164 1165 PetscFunctionBegin; 1166 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1167 ierr = MatInitializePackage();CHKERRQ(ierr); 1168 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1169 PetscValidPointer(mat,3); 1170 ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr); 1171 PetscFunctionReturn(0); 1172 } 1173 1174 #undef __FUNCT__ 1175 #define __FUNCT__ "DMSetMatrixPreallocateOnly" 1176 /*@ 1177 DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly 1178 preallocated but the nonzero structure and zero values will not be set. 1179 1180 Logically Collective on DM 1181 1182 Input Parameter: 1183 + dm - the DM 1184 - only - PETSC_TRUE if only want preallocation 1185 1186 Level: developer 1187 .seealso DMCreateMatrix() 1188 @*/ 1189 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only) 1190 { 1191 PetscFunctionBegin; 1192 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1193 dm->prealloc_only = only; 1194 PetscFunctionReturn(0); 1195 } 1196 1197 #undef __FUNCT__ 1198 #define __FUNCT__ "DMGetWorkArray" 1199 /*@C 1200 DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1201 1202 Not Collective 1203 1204 Input Parameters: 1205 + dm - the DM object 1206 . count - The minium size 1207 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 1208 1209 Output Parameter: 1210 . array - the work array 1211 1212 Level: developer 1213 1214 .seealso DMDestroy(), DMCreate() 1215 @*/ 1216 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 1217 { 1218 PetscErrorCode ierr; 1219 DMWorkLink link; 1220 size_t dsize; 1221 1222 PetscFunctionBegin; 1223 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1224 PetscValidPointer(mem,4); 1225 if (dm->workin) { 1226 link = dm->workin; 1227 dm->workin = dm->workin->next; 1228 } else { 1229 ierr = PetscNewLog(dm,&link);CHKERRQ(ierr); 1230 } 1231 ierr = PetscDataTypeGetSize(dtype,&dsize);CHKERRQ(ierr); 1232 if (dsize*count > link->bytes) { 1233 ierr = PetscFree(link->mem);CHKERRQ(ierr); 1234 ierr = PetscMalloc(dsize*count,&link->mem);CHKERRQ(ierr); 1235 link->bytes = dsize*count; 1236 } 1237 link->next = dm->workout; 1238 dm->workout = link; 1239 *(void**)mem = link->mem; 1240 PetscFunctionReturn(0); 1241 } 1242 1243 #undef __FUNCT__ 1244 #define __FUNCT__ "DMRestoreWorkArray" 1245 /*@C 1246 DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1247 1248 Not Collective 1249 1250 Input Parameters: 1251 + dm - the DM object 1252 . count - The minium size 1253 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 1254 1255 Output Parameter: 1256 . array - the work array 1257 1258 Level: developer 1259 1260 .seealso DMDestroy(), DMCreate() 1261 @*/ 1262 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 1263 { 1264 DMWorkLink *p,link; 1265 1266 PetscFunctionBegin; 1267 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1268 PetscValidPointer(mem,4); 1269 for (p=&dm->workout; (link=*p); p=&link->next) { 1270 if (link->mem == *(void**)mem) { 1271 *p = link->next; 1272 link->next = dm->workin; 1273 dm->workin = link; 1274 *(void**)mem = NULL; 1275 PetscFunctionReturn(0); 1276 } 1277 } 1278 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out"); 1279 } 1280 1281 #undef __FUNCT__ 1282 #define __FUNCT__ "DMSetNullSpaceConstructor" 1283 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace)) 1284 { 1285 PetscFunctionBegin; 1286 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1287 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1288 dm->nullspaceConstructors[field] = nullsp; 1289 PetscFunctionReturn(0); 1290 } 1291 1292 #undef __FUNCT__ 1293 #define __FUNCT__ "DMCreateFieldIS" 1294 /*@C 1295 DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field 1296 1297 Not collective 1298 1299 Input Parameter: 1300 . dm - the DM object 1301 1302 Output Parameters: 1303 + numFields - The number of fields (or NULL if not requested) 1304 . fieldNames - The name for each field (or NULL if not requested) 1305 - fields - The global indices for each field (or NULL if not requested) 1306 1307 Level: intermediate 1308 1309 Notes: 1310 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1311 PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with 1312 PetscFree(). 1313 1314 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1315 @*/ 1316 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields) 1317 { 1318 PetscSection section, sectionGlobal; 1319 PetscErrorCode ierr; 1320 1321 PetscFunctionBegin; 1322 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1323 if (numFields) { 1324 PetscValidPointer(numFields,2); 1325 *numFields = 0; 1326 } 1327 if (fieldNames) { 1328 PetscValidPointer(fieldNames,3); 1329 *fieldNames = NULL; 1330 } 1331 if (fields) { 1332 PetscValidPointer(fields,4); 1333 *fields = NULL; 1334 } 1335 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1336 if (section) { 1337 PetscInt *fieldSizes, **fieldIndices; 1338 PetscInt nF, f, pStart, pEnd, p; 1339 1340 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1341 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1342 ierr = PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);CHKERRQ(ierr); 1343 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1344 for (f = 0; f < nF; ++f) { 1345 fieldSizes[f] = 0; 1346 } 1347 for (p = pStart; p < pEnd; ++p) { 1348 PetscInt gdof; 1349 1350 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1351 if (gdof > 0) { 1352 for (f = 0; f < nF; ++f) { 1353 PetscInt fdof, fcdof; 1354 1355 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1356 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1357 fieldSizes[f] += fdof-fcdof; 1358 } 1359 } 1360 } 1361 for (f = 0; f < nF; ++f) { 1362 ierr = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr); 1363 fieldSizes[f] = 0; 1364 } 1365 for (p = pStart; p < pEnd; ++p) { 1366 PetscInt gdof, goff; 1367 1368 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1369 if (gdof > 0) { 1370 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1371 for (f = 0; f < nF; ++f) { 1372 PetscInt fdof, fcdof, fc; 1373 1374 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1375 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1376 for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) { 1377 fieldIndices[f][fieldSizes[f]] = goff++; 1378 } 1379 } 1380 } 1381 } 1382 if (numFields) *numFields = nF; 1383 if (fieldNames) { 1384 ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr); 1385 for (f = 0; f < nF; ++f) { 1386 const char *fieldName; 1387 1388 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1389 ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr); 1390 } 1391 } 1392 if (fields) { 1393 ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr); 1394 for (f = 0; f < nF; ++f) { 1395 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr); 1396 } 1397 } 1398 ierr = PetscFree2(fieldSizes,fieldIndices);CHKERRQ(ierr); 1399 } else if (dm->ops->createfieldis) { 1400 ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr); 1401 } 1402 PetscFunctionReturn(0); 1403 } 1404 1405 1406 #undef __FUNCT__ 1407 #define __FUNCT__ "DMCreateFieldDecomposition" 1408 /*@C 1409 DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems 1410 corresponding to different fields: each IS contains the global indices of the dofs of the 1411 corresponding field. The optional list of DMs define the DM for each subproblem. 1412 Generalizes DMCreateFieldIS(). 1413 1414 Not collective 1415 1416 Input Parameter: 1417 . dm - the DM object 1418 1419 Output Parameters: 1420 + len - The number of subproblems in the field decomposition (or NULL if not requested) 1421 . namelist - The name for each field (or NULL if not requested) 1422 . islist - The global indices for each field (or NULL if not requested) 1423 - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1424 1425 Level: intermediate 1426 1427 Notes: 1428 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1429 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1430 and all of the arrays should be freed with PetscFree(). 1431 1432 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1433 @*/ 1434 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 1435 { 1436 PetscErrorCode ierr; 1437 1438 PetscFunctionBegin; 1439 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1440 if (len) { 1441 PetscValidPointer(len,2); 1442 *len = 0; 1443 } 1444 if (namelist) { 1445 PetscValidPointer(namelist,3); 1446 *namelist = 0; 1447 } 1448 if (islist) { 1449 PetscValidPointer(islist,4); 1450 *islist = 0; 1451 } 1452 if (dmlist) { 1453 PetscValidPointer(dmlist,5); 1454 *dmlist = 0; 1455 } 1456 /* 1457 Is it a good idea to apply the following check across all impls? 1458 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1459 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1460 */ 1461 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1462 if (!dm->ops->createfielddecomposition) { 1463 PetscSection section; 1464 PetscInt numFields, f; 1465 1466 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1467 if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);} 1468 if (section && numFields && dm->ops->createsubdm) { 1469 *len = numFields; 1470 if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);} 1471 if (islist) {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);} 1472 if (dmlist) {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);} 1473 for (f = 0; f < numFields; ++f) { 1474 const char *fieldName; 1475 1476 ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr); 1477 if (namelist) { 1478 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1479 ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr); 1480 } 1481 } 1482 } else { 1483 ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr); 1484 /* By default there are no DMs associated with subproblems. */ 1485 if (dmlist) *dmlist = NULL; 1486 } 1487 } else { 1488 ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr); 1489 } 1490 PetscFunctionReturn(0); 1491 } 1492 1493 #undef __FUNCT__ 1494 #define __FUNCT__ "DMCreateSubDM" 1495 /*@ 1496 DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in. 1497 The fields are defined by DMCreateFieldIS(). 1498 1499 Not collective 1500 1501 Input Parameters: 1502 + dm - the DM object 1503 . numFields - number of fields in this subproblem 1504 - len - The number of subproblems in the decomposition (or NULL if not requested) 1505 1506 Output Parameters: 1507 . is - The global indices for the subproblem 1508 - dm - The DM for the subproblem 1509 1510 Level: intermediate 1511 1512 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1513 @*/ 1514 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1515 { 1516 PetscErrorCode ierr; 1517 1518 PetscFunctionBegin; 1519 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1520 PetscValidPointer(fields,3); 1521 if (is) PetscValidPointer(is,4); 1522 if (subdm) PetscValidPointer(subdm,5); 1523 if (dm->ops->createsubdm) { 1524 ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1525 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined"); 1526 PetscFunctionReturn(0); 1527 } 1528 1529 1530 #undef __FUNCT__ 1531 #define __FUNCT__ "DMCreateDomainDecomposition" 1532 /*@C 1533 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems 1534 corresponding to restrictions to pairs nested subdomains: each IS contains the global 1535 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually 1536 define a nonoverlapping covering, while outer subdomains can overlap. 1537 The optional list of DMs define the DM for each subproblem. 1538 1539 Not collective 1540 1541 Input Parameter: 1542 . dm - the DM object 1543 1544 Output Parameters: 1545 + len - The number of subproblems in the domain decomposition (or NULL if not requested) 1546 . namelist - The name for each subdomain (or NULL if not requested) 1547 . innerislist - The global indices for each inner subdomain (or NULL, if not requested) 1548 . outerislist - The global indices for each outer subdomain (or NULL, if not requested) 1549 - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1550 1551 Level: intermediate 1552 1553 Notes: 1554 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1555 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1556 and all of the arrays should be freed with PetscFree(). 1557 1558 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition() 1559 @*/ 1560 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 1561 { 1562 PetscErrorCode ierr; 1563 DMSubDomainHookLink link; 1564 PetscInt i,l; 1565 1566 PetscFunctionBegin; 1567 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1568 if (len) {PetscValidPointer(len,2); *len = 0;} 1569 if (namelist) {PetscValidPointer(namelist,3); *namelist = NULL;} 1570 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = NULL;} 1571 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = NULL;} 1572 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = NULL;} 1573 /* 1574 Is it a good idea to apply the following check across all impls? 1575 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1576 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1577 */ 1578 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1579 if (dm->ops->createdomaindecomposition) { 1580 ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr); 1581 /* copy subdomain hooks and context over to the subdomain DMs */ 1582 if (dmlist) { 1583 for (i = 0; i < l; i++) { 1584 for (link=dm->subdomainhook; link; link=link->next) { 1585 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);} 1586 } 1587 (*dmlist)[i]->ctx = dm->ctx; 1588 } 1589 } 1590 if (len) *len = l; 1591 } 1592 PetscFunctionReturn(0); 1593 } 1594 1595 1596 #undef __FUNCT__ 1597 #define __FUNCT__ "DMCreateDomainDecompositionScatters" 1598 /*@C 1599 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector 1600 1601 Not collective 1602 1603 Input Parameters: 1604 + dm - the DM object 1605 . n - the number of subdomain scatters 1606 - subdms - the local subdomains 1607 1608 Output Parameters: 1609 + n - the number of scatters returned 1610 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain 1611 . oscat - scatter from global vector to overlapping global vector entries on subdomain 1612 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts) 1613 1614 Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution 1615 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets 1616 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of 1617 solution and residual data. 1618 1619 Level: developer 1620 1621 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1622 @*/ 1623 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat) 1624 { 1625 PetscErrorCode ierr; 1626 1627 PetscFunctionBegin; 1628 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1629 PetscValidPointer(subdms,3); 1630 if (dm->ops->createddscatters) { 1631 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr); 1632 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionLocalScatter implementation defined"); 1633 PetscFunctionReturn(0); 1634 } 1635 1636 #undef __FUNCT__ 1637 #define __FUNCT__ "DMRefine" 1638 /*@ 1639 DMRefine - Refines a DM object 1640 1641 Collective on DM 1642 1643 Input Parameter: 1644 + dm - the DM object 1645 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1646 1647 Output Parameter: 1648 . dmf - the refined DM, or NULL 1649 1650 Note: If no refinement was done, the return value is NULL 1651 1652 Level: developer 1653 1654 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1655 @*/ 1656 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 1657 { 1658 PetscErrorCode ierr; 1659 DMRefineHookLink link; 1660 1661 PetscFunctionBegin; 1662 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1663 if (!dm->ops->refine) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot refine"); 1664 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr); 1665 if (*dmf) { 1666 (*dmf)->ops->creatematrix = dm->ops->creatematrix; 1667 1668 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr); 1669 1670 (*dmf)->ctx = dm->ctx; 1671 (*dmf)->leveldown = dm->leveldown; 1672 (*dmf)->levelup = dm->levelup + 1; 1673 1674 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr); 1675 for (link=dm->refinehook; link; link=link->next) { 1676 if (link->refinehook) { 1677 ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr); 1678 } 1679 } 1680 } 1681 PetscFunctionReturn(0); 1682 } 1683 1684 #undef __FUNCT__ 1685 #define __FUNCT__ "DMRefineHookAdd" 1686 /*@C 1687 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 1688 1689 Logically Collective 1690 1691 Input Arguments: 1692 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1693 . refinehook - function to run when setting up a coarser level 1694 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1695 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1696 1697 Calling sequence of refinehook: 1698 $ refinehook(DM coarse,DM fine,void *ctx); 1699 1700 + coarse - coarse level DM 1701 . fine - fine level DM to interpolate problem to 1702 - ctx - optional user-defined function context 1703 1704 Calling sequence for interphook: 1705 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 1706 1707 + coarse - coarse level DM 1708 . interp - matrix interpolating a coarse-level solution to the finer grid 1709 . fine - fine level DM to update 1710 - ctx - optional user-defined function context 1711 1712 Level: advanced 1713 1714 Notes: 1715 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 1716 1717 If this function is called multiple times, the hooks will be run in the order they are added. 1718 1719 This function is currently not available from Fortran. 1720 1721 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1722 @*/ 1723 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1724 { 1725 PetscErrorCode ierr; 1726 DMRefineHookLink link,*p; 1727 1728 PetscFunctionBegin; 1729 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1730 for (p=&coarse->refinehook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1731 ierr = PetscMalloc(sizeof(struct _DMRefineHookLink),&link);CHKERRQ(ierr); 1732 link->refinehook = refinehook; 1733 link->interphook = interphook; 1734 link->ctx = ctx; 1735 link->next = NULL; 1736 *p = link; 1737 PetscFunctionReturn(0); 1738 } 1739 1740 #undef __FUNCT__ 1741 #define __FUNCT__ "DMInterpolate" 1742 /*@ 1743 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 1744 1745 Collective if any hooks are 1746 1747 Input Arguments: 1748 + coarse - coarser DM to use as a base 1749 . restrct - interpolation matrix, apply using MatInterpolate() 1750 - fine - finer DM to update 1751 1752 Level: developer 1753 1754 .seealso: DMRefineHookAdd(), MatInterpolate() 1755 @*/ 1756 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 1757 { 1758 PetscErrorCode ierr; 1759 DMRefineHookLink link; 1760 1761 PetscFunctionBegin; 1762 for (link=fine->refinehook; link; link=link->next) { 1763 if (link->interphook) { 1764 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr); 1765 } 1766 } 1767 PetscFunctionReturn(0); 1768 } 1769 1770 #undef __FUNCT__ 1771 #define __FUNCT__ "DMGetRefineLevel" 1772 /*@ 1773 DMGetRefineLevel - Get's the number of refinements that have generated this DM. 1774 1775 Not Collective 1776 1777 Input Parameter: 1778 . dm - the DM object 1779 1780 Output Parameter: 1781 . level - number of refinements 1782 1783 Level: developer 1784 1785 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1786 1787 @*/ 1788 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 1789 { 1790 PetscFunctionBegin; 1791 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1792 *level = dm->levelup; 1793 PetscFunctionReturn(0); 1794 } 1795 1796 #undef __FUNCT__ 1797 #define __FUNCT__ "DMSetRefineLevel" 1798 /*@ 1799 DMSetRefineLevel - Set's the number of refinements that have generated this DM. 1800 1801 Not Collective 1802 1803 Input Parameter: 1804 + dm - the DM object 1805 - level - number of refinements 1806 1807 Level: advanced 1808 1809 Notes: This value is used by PCMG to determine how many multigrid levels to use 1810 1811 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1812 1813 @*/ 1814 PetscErrorCode DMSetRefineLevel(DM dm,PetscInt level) 1815 { 1816 PetscFunctionBegin; 1817 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1818 dm->levelup = level; 1819 PetscFunctionReturn(0); 1820 } 1821 1822 #undef __FUNCT__ 1823 #define __FUNCT__ "DMGlobalToLocalHookAdd" 1824 /*@C 1825 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called 1826 1827 Logically Collective 1828 1829 Input Arguments: 1830 + dm - the DM 1831 . beginhook - function to run at the beginning of DMGlobalToLocalBegin() 1832 . endhook - function to run after DMGlobalToLocalEnd() has completed 1833 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1834 1835 Calling sequence for beginhook: 1836 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1837 1838 + dm - global DM 1839 . g - global vector 1840 . mode - mode 1841 . l - local vector 1842 - ctx - optional user-defined function context 1843 1844 1845 Calling sequence for endhook: 1846 $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1847 1848 + global - global DM 1849 - ctx - optional user-defined function context 1850 1851 Level: advanced 1852 1853 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1854 @*/ 1855 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 1856 { 1857 PetscErrorCode ierr; 1858 DMGlobalToLocalHookLink link,*p; 1859 1860 PetscFunctionBegin; 1861 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1862 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1863 ierr = PetscMalloc(sizeof(struct _DMGlobalToLocalHookLink),&link);CHKERRQ(ierr); 1864 link->beginhook = beginhook; 1865 link->endhook = endhook; 1866 link->ctx = ctx; 1867 link->next = NULL; 1868 *p = link; 1869 PetscFunctionReturn(0); 1870 } 1871 1872 #undef __FUNCT__ 1873 #define __FUNCT__ "DMGlobalToLocalHook_Constraints" 1874 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx) 1875 { 1876 Mat cMat; 1877 Vec cVec; 1878 PetscSection section, cSec; 1879 PetscInt pStart, pEnd, p, dof; 1880 PetscErrorCode ierr; 1881 1882 PetscFunctionBegin; 1883 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1884 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 1885 if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) { 1886 PetscInt nRows; 1887 1888 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 1889 if (nRows <= 0) PetscFunctionReturn(0); 1890 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 1891 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 1892 ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr); 1893 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 1894 for (p = pStart; p < pEnd; p++) { 1895 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 1896 if (dof) { 1897 PetscScalar *vals; 1898 ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr); 1899 ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr); 1900 } 1901 } 1902 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 1903 } 1904 PetscFunctionReturn(0); 1905 } 1906 1907 #undef __FUNCT__ 1908 #define __FUNCT__ "DMGlobalToLocalBegin" 1909 /*@ 1910 DMGlobalToLocalBegin - Begins updating local vectors from global vector 1911 1912 Neighbor-wise Collective on DM 1913 1914 Input Parameters: 1915 + dm - the DM object 1916 . g - the global vector 1917 . mode - INSERT_VALUES or ADD_VALUES 1918 - l - the local vector 1919 1920 1921 Level: beginner 1922 1923 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1924 1925 @*/ 1926 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 1927 { 1928 PetscSF sf; 1929 PetscErrorCode ierr; 1930 DMGlobalToLocalHookLink link; 1931 1932 PetscFunctionBegin; 1933 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1934 for (link=dm->gtolhook; link; link=link->next) { 1935 if (link->beginhook) { 1936 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 1937 } 1938 } 1939 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1940 if (sf) { 1941 const PetscScalar *gArray; 1942 PetscScalar *lArray; 1943 1944 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1945 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1946 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 1947 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1948 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1949 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 1950 } else { 1951 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1952 } 1953 PetscFunctionReturn(0); 1954 } 1955 1956 #undef __FUNCT__ 1957 #define __FUNCT__ "DMGlobalToLocalEnd" 1958 /*@ 1959 DMGlobalToLocalEnd - Ends updating local vectors from global vector 1960 1961 Neighbor-wise Collective on DM 1962 1963 Input Parameters: 1964 + dm - the DM object 1965 . g - the global vector 1966 . mode - INSERT_VALUES or ADD_VALUES 1967 - l - the local vector 1968 1969 1970 Level: beginner 1971 1972 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1973 1974 @*/ 1975 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 1976 { 1977 PetscSF sf; 1978 PetscErrorCode ierr; 1979 const PetscScalar *gArray; 1980 PetscScalar *lArray; 1981 DMGlobalToLocalHookLink link; 1982 1983 PetscFunctionBegin; 1984 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1985 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1986 if (sf) { 1987 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1988 1989 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1990 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 1991 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1992 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1993 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 1994 } else { 1995 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1996 } 1997 ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr); 1998 for (link=dm->gtolhook; link; link=link->next) { 1999 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2000 } 2001 PetscFunctionReturn(0); 2002 } 2003 2004 #undef __FUNCT__ 2005 #define __FUNCT__ "DMLocalToGlobalHookAdd" 2006 /*@C 2007 DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called 2008 2009 Logically Collective 2010 2011 Input Arguments: 2012 + dm - the DM 2013 . beginhook - function to run at the beginning of DMLocalToGlobalBegin() 2014 . endhook - function to run after DMLocalToGlobalEnd() has completed 2015 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2016 2017 Calling sequence for beginhook: 2018 $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2019 2020 + dm - global DM 2021 . l - local vector 2022 . mode - mode 2023 . g - global vector 2024 - ctx - optional user-defined function context 2025 2026 2027 Calling sequence for endhook: 2028 $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2029 2030 + global - global DM 2031 . l - local vector 2032 . mode - mode 2033 . g - global vector 2034 - ctx - optional user-defined function context 2035 2036 Level: advanced 2037 2038 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2039 @*/ 2040 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 2041 { 2042 PetscErrorCode ierr; 2043 DMLocalToGlobalHookLink link,*p; 2044 2045 PetscFunctionBegin; 2046 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2047 for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2048 ierr = PetscMalloc(sizeof(struct _DMLocalToGlobalHookLink),&link);CHKERRQ(ierr); 2049 link->beginhook = beginhook; 2050 link->endhook = endhook; 2051 link->ctx = ctx; 2052 link->next = NULL; 2053 *p = link; 2054 PetscFunctionReturn(0); 2055 } 2056 2057 #undef __FUNCT__ 2058 #define __FUNCT__ "DMLocalToGlobalHook_Constraints" 2059 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx) 2060 { 2061 Mat cMat; 2062 Vec cVec; 2063 PetscSection section, cSec; 2064 PetscInt pStart, pEnd, p, dof; 2065 PetscErrorCode ierr; 2066 2067 PetscFunctionBegin; 2068 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2069 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 2070 if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) { 2071 PetscInt nRows; 2072 2073 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 2074 if (nRows <= 0) PetscFunctionReturn(0); 2075 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 2076 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 2077 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 2078 for (p = pStart; p < pEnd; p++) { 2079 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 2080 if (dof) { 2081 PetscInt d; 2082 PetscScalar *vals; 2083 ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr); 2084 ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr); 2085 /* for this to be the true transpose, we have to zero the values that 2086 * we just extracted */ 2087 for (d = 0; d < dof; d++) { 2088 vals[d] = 0.; 2089 } 2090 } 2091 } 2092 ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr); 2093 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2094 } 2095 PetscFunctionReturn(0); 2096 } 2097 2098 #undef __FUNCT__ 2099 #define __FUNCT__ "DMLocalToGlobalBegin" 2100 /*@ 2101 DMLocalToGlobalBegin - updates global vectors from local vectors 2102 2103 Neighbor-wise Collective on DM 2104 2105 Input Parameters: 2106 + dm - the DM object 2107 . l - the local vector 2108 . mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that base point. 2109 - g - the global vector 2110 2111 Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 2112 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one. 2113 2114 Level: beginner 2115 2116 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 2117 2118 @*/ 2119 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 2120 { 2121 PetscSF sf; 2122 PetscSection s, gs; 2123 DMLocalToGlobalHookLink link; 2124 const PetscScalar *lArray; 2125 PetscScalar *gArray; 2126 PetscBool isInsert; 2127 PetscErrorCode ierr; 2128 2129 PetscFunctionBegin; 2130 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2131 for (link=dm->ltoghook; link; link=link->next) { 2132 if (link->beginhook) { 2133 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr); 2134 } 2135 } 2136 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr); 2137 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2138 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 2139 switch (mode) { 2140 case INSERT_VALUES: 2141 case INSERT_ALL_VALUES: 2142 isInsert = PETSC_TRUE; break; 2143 case ADD_VALUES: 2144 case ADD_ALL_VALUES: 2145 isInsert = PETSC_FALSE; break; 2146 default: 2147 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2148 } 2149 if (sf && !isInsert) { 2150 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2151 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2152 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2153 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2154 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2155 } else if (s && isInsert) { 2156 PetscInt gStart, pStart, pEnd, p; 2157 2158 ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr); 2159 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 2160 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 2161 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2162 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2163 for (p = pStart; p < pEnd; ++p) { 2164 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 2165 2166 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 2167 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 2168 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 2169 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 2170 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 2171 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 2172 /* Ignore off-process data and points with no global data */ 2173 if (!gdof || goff < 0) continue; 2174 if (dof != gdof) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof); 2175 /* If no constraints are enforced in the global vector */ 2176 if (!gcdof) { 2177 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 2178 /* If constraints are enforced in the global vector */ 2179 } else if (cdof == gcdof) { 2180 const PetscInt *cdofs; 2181 PetscInt cind = 0; 2182 2183 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 2184 for (d = 0, e = 0; d < dof; ++d) { 2185 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 2186 gArray[goff-gStart+e++] = lArray[off+d]; 2187 } 2188 } else SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Inconsistent sizes, p: %d dof: %d gdof: %d cdof: %d gcdof: %d", p, dof, gdof, cdof, gcdof); 2189 } 2190 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2191 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2192 } else { 2193 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2194 } 2195 PetscFunctionReturn(0); 2196 } 2197 2198 #undef __FUNCT__ 2199 #define __FUNCT__ "DMLocalToGlobalEnd" 2200 /*@ 2201 DMLocalToGlobalEnd - updates global vectors from local vectors 2202 2203 Neighbor-wise Collective on DM 2204 2205 Input Parameters: 2206 + dm - the DM object 2207 . l - the local vector 2208 . mode - INSERT_VALUES or ADD_VALUES 2209 - g - the global vector 2210 2211 2212 Level: beginner 2213 2214 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 2215 2216 @*/ 2217 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 2218 { 2219 PetscSF sf; 2220 PetscSection s; 2221 DMLocalToGlobalHookLink link; 2222 PetscBool isInsert; 2223 PetscErrorCode ierr; 2224 2225 PetscFunctionBegin; 2226 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2227 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2228 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 2229 switch (mode) { 2230 case INSERT_VALUES: 2231 case INSERT_ALL_VALUES: 2232 isInsert = PETSC_TRUE; break; 2233 case ADD_VALUES: 2234 case ADD_ALL_VALUES: 2235 isInsert = PETSC_FALSE; break; 2236 default: 2237 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2238 } 2239 if (sf && !isInsert) { 2240 const PetscScalar *lArray; 2241 PetscScalar *gArray; 2242 2243 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2244 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2245 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2246 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2247 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2248 } else if (s && isInsert) { 2249 } else { 2250 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2251 } 2252 for (link=dm->ltoghook; link; link=link->next) { 2253 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2254 } 2255 PetscFunctionReturn(0); 2256 } 2257 2258 #undef __FUNCT__ 2259 #define __FUNCT__ "DMLocalToLocalBegin" 2260 /*@ 2261 DMLocalToLocalBegin - Maps from a local vector (including ghost points 2262 that contain irrelevant values) to another local vector where the ghost 2263 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 2264 2265 Neighbor-wise Collective on DM and Vec 2266 2267 Input Parameters: 2268 + dm - the DM object 2269 . g - the original local vector 2270 - mode - one of INSERT_VALUES or ADD_VALUES 2271 2272 Output Parameter: 2273 . l - the local vector with correct ghost values 2274 2275 Level: intermediate 2276 2277 Notes: 2278 The local vectors used here need not be the same as those 2279 obtained from DMCreateLocalVector(), BUT they 2280 must have the same parallel data layout; they could, for example, be 2281 obtained with VecDuplicate() from the DM originating vectors. 2282 2283 .keywords: DM, local-to-local, begin 2284 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2285 2286 @*/ 2287 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2288 { 2289 PetscErrorCode ierr; 2290 2291 PetscFunctionBegin; 2292 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2293 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2294 PetscFunctionReturn(0); 2295 } 2296 2297 #undef __FUNCT__ 2298 #define __FUNCT__ "DMLocalToLocalEnd" 2299 /*@ 2300 DMLocalToLocalEnd - Maps from a local vector (including ghost points 2301 that contain irrelevant values) to another local vector where the ghost 2302 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 2303 2304 Neighbor-wise Collective on DM and Vec 2305 2306 Input Parameters: 2307 + da - the DM object 2308 . g - the original local vector 2309 - mode - one of INSERT_VALUES or ADD_VALUES 2310 2311 Output Parameter: 2312 . l - the local vector with correct ghost values 2313 2314 Level: intermediate 2315 2316 Notes: 2317 The local vectors used here need not be the same as those 2318 obtained from DMCreateLocalVector(), BUT they 2319 must have the same parallel data layout; they could, for example, be 2320 obtained with VecDuplicate() from the DM originating vectors. 2321 2322 .keywords: DM, local-to-local, end 2323 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2324 2325 @*/ 2326 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2327 { 2328 PetscErrorCode ierr; 2329 2330 PetscFunctionBegin; 2331 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2332 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2333 PetscFunctionReturn(0); 2334 } 2335 2336 2337 #undef __FUNCT__ 2338 #define __FUNCT__ "DMCoarsen" 2339 /*@ 2340 DMCoarsen - Coarsens a DM object 2341 2342 Collective on DM 2343 2344 Input Parameter: 2345 + dm - the DM object 2346 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2347 2348 Output Parameter: 2349 . dmc - the coarsened DM 2350 2351 Level: developer 2352 2353 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2354 2355 @*/ 2356 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 2357 { 2358 PetscErrorCode ierr; 2359 DMCoarsenHookLink link; 2360 2361 PetscFunctionBegin; 2362 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2363 if (!dm->ops->coarsen) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot coarsen"); 2364 ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2365 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 2366 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 2367 ierr = DMSetCoarseDM(dm,*dmc);CHKERRQ(ierr); 2368 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2369 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2370 (*dmc)->ctx = dm->ctx; 2371 (*dmc)->levelup = dm->levelup; 2372 (*dmc)->leveldown = dm->leveldown + 1; 2373 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2374 for (link=dm->coarsenhook; link; link=link->next) { 2375 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2376 } 2377 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2378 PetscFunctionReturn(0); 2379 } 2380 2381 #undef __FUNCT__ 2382 #define __FUNCT__ "DMCoarsenHookAdd" 2383 /*@C 2384 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2385 2386 Logically Collective 2387 2388 Input Arguments: 2389 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2390 . coarsenhook - function to run when setting up a coarser level 2391 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2392 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2393 2394 Calling sequence of coarsenhook: 2395 $ coarsenhook(DM fine,DM coarse,void *ctx); 2396 2397 + fine - fine level DM 2398 . coarse - coarse level DM to restrict problem to 2399 - ctx - optional user-defined function context 2400 2401 Calling sequence for restricthook: 2402 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2403 2404 + fine - fine level DM 2405 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2406 . rscale - scaling vector for restriction 2407 . inject - matrix restricting by injection 2408 . coarse - coarse level DM to update 2409 - ctx - optional user-defined function context 2410 2411 Level: advanced 2412 2413 Notes: 2414 This function is only needed if auxiliary data needs to be set up on coarse grids. 2415 2416 If this function is called multiple times, the hooks will be run in the order they are added. 2417 2418 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2419 extract the finest level information from its context (instead of from the SNES). 2420 2421 This function is currently not available from Fortran. 2422 2423 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2424 @*/ 2425 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2426 { 2427 PetscErrorCode ierr; 2428 DMCoarsenHookLink link,*p; 2429 2430 PetscFunctionBegin; 2431 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2432 for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2433 ierr = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr); 2434 link->coarsenhook = coarsenhook; 2435 link->restricthook = restricthook; 2436 link->ctx = ctx; 2437 link->next = NULL; 2438 *p = link; 2439 PetscFunctionReturn(0); 2440 } 2441 2442 #undef __FUNCT__ 2443 #define __FUNCT__ "DMRestrict" 2444 /*@ 2445 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 2446 2447 Collective if any hooks are 2448 2449 Input Arguments: 2450 + fine - finer DM to use as a base 2451 . restrct - restriction matrix, apply using MatRestrict() 2452 . inject - injection matrix, also use MatRestrict() 2453 - coarse - coarer DM to update 2454 2455 Level: developer 2456 2457 .seealso: DMCoarsenHookAdd(), MatRestrict() 2458 @*/ 2459 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 2460 { 2461 PetscErrorCode ierr; 2462 DMCoarsenHookLink link; 2463 2464 PetscFunctionBegin; 2465 for (link=fine->coarsenhook; link; link=link->next) { 2466 if (link->restricthook) { 2467 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 2468 } 2469 } 2470 PetscFunctionReturn(0); 2471 } 2472 2473 #undef __FUNCT__ 2474 #define __FUNCT__ "DMSubDomainHookAdd" 2475 /*@C 2476 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 2477 2478 Logically Collective 2479 2480 Input Arguments: 2481 + global - global DM 2482 . ddhook - function to run to pass data to the decomposition DM upon its creation 2483 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2484 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2485 2486 2487 Calling sequence for ddhook: 2488 $ ddhook(DM global,DM block,void *ctx) 2489 2490 + global - global DM 2491 . block - block DM 2492 - ctx - optional user-defined function context 2493 2494 Calling sequence for restricthook: 2495 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 2496 2497 + global - global DM 2498 . out - scatter to the outer (with ghost and overlap points) block vector 2499 . in - scatter to block vector values only owned locally 2500 . block - block DM 2501 - ctx - optional user-defined function context 2502 2503 Level: advanced 2504 2505 Notes: 2506 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 2507 2508 If this function is called multiple times, the hooks will be run in the order they are added. 2509 2510 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2511 extract the global information from its context (instead of from the SNES). 2512 2513 This function is currently not available from Fortran. 2514 2515 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2516 @*/ 2517 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2518 { 2519 PetscErrorCode ierr; 2520 DMSubDomainHookLink link,*p; 2521 2522 PetscFunctionBegin; 2523 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2524 for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2525 ierr = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr); 2526 link->restricthook = restricthook; 2527 link->ddhook = ddhook; 2528 link->ctx = ctx; 2529 link->next = NULL; 2530 *p = link; 2531 PetscFunctionReturn(0); 2532 } 2533 2534 #undef __FUNCT__ 2535 #define __FUNCT__ "DMSubDomainRestrict" 2536 /*@ 2537 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 2538 2539 Collective if any hooks are 2540 2541 Input Arguments: 2542 + fine - finer DM to use as a base 2543 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 2544 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 2545 - coarse - coarer DM to update 2546 2547 Level: developer 2548 2549 .seealso: DMCoarsenHookAdd(), MatRestrict() 2550 @*/ 2551 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 2552 { 2553 PetscErrorCode ierr; 2554 DMSubDomainHookLink link; 2555 2556 PetscFunctionBegin; 2557 for (link=global->subdomainhook; link; link=link->next) { 2558 if (link->restricthook) { 2559 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2560 } 2561 } 2562 PetscFunctionReturn(0); 2563 } 2564 2565 #undef __FUNCT__ 2566 #define __FUNCT__ "DMGetCoarsenLevel" 2567 /*@ 2568 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2569 2570 Not Collective 2571 2572 Input Parameter: 2573 . dm - the DM object 2574 2575 Output Parameter: 2576 . level - number of coarsenings 2577 2578 Level: developer 2579 2580 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2581 2582 @*/ 2583 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2584 { 2585 PetscFunctionBegin; 2586 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2587 *level = dm->leveldown; 2588 PetscFunctionReturn(0); 2589 } 2590 2591 2592 2593 #undef __FUNCT__ 2594 #define __FUNCT__ "DMRefineHierarchy" 2595 /*@C 2596 DMRefineHierarchy - Refines a DM object, all levels at once 2597 2598 Collective on DM 2599 2600 Input Parameter: 2601 + dm - the DM object 2602 - nlevels - the number of levels of refinement 2603 2604 Output Parameter: 2605 . dmf - the refined DM hierarchy 2606 2607 Level: developer 2608 2609 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2610 2611 @*/ 2612 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 2613 { 2614 PetscErrorCode ierr; 2615 2616 PetscFunctionBegin; 2617 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2618 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2619 if (nlevels == 0) PetscFunctionReturn(0); 2620 if (dm->ops->refinehierarchy) { 2621 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2622 } else if (dm->ops->refine) { 2623 PetscInt i; 2624 2625 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2626 for (i=1; i<nlevels; i++) { 2627 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2628 } 2629 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2630 PetscFunctionReturn(0); 2631 } 2632 2633 #undef __FUNCT__ 2634 #define __FUNCT__ "DMCoarsenHierarchy" 2635 /*@C 2636 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2637 2638 Collective on DM 2639 2640 Input Parameter: 2641 + dm - the DM object 2642 - nlevels - the number of levels of coarsening 2643 2644 Output Parameter: 2645 . dmc - the coarsened DM hierarchy 2646 2647 Level: developer 2648 2649 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2650 2651 @*/ 2652 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 2653 { 2654 PetscErrorCode ierr; 2655 2656 PetscFunctionBegin; 2657 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2658 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2659 if (nlevels == 0) PetscFunctionReturn(0); 2660 PetscValidPointer(dmc,3); 2661 if (dm->ops->coarsenhierarchy) { 2662 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 2663 } else if (dm->ops->coarsen) { 2664 PetscInt i; 2665 2666 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 2667 for (i=1; i<nlevels; i++) { 2668 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 2669 } 2670 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 2671 PetscFunctionReturn(0); 2672 } 2673 2674 #undef __FUNCT__ 2675 #define __FUNCT__ "DMCreateAggregates" 2676 /*@ 2677 DMCreateAggregates - Gets the aggregates that map between 2678 grids associated with two DMs. 2679 2680 Collective on DM 2681 2682 Input Parameters: 2683 + dmc - the coarse grid DM 2684 - dmf - the fine grid DM 2685 2686 Output Parameters: 2687 . rest - the restriction matrix (transpose of the projection matrix) 2688 2689 Level: intermediate 2690 2691 .keywords: interpolation, restriction, multigrid 2692 2693 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 2694 @*/ 2695 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 2696 { 2697 PetscErrorCode ierr; 2698 2699 PetscFunctionBegin; 2700 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 2701 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 2702 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 2703 PetscFunctionReturn(0); 2704 } 2705 2706 #undef __FUNCT__ 2707 #define __FUNCT__ "DMSetApplicationContextDestroy" 2708 /*@C 2709 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 2710 2711 Not Collective 2712 2713 Input Parameters: 2714 + dm - the DM object 2715 - destroy - the destroy function 2716 2717 Level: intermediate 2718 2719 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2720 2721 @*/ 2722 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 2723 { 2724 PetscFunctionBegin; 2725 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2726 dm->ctxdestroy = destroy; 2727 PetscFunctionReturn(0); 2728 } 2729 2730 #undef __FUNCT__ 2731 #define __FUNCT__ "DMSetApplicationContext" 2732 /*@ 2733 DMSetApplicationContext - Set a user context into a DM object 2734 2735 Not Collective 2736 2737 Input Parameters: 2738 + dm - the DM object 2739 - ctx - the user context 2740 2741 Level: intermediate 2742 2743 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2744 2745 @*/ 2746 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 2747 { 2748 PetscFunctionBegin; 2749 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2750 dm->ctx = ctx; 2751 PetscFunctionReturn(0); 2752 } 2753 2754 #undef __FUNCT__ 2755 #define __FUNCT__ "DMGetApplicationContext" 2756 /*@ 2757 DMGetApplicationContext - Gets a user context from a DM object 2758 2759 Not Collective 2760 2761 Input Parameter: 2762 . dm - the DM object 2763 2764 Output Parameter: 2765 . ctx - the user context 2766 2767 Level: intermediate 2768 2769 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2770 2771 @*/ 2772 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 2773 { 2774 PetscFunctionBegin; 2775 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2776 *(void**)ctx = dm->ctx; 2777 PetscFunctionReturn(0); 2778 } 2779 2780 #undef __FUNCT__ 2781 #define __FUNCT__ "DMSetVariableBounds" 2782 /*@C 2783 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 2784 2785 Logically Collective on DM 2786 2787 Input Parameter: 2788 + dm - the DM object 2789 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 2790 2791 Level: intermediate 2792 2793 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 2794 DMSetJacobian() 2795 2796 @*/ 2797 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 2798 { 2799 PetscFunctionBegin; 2800 dm->ops->computevariablebounds = f; 2801 PetscFunctionReturn(0); 2802 } 2803 2804 #undef __FUNCT__ 2805 #define __FUNCT__ "DMHasVariableBounds" 2806 /*@ 2807 DMHasVariableBounds - does the DM object have a variable bounds function? 2808 2809 Not Collective 2810 2811 Input Parameter: 2812 . dm - the DM object to destroy 2813 2814 Output Parameter: 2815 . flg - PETSC_TRUE if the variable bounds function exists 2816 2817 Level: developer 2818 2819 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2820 2821 @*/ 2822 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 2823 { 2824 PetscFunctionBegin; 2825 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 2826 PetscFunctionReturn(0); 2827 } 2828 2829 #undef __FUNCT__ 2830 #define __FUNCT__ "DMComputeVariableBounds" 2831 /*@C 2832 DMComputeVariableBounds - compute variable bounds used by SNESVI. 2833 2834 Logically Collective on DM 2835 2836 Input Parameters: 2837 . dm - the DM object 2838 2839 Output parameters: 2840 + xl - lower bound 2841 - xu - upper bound 2842 2843 Level: advanced 2844 2845 Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 2846 2847 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2848 2849 @*/ 2850 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 2851 { 2852 PetscErrorCode ierr; 2853 2854 PetscFunctionBegin; 2855 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 2856 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 2857 if (dm->ops->computevariablebounds) { 2858 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 2859 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 2860 PetscFunctionReturn(0); 2861 } 2862 2863 #undef __FUNCT__ 2864 #define __FUNCT__ "DMHasColoring" 2865 /*@ 2866 DMHasColoring - does the DM object have a method of providing a coloring? 2867 2868 Not Collective 2869 2870 Input Parameter: 2871 . dm - the DM object 2872 2873 Output Parameter: 2874 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 2875 2876 Level: developer 2877 2878 .seealso DMHasFunction(), DMCreateColoring() 2879 2880 @*/ 2881 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 2882 { 2883 PetscFunctionBegin; 2884 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 2885 PetscFunctionReturn(0); 2886 } 2887 2888 #undef __FUNCT__ 2889 #define __FUNCT__ "DMHasCreateRestriction" 2890 /*@ 2891 DMHasCreateRestriction - does the DM object have a method of providing a restriction? 2892 2893 Not Collective 2894 2895 Input Parameter: 2896 . dm - the DM object 2897 2898 Output Parameter: 2899 . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction(). 2900 2901 Level: developer 2902 2903 .seealso DMHasFunction(), DMCreateRestriction() 2904 2905 @*/ 2906 PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg) 2907 { 2908 PetscFunctionBegin; 2909 *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE; 2910 PetscFunctionReturn(0); 2911 } 2912 2913 #undef __FUNCT__ 2914 #define __FUNCT__ "DMSetVec" 2915 /*@C 2916 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 2917 2918 Collective on DM 2919 2920 Input Parameter: 2921 + dm - the DM object 2922 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 2923 2924 Level: developer 2925 2926 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2927 2928 @*/ 2929 PetscErrorCode DMSetVec(DM dm,Vec x) 2930 { 2931 PetscErrorCode ierr; 2932 2933 PetscFunctionBegin; 2934 if (x) { 2935 if (!dm->x) { 2936 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 2937 } 2938 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 2939 } else if (dm->x) { 2940 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 2941 } 2942 PetscFunctionReturn(0); 2943 } 2944 2945 PetscFunctionList DMList = NULL; 2946 PetscBool DMRegisterAllCalled = PETSC_FALSE; 2947 2948 #undef __FUNCT__ 2949 #define __FUNCT__ "DMSetType" 2950 /*@C 2951 DMSetType - Builds a DM, for a particular DM implementation. 2952 2953 Collective on DM 2954 2955 Input Parameters: 2956 + dm - The DM object 2957 - method - The name of the DM type 2958 2959 Options Database Key: 2960 . -dm_type <type> - Sets the DM type; use -help for a list of available types 2961 2962 Notes: 2963 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 2964 2965 Level: intermediate 2966 2967 .keywords: DM, set, type 2968 .seealso: DMGetType(), DMCreate() 2969 @*/ 2970 PetscErrorCode DMSetType(DM dm, DMType method) 2971 { 2972 PetscErrorCode (*r)(DM); 2973 PetscBool match; 2974 PetscErrorCode ierr; 2975 2976 PetscFunctionBegin; 2977 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2978 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 2979 if (match) PetscFunctionReturn(0); 2980 2981 ierr = DMRegisterAll();CHKERRQ(ierr); 2982 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 2983 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 2984 2985 if (dm->ops->destroy) { 2986 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 2987 dm->ops->destroy = NULL; 2988 } 2989 ierr = (*r)(dm);CHKERRQ(ierr); 2990 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 2991 PetscFunctionReturn(0); 2992 } 2993 2994 #undef __FUNCT__ 2995 #define __FUNCT__ "DMGetType" 2996 /*@C 2997 DMGetType - Gets the DM type name (as a string) from the DM. 2998 2999 Not Collective 3000 3001 Input Parameter: 3002 . dm - The DM 3003 3004 Output Parameter: 3005 . type - The DM type name 3006 3007 Level: intermediate 3008 3009 .keywords: DM, get, type, name 3010 .seealso: DMSetType(), DMCreate() 3011 @*/ 3012 PetscErrorCode DMGetType(DM dm, DMType *type) 3013 { 3014 PetscErrorCode ierr; 3015 3016 PetscFunctionBegin; 3017 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3018 PetscValidPointer(type,2); 3019 ierr = DMRegisterAll();CHKERRQ(ierr); 3020 *type = ((PetscObject)dm)->type_name; 3021 PetscFunctionReturn(0); 3022 } 3023 3024 #undef __FUNCT__ 3025 #define __FUNCT__ "DMConvert" 3026 /*@C 3027 DMConvert - Converts a DM to another DM, either of the same or different type. 3028 3029 Collective on DM 3030 3031 Input Parameters: 3032 + dm - the DM 3033 - newtype - new DM type (use "same" for the same type) 3034 3035 Output Parameter: 3036 . M - pointer to new DM 3037 3038 Notes: 3039 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 3040 the MPI communicator of the generated DM is always the same as the communicator 3041 of the input DM. 3042 3043 Level: intermediate 3044 3045 .seealso: DMCreate() 3046 @*/ 3047 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 3048 { 3049 DM B; 3050 char convname[256]; 3051 PetscBool sametype/*, issame */; 3052 PetscErrorCode ierr; 3053 3054 PetscFunctionBegin; 3055 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3056 PetscValidType(dm,1); 3057 PetscValidPointer(M,3); 3058 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 3059 /* ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); */ 3060 if (sametype) { 3061 *M = dm; 3062 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 3063 PetscFunctionReturn(0); 3064 } else { 3065 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 3066 3067 /* 3068 Order of precedence: 3069 1) See if a specialized converter is known to the current DM. 3070 2) See if a specialized converter is known to the desired DM class. 3071 3) See if a good general converter is registered for the desired class 3072 4) See if a good general converter is known for the current matrix. 3073 5) Use a really basic converter. 3074 */ 3075 3076 /* 1) See if a specialized converter is known to the current DM and the desired class */ 3077 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 3078 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 3079 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 3080 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 3081 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 3082 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 3083 if (conv) goto foundconv; 3084 3085 /* 2) See if a specialized converter is known to the desired DM class. */ 3086 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 3087 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 3088 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 3089 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 3090 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 3091 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 3092 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 3093 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 3094 if (conv) { 3095 ierr = DMDestroy(&B);CHKERRQ(ierr); 3096 goto foundconv; 3097 } 3098 3099 #if 0 3100 /* 3) See if a good general converter is registered for the desired class */ 3101 conv = B->ops->convertfrom; 3102 ierr = DMDestroy(&B);CHKERRQ(ierr); 3103 if (conv) goto foundconv; 3104 3105 /* 4) See if a good general converter is known for the current matrix */ 3106 if (dm->ops->convert) { 3107 conv = dm->ops->convert; 3108 } 3109 if (conv) goto foundconv; 3110 #endif 3111 3112 /* 5) Use a really basic converter. */ 3113 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 3114 3115 foundconv: 3116 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3117 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 3118 /* Things that are independent of DM type: We should consult DMClone() here */ 3119 if (dm->maxCell) { 3120 const PetscReal *maxCell, *L; 3121 const DMBoundaryType *bd; 3122 ierr = DMGetPeriodicity(dm, &maxCell, &L, &bd);CHKERRQ(ierr); 3123 ierr = DMSetPeriodicity(*M, maxCell, L, bd);CHKERRQ(ierr); 3124 } 3125 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3126 } 3127 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 3128 PetscFunctionReturn(0); 3129 } 3130 3131 /*--------------------------------------------------------------------------------------------------------------------*/ 3132 3133 #undef __FUNCT__ 3134 #define __FUNCT__ "DMRegister" 3135 /*@C 3136 DMRegister - Adds a new DM component implementation 3137 3138 Not Collective 3139 3140 Input Parameters: 3141 + name - The name of a new user-defined creation routine 3142 - create_func - The creation routine itself 3143 3144 Notes: 3145 DMRegister() may be called multiple times to add several user-defined DMs 3146 3147 3148 Sample usage: 3149 .vb 3150 DMRegister("my_da", MyDMCreate); 3151 .ve 3152 3153 Then, your DM type can be chosen with the procedural interface via 3154 .vb 3155 DMCreate(MPI_Comm, DM *); 3156 DMSetType(DM,"my_da"); 3157 .ve 3158 or at runtime via the option 3159 .vb 3160 -da_type my_da 3161 .ve 3162 3163 Level: advanced 3164 3165 .keywords: DM, register 3166 .seealso: DMRegisterAll(), DMRegisterDestroy() 3167 3168 @*/ 3169 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 3170 { 3171 PetscErrorCode ierr; 3172 3173 PetscFunctionBegin; 3174 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 3175 PetscFunctionReturn(0); 3176 } 3177 3178 #undef __FUNCT__ 3179 #define __FUNCT__ "DMLoad" 3180 /*@C 3181 DMLoad - Loads a DM that has been stored in binary with DMView(). 3182 3183 Collective on PetscViewer 3184 3185 Input Parameters: 3186 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 3187 some related function before a call to DMLoad(). 3188 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 3189 HDF5 file viewer, obtained from PetscViewerHDF5Open() 3190 3191 Level: intermediate 3192 3193 Notes: 3194 The type is determined by the data in the file, any type set into the DM before this call is ignored. 3195 3196 Notes for advanced users: 3197 Most users should not need to know the details of the binary storage 3198 format, since DMLoad() and DMView() completely hide these details. 3199 But for anyone who's interested, the standard binary matrix storage 3200 format is 3201 .vb 3202 has not yet been determined 3203 .ve 3204 3205 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 3206 @*/ 3207 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 3208 { 3209 PetscBool isbinary, ishdf5; 3210 PetscErrorCode ierr; 3211 3212 PetscFunctionBegin; 3213 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 3214 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3215 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 3216 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 3217 if (isbinary) { 3218 PetscInt classid; 3219 char type[256]; 3220 3221 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3222 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3223 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3224 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3225 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3226 } else if (ishdf5) { 3227 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3228 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3229 PetscFunctionReturn(0); 3230 } 3231 3232 /******************************** FEM Support **********************************/ 3233 3234 #undef __FUNCT__ 3235 #define __FUNCT__ "DMPrintCellVector" 3236 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3237 { 3238 PetscInt f; 3239 PetscErrorCode ierr; 3240 3241 PetscFunctionBegin; 3242 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3243 for (f = 0; f < len; ++f) { 3244 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3245 } 3246 PetscFunctionReturn(0); 3247 } 3248 3249 #undef __FUNCT__ 3250 #define __FUNCT__ "DMPrintCellMatrix" 3251 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3252 { 3253 PetscInt f, g; 3254 PetscErrorCode ierr; 3255 3256 PetscFunctionBegin; 3257 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3258 for (f = 0; f < rows; ++f) { 3259 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3260 for (g = 0; g < cols; ++g) { 3261 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3262 } 3263 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3264 } 3265 PetscFunctionReturn(0); 3266 } 3267 3268 #undef __FUNCT__ 3269 #define __FUNCT__ "DMPrintLocalVec" 3270 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3271 { 3272 PetscMPIInt rank, numProcs; 3273 PetscInt p; 3274 PetscErrorCode ierr; 3275 3276 PetscFunctionBegin; 3277 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 3278 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 3279 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr); 3280 for (p = 0; p < numProcs; ++p) { 3281 if (p == rank) { 3282 Vec x; 3283 3284 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3285 ierr = VecCopy(X, x);CHKERRQ(ierr); 3286 ierr = VecChop(x, tol);CHKERRQ(ierr); 3287 ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3288 ierr = VecDestroy(&x);CHKERRQ(ierr); 3289 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3290 } 3291 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 3292 } 3293 PetscFunctionReturn(0); 3294 } 3295 3296 #undef __FUNCT__ 3297 #define __FUNCT__ "DMGetDefaultSection" 3298 /*@ 3299 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 3300 3301 Input Parameter: 3302 . dm - The DM 3303 3304 Output Parameter: 3305 . section - The PetscSection 3306 3307 Level: intermediate 3308 3309 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3310 3311 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3312 @*/ 3313 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 3314 { 3315 PetscErrorCode ierr; 3316 3317 PetscFunctionBegin; 3318 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3319 PetscValidPointer(section, 2); 3320 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3321 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3322 if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 3323 } 3324 *section = dm->defaultSection; 3325 PetscFunctionReturn(0); 3326 } 3327 3328 #undef __FUNCT__ 3329 #define __FUNCT__ "DMSetDefaultSection" 3330 /*@ 3331 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3332 3333 Input Parameters: 3334 + dm - The DM 3335 - section - The PetscSection 3336 3337 Level: intermediate 3338 3339 Note: Any existing Section will be destroyed 3340 3341 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3342 @*/ 3343 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 3344 { 3345 PetscInt numFields = 0; 3346 PetscInt f; 3347 PetscErrorCode ierr; 3348 3349 PetscFunctionBegin; 3350 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3351 if (section) { 3352 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3353 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3354 } 3355 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3356 dm->defaultSection = section; 3357 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3358 if (numFields) { 3359 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3360 for (f = 0; f < numFields; ++f) { 3361 PetscObject disc; 3362 const char *name; 3363 3364 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3365 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3366 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3367 } 3368 } 3369 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3370 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3371 PetscFunctionReturn(0); 3372 } 3373 3374 #undef __FUNCT__ 3375 #define __FUNCT__ "DMGetDefaultConstraints" 3376 /*@ 3377 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3378 3379 not collective 3380 3381 Input Parameter: 3382 . dm - The DM 3383 3384 Output Parameter: 3385 + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section. Returns NULL if there are no local constraints. 3386 - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section. Returns NULL if there are no local constraints. 3387 3388 Level: advanced 3389 3390 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3391 3392 .seealso: DMSetDefaultConstraints() 3393 @*/ 3394 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3395 { 3396 PetscErrorCode ierr; 3397 3398 PetscFunctionBegin; 3399 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3400 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3401 if (section) {*section = dm->defaultConstraintSection;} 3402 if (mat) {*mat = dm->defaultConstraintMat;} 3403 PetscFunctionReturn(0); 3404 } 3405 3406 #undef __FUNCT__ 3407 #define __FUNCT__ "DMSetDefaultConstraints" 3408 /*@ 3409 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3410 3411 If a constraint matrix is specified, then it is applied during DMGlobalToLocalEnd() when mode is INSERT_VALUES, INSERT_BC_VALUES, or INSERT_ALL_VALUES. Without a constraint matrix, the local vector l returned by DMGlobalToLocalEnd() contains values that have been scattered from a global vector without modification; with a constraint matrix A, l is modified by computing c = A * l, l[s[i]] = c[i], where the scatter s is defined by the PetscSection returned by DMGetDefaultConstraintMatrix(). 3412 3413 If a constraint matrix is specified, then its adjoint is applied during DMLocalToGlobalBegin() when mode is ADD_VALUES, ADD_BC_VALUES, or ADD_ALL_VALUES. Without a constraint matrix, the local vector l is accumulated into a global vector without modification; with a constraint matrix A, l is first modified by computing c[i] = l[s[i]], l[s[i]] = 0, l = l + A'*c, which is the adjoint of the operation described above. 3414 3415 collective on dm 3416 3417 Input Parameters: 3418 + dm - The DM 3419 + section - The PetscSection describing the range of the constraint matrix: relates rows of the constraint matrix to dofs of the default section. Must have a local communicator (PETSC_COMM_SELF or derivative). 3420 - mat - The Mat that interpolates local constraints: its width should be the layout size of the default section: NULL indicates no constraints. Must have a local communicator (PETSC_COMM_SELF or derivative). 3421 3422 Level: advanced 3423 3424 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3425 3426 .seealso: DMGetDefaultConstraints() 3427 @*/ 3428 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3429 { 3430 PetscMPIInt result; 3431 PetscErrorCode ierr; 3432 3433 PetscFunctionBegin; 3434 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3435 if (section) { 3436 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3437 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3438 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3439 } 3440 if (mat) { 3441 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3442 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3443 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3444 } 3445 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3446 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3447 dm->defaultConstraintSection = section; 3448 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3449 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3450 dm->defaultConstraintMat = mat; 3451 PetscFunctionReturn(0); 3452 } 3453 3454 #ifdef PETSC_USE_DEBUG 3455 #undef __FUNCT__ 3456 #define __FUNCT__ "DMDefaultSectionCheckConsistency_Internal" 3457 /* 3458 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3459 3460 Input Parameters: 3461 + dm - The DM 3462 . localSection - PetscSection describing the local data layout 3463 - globalSection - PetscSection describing the global data layout 3464 3465 Level: intermediate 3466 3467 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3468 */ 3469 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3470 { 3471 MPI_Comm comm; 3472 PetscLayout layout; 3473 const PetscInt *ranges; 3474 PetscInt pStart, pEnd, p, nroots; 3475 PetscMPIInt size, rank; 3476 PetscBool valid = PETSC_TRUE, gvalid; 3477 PetscErrorCode ierr; 3478 3479 PetscFunctionBegin; 3480 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3481 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3482 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3483 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3484 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3485 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3486 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3487 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3488 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3489 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3490 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3491 for (p = pStart; p < pEnd; ++p) { 3492 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3493 3494 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3495 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3496 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3497 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3498 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3499 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3500 if (!gdof) continue; /* Censored point */ 3501 if ((gdof < 0 ? -(gdof+1) : gdof) != dof) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global dof %d for point %d not equal to local dof %d\n", rank, gdof, p, dof);CHKERRQ(ierr); valid = PETSC_FALSE;} 3502 if (gcdof && (gcdof != cdof)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Global constraints %d for point %d not equal to local constraints %d\n", rank, gcdof, p, cdof);CHKERRQ(ierr); valid = PETSC_FALSE;} 3503 if (gdof < 0) { 3504 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3505 for (d = 0; d < gsize; ++d) { 3506 PetscInt offset = -(goff+1) + d, r; 3507 3508 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3509 if (r < 0) r = -(r+2); 3510 if ((r < 0) || (r >= size)) {ierr = PetscSynchronizedPrintf(comm, "[%d]Point %d mapped to invalid process %d (%d, %d)\n", rank, p, r, gdof, goff);CHKERRQ(ierr); valid = PETSC_FALSE;break;} 3511 } 3512 } 3513 } 3514 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3515 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3516 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3517 if (!gvalid) { 3518 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3519 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3520 } 3521 PetscFunctionReturn(0); 3522 } 3523 #endif 3524 3525 #undef __FUNCT__ 3526 #define __FUNCT__ "DMGetDefaultGlobalSection" 3527 /*@ 3528 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3529 3530 Collective on DM 3531 3532 Input Parameter: 3533 . dm - The DM 3534 3535 Output Parameter: 3536 . section - The PetscSection 3537 3538 Level: intermediate 3539 3540 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3541 3542 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3543 @*/ 3544 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3545 { 3546 PetscErrorCode ierr; 3547 3548 PetscFunctionBegin; 3549 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3550 PetscValidPointer(section, 2); 3551 if (!dm->defaultGlobalSection) { 3552 PetscSection s; 3553 3554 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3555 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3556 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3557 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3558 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3559 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3560 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 3561 } 3562 *section = dm->defaultGlobalSection; 3563 PetscFunctionReturn(0); 3564 } 3565 3566 #undef __FUNCT__ 3567 #define __FUNCT__ "DMSetDefaultGlobalSection" 3568 /*@ 3569 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3570 3571 Input Parameters: 3572 + dm - The DM 3573 - section - The PetscSection, or NULL 3574 3575 Level: intermediate 3576 3577 Note: Any existing Section will be destroyed 3578 3579 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3580 @*/ 3581 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3582 { 3583 PetscErrorCode ierr; 3584 3585 PetscFunctionBegin; 3586 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3587 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3588 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3589 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3590 dm->defaultGlobalSection = section; 3591 #ifdef PETSC_USE_DEBUG 3592 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3593 #endif 3594 PetscFunctionReturn(0); 3595 } 3596 3597 #undef __FUNCT__ 3598 #define __FUNCT__ "DMGetDefaultSF" 3599 /*@ 3600 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3601 it is created from the default PetscSection layouts in the DM. 3602 3603 Input Parameter: 3604 . dm - The DM 3605 3606 Output Parameter: 3607 . sf - The PetscSF 3608 3609 Level: intermediate 3610 3611 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3612 3613 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3614 @*/ 3615 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3616 { 3617 PetscInt nroots; 3618 PetscErrorCode ierr; 3619 3620 PetscFunctionBegin; 3621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3622 PetscValidPointer(sf, 2); 3623 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3624 if (nroots < 0) { 3625 PetscSection section, gSection; 3626 3627 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3628 if (section) { 3629 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3630 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3631 } else { 3632 *sf = NULL; 3633 PetscFunctionReturn(0); 3634 } 3635 } 3636 *sf = dm->defaultSF; 3637 PetscFunctionReturn(0); 3638 } 3639 3640 #undef __FUNCT__ 3641 #define __FUNCT__ "DMSetDefaultSF" 3642 /*@ 3643 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3644 3645 Input Parameters: 3646 + dm - The DM 3647 - sf - The PetscSF 3648 3649 Level: intermediate 3650 3651 Note: Any previous SF is destroyed 3652 3653 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3654 @*/ 3655 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3656 { 3657 PetscErrorCode ierr; 3658 3659 PetscFunctionBegin; 3660 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3661 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3662 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3663 dm->defaultSF = sf; 3664 PetscFunctionReturn(0); 3665 } 3666 3667 #undef __FUNCT__ 3668 #define __FUNCT__ "DMCreateDefaultSF" 3669 /*@C 3670 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3671 describing the data layout. 3672 3673 Input Parameters: 3674 + dm - The DM 3675 . localSection - PetscSection describing the local data layout 3676 - globalSection - PetscSection describing the global data layout 3677 3678 Level: intermediate 3679 3680 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3681 @*/ 3682 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3683 { 3684 MPI_Comm comm; 3685 PetscLayout layout; 3686 const PetscInt *ranges; 3687 PetscInt *local; 3688 PetscSFNode *remote; 3689 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3690 PetscMPIInt size, rank; 3691 PetscErrorCode ierr; 3692 3693 PetscFunctionBegin; 3694 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3695 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3696 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3697 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3698 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3699 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3700 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3701 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3702 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3703 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3704 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3705 for (p = pStart; p < pEnd; ++p) { 3706 PetscInt gdof, gcdof; 3707 3708 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3709 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3710 if (gcdof > (gdof < 0 ? -(gdof+1) : gdof)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d has %d constraints > %d dof", p, gcdof, (gdof < 0 ? -(gdof+1) : gdof)); 3711 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3712 } 3713 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3714 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3715 for (p = pStart, l = 0; p < pEnd; ++p) { 3716 const PetscInt *cind; 3717 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3718 3719 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3720 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3721 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3722 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3723 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3724 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3725 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3726 if (!gdof) continue; /* Censored point */ 3727 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3728 if (gsize != dof-cdof) { 3729 if (gsize != dof) SETERRQ4(comm, PETSC_ERR_ARG_WRONG, "Global dof %d for point %d is neither the constrained size %d, nor the unconstrained %d", gsize, p, dof-cdof, dof); 3730 cdof = 0; /* Ignore constraints */ 3731 } 3732 for (d = 0, c = 0; d < dof; ++d) { 3733 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3734 local[l+d-c] = off+d; 3735 } 3736 if (gdof < 0) { 3737 for (d = 0; d < gsize; ++d, ++l) { 3738 PetscInt offset = -(goff+1) + d, r; 3739 3740 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3741 if (r < 0) r = -(r+2); 3742 if ((r < 0) || (r >= size)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d mapped to invalid process %d (%d, %d)", p, r, gdof, goff); 3743 remote[l].rank = r; 3744 remote[l].index = offset - ranges[r]; 3745 } 3746 } else { 3747 for (d = 0; d < gsize; ++d, ++l) { 3748 remote[l].rank = rank; 3749 remote[l].index = goff+d - ranges[rank]; 3750 } 3751 } 3752 } 3753 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3754 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3755 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3756 PetscFunctionReturn(0); 3757 } 3758 3759 #undef __FUNCT__ 3760 #define __FUNCT__ "DMGetPointSF" 3761 /*@ 3762 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3763 3764 Input Parameter: 3765 . dm - The DM 3766 3767 Output Parameter: 3768 . sf - The PetscSF 3769 3770 Level: intermediate 3771 3772 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3773 3774 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3775 @*/ 3776 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3777 { 3778 PetscFunctionBegin; 3779 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3780 PetscValidPointer(sf, 2); 3781 *sf = dm->sf; 3782 PetscFunctionReturn(0); 3783 } 3784 3785 #undef __FUNCT__ 3786 #define __FUNCT__ "DMSetPointSF" 3787 /*@ 3788 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3789 3790 Input Parameters: 3791 + dm - The DM 3792 - sf - The PetscSF 3793 3794 Level: intermediate 3795 3796 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3797 @*/ 3798 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3799 { 3800 PetscErrorCode ierr; 3801 3802 PetscFunctionBegin; 3803 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3804 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3805 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3806 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3807 dm->sf = sf; 3808 PetscFunctionReturn(0); 3809 } 3810 3811 #undef __FUNCT__ 3812 #define __FUNCT__ "DMGetDS" 3813 /*@ 3814 DMGetDS - Get the PetscDS 3815 3816 Input Parameter: 3817 . dm - The DM 3818 3819 Output Parameter: 3820 . prob - The PetscDS 3821 3822 Level: developer 3823 3824 .seealso: DMSetDS() 3825 @*/ 3826 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3827 { 3828 PetscFunctionBegin; 3829 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3830 PetscValidPointer(prob, 2); 3831 *prob = dm->prob; 3832 PetscFunctionReturn(0); 3833 } 3834 3835 #undef __FUNCT__ 3836 #define __FUNCT__ "DMSetDS" 3837 /*@ 3838 DMSetDS - Set the PetscDS 3839 3840 Input Parameters: 3841 + dm - The DM 3842 - prob - The PetscDS 3843 3844 Level: developer 3845 3846 .seealso: DMGetDS() 3847 @*/ 3848 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3849 { 3850 PetscErrorCode ierr; 3851 3852 PetscFunctionBegin; 3853 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3854 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3855 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3856 dm->prob = prob; 3857 ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr); 3858 PetscFunctionReturn(0); 3859 } 3860 3861 #undef __FUNCT__ 3862 #define __FUNCT__ "DMGetNumFields" 3863 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3864 { 3865 PetscErrorCode ierr; 3866 3867 PetscFunctionBegin; 3868 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3869 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3870 PetscFunctionReturn(0); 3871 } 3872 3873 #undef __FUNCT__ 3874 #define __FUNCT__ "DMSetNumFields" 3875 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3876 { 3877 PetscInt Nf, f; 3878 PetscErrorCode ierr; 3879 3880 PetscFunctionBegin; 3881 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3882 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3883 for (f = Nf; f < numFields; ++f) { 3884 PetscContainer obj; 3885 3886 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3887 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3888 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3889 } 3890 PetscFunctionReturn(0); 3891 } 3892 3893 #undef __FUNCT__ 3894 #define __FUNCT__ "DMGetField" 3895 /*@ 3896 DMGetField - Return the discretization object for a given DM field 3897 3898 Not collective 3899 3900 Input Parameters: 3901 + dm - The DM 3902 - f - The field number 3903 3904 Output Parameter: 3905 . field - The discretization object 3906 3907 Level: developer 3908 3909 .seealso: DMSetField() 3910 @*/ 3911 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3912 { 3913 PetscErrorCode ierr; 3914 3915 PetscFunctionBegin; 3916 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3917 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3918 PetscFunctionReturn(0); 3919 } 3920 3921 #undef __FUNCT__ 3922 #define __FUNCT__ "DMSetField" 3923 /*@ 3924 DMSetField - Set the discretization object for a given DM field 3925 3926 Logically collective on DM 3927 3928 Input Parameters: 3929 + dm - The DM 3930 . f - The field number 3931 - field - The discretization object 3932 3933 Level: developer 3934 3935 .seealso: DMGetField() 3936 @*/ 3937 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3938 { 3939 PetscErrorCode ierr; 3940 3941 PetscFunctionBegin; 3942 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3943 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3944 PetscFunctionReturn(0); 3945 } 3946 3947 #undef __FUNCT__ 3948 #define __FUNCT__ "DMRestrictHook_Coordinates" 3949 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3950 { 3951 DM dm_coord,dmc_coord; 3952 PetscErrorCode ierr; 3953 Vec coords,ccoords; 3954 Mat inject; 3955 PetscFunctionBegin; 3956 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3957 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3958 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3959 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3960 if (coords && !ccoords) { 3961 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3962 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 3963 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 3964 ierr = MatDestroy(&inject);CHKERRQ(ierr); 3965 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3966 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3967 } 3968 PetscFunctionReturn(0); 3969 } 3970 3971 #undef __FUNCT__ 3972 #define __FUNCT__ "DMSubDomainHook_Coordinates" 3973 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 3974 { 3975 DM dm_coord,subdm_coord; 3976 PetscErrorCode ierr; 3977 Vec coords,ccoords,clcoords; 3978 VecScatter *scat_i,*scat_g; 3979 PetscFunctionBegin; 3980 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3981 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 3982 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3983 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 3984 if (coords && !ccoords) { 3985 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 3986 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 3987 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 3988 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 3989 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3990 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3991 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3992 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3993 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 3994 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 3995 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 3996 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 3997 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3998 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 3999 ierr = PetscFree(scat_i);CHKERRQ(ierr); 4000 ierr = PetscFree(scat_g);CHKERRQ(ierr); 4001 } 4002 PetscFunctionReturn(0); 4003 } 4004 4005 #undef __FUNCT__ 4006 #define __FUNCT__ "DMGetDimension" 4007 /*@ 4008 DMGetDimension - Return the topological dimension of the DM 4009 4010 Not collective 4011 4012 Input Parameter: 4013 . dm - The DM 4014 4015 Output Parameter: 4016 . dim - The topological dimension 4017 4018 Level: beginner 4019 4020 .seealso: DMSetDimension(), DMCreate() 4021 @*/ 4022 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 4023 { 4024 PetscFunctionBegin; 4025 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4026 PetscValidPointer(dim, 2); 4027 *dim = dm->dim; 4028 PetscFunctionReturn(0); 4029 } 4030 4031 #undef __FUNCT__ 4032 #define __FUNCT__ "DMSetDimension" 4033 /*@ 4034 DMSetDimension - Set the topological dimension of the DM 4035 4036 Collective on dm 4037 4038 Input Parameters: 4039 + dm - The DM 4040 - dim - The topological dimension 4041 4042 Level: beginner 4043 4044 .seealso: DMGetDimension(), DMCreate() 4045 @*/ 4046 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 4047 { 4048 PetscFunctionBegin; 4049 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4050 PetscValidLogicalCollectiveInt(dm, dim, 2); 4051 dm->dim = dim; 4052 PetscFunctionReturn(0); 4053 } 4054 4055 #undef __FUNCT__ 4056 #define __FUNCT__ "DMGetDimPoints" 4057 /*@ 4058 DMGetDimPoints - Get the half-open interval for all points of a given dimension 4059 4060 Collective on DM 4061 4062 Input Parameters: 4063 + dm - the DM 4064 - dim - the dimension 4065 4066 Output Parameters: 4067 + pStart - The first point of the given dimension 4068 . pEnd - The first point following points of the given dimension 4069 4070 Note: 4071 The points are vertices in the Hasse diagram encoding the topology. This is explained in 4072 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 4073 then the interval is empty. 4074 4075 Level: intermediate 4076 4077 .keywords: point, Hasse Diagram, dimension 4078 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 4079 @*/ 4080 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4081 { 4082 PetscInt d; 4083 PetscErrorCode ierr; 4084 4085 PetscFunctionBegin; 4086 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4087 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 4088 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 4089 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 4090 PetscFunctionReturn(0); 4091 } 4092 4093 #undef __FUNCT__ 4094 #define __FUNCT__ "DMSetCoordinates" 4095 /*@ 4096 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 4097 4098 Collective on DM 4099 4100 Input Parameters: 4101 + dm - the DM 4102 - c - coordinate vector 4103 4104 Note: 4105 The coordinates do include those for ghost points, which are in the local vector 4106 4107 Level: intermediate 4108 4109 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4110 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 4111 @*/ 4112 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 4113 { 4114 PetscErrorCode ierr; 4115 4116 PetscFunctionBegin; 4117 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4118 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4119 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4120 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4121 dm->coordinates = c; 4122 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4123 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4124 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4125 PetscFunctionReturn(0); 4126 } 4127 4128 #undef __FUNCT__ 4129 #define __FUNCT__ "DMSetCoordinatesLocal" 4130 /*@ 4131 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 4132 4133 Collective on DM 4134 4135 Input Parameters: 4136 + dm - the DM 4137 - c - coordinate vector 4138 4139 Note: 4140 The coordinates of ghost points can be set using DMSetCoordinates() 4141 followed by DMGetCoordinatesLocal(). This is intended to enable the 4142 setting of ghost coordinates outside of the domain. 4143 4144 Level: intermediate 4145 4146 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4147 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 4148 @*/ 4149 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 4150 { 4151 PetscErrorCode ierr; 4152 4153 PetscFunctionBegin; 4154 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4155 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4156 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4157 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4158 4159 dm->coordinatesLocal = c; 4160 4161 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4162 PetscFunctionReturn(0); 4163 } 4164 4165 #undef __FUNCT__ 4166 #define __FUNCT__ "DMGetCoordinates" 4167 /*@ 4168 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 4169 4170 Not Collective 4171 4172 Input Parameter: 4173 . dm - the DM 4174 4175 Output Parameter: 4176 . c - global coordinate vector 4177 4178 Note: 4179 This is a borrowed reference, so the user should NOT destroy this vector 4180 4181 Each process has only the local coordinates (does NOT have the ghost coordinates). 4182 4183 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4184 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4185 4186 Level: intermediate 4187 4188 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4189 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4190 @*/ 4191 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4192 { 4193 PetscErrorCode ierr; 4194 4195 PetscFunctionBegin; 4196 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4197 PetscValidPointer(c,2); 4198 if (!dm->coordinates && dm->coordinatesLocal) { 4199 DM cdm = NULL; 4200 4201 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4202 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4203 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4204 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4205 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4206 } 4207 *c = dm->coordinates; 4208 PetscFunctionReturn(0); 4209 } 4210 4211 #undef __FUNCT__ 4212 #define __FUNCT__ "DMGetCoordinatesLocal" 4213 /*@ 4214 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4215 4216 Collective on DM 4217 4218 Input Parameter: 4219 . dm - the DM 4220 4221 Output Parameter: 4222 . c - coordinate vector 4223 4224 Note: 4225 This is a borrowed reference, so the user should NOT destroy this vector 4226 4227 Each process has the local and ghost coordinates 4228 4229 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4230 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4231 4232 Level: intermediate 4233 4234 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4235 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4236 @*/ 4237 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4238 { 4239 PetscErrorCode ierr; 4240 4241 PetscFunctionBegin; 4242 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4243 PetscValidPointer(c,2); 4244 if (!dm->coordinatesLocal && dm->coordinates) { 4245 DM cdm = NULL; 4246 4247 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4248 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4249 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4250 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4251 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4252 } 4253 *c = dm->coordinatesLocal; 4254 PetscFunctionReturn(0); 4255 } 4256 4257 #undef __FUNCT__ 4258 #define __FUNCT__ "DMGetCoordinateDM" 4259 /*@ 4260 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4261 4262 Collective on DM 4263 4264 Input Parameter: 4265 . dm - the DM 4266 4267 Output Parameter: 4268 . cdm - coordinate DM 4269 4270 Level: intermediate 4271 4272 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4273 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4274 @*/ 4275 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4276 { 4277 PetscErrorCode ierr; 4278 4279 PetscFunctionBegin; 4280 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4281 PetscValidPointer(cdm,2); 4282 if (!dm->coordinateDM) { 4283 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4284 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 4285 } 4286 *cdm = dm->coordinateDM; 4287 PetscFunctionReturn(0); 4288 } 4289 4290 #undef __FUNCT__ 4291 #define __FUNCT__ "DMSetCoordinateDM" 4292 /*@ 4293 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4294 4295 Logically Collective on DM 4296 4297 Input Parameters: 4298 + dm - the DM 4299 - cdm - coordinate DM 4300 4301 Level: intermediate 4302 4303 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4304 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4305 @*/ 4306 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4307 { 4308 PetscErrorCode ierr; 4309 4310 PetscFunctionBegin; 4311 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4312 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4313 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4314 dm->coordinateDM = cdm; 4315 ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr); 4316 PetscFunctionReturn(0); 4317 } 4318 4319 #undef __FUNCT__ 4320 #define __FUNCT__ "DMGetCoordinateDim" 4321 /*@ 4322 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4323 4324 Not Collective 4325 4326 Input Parameter: 4327 . dm - The DM object 4328 4329 Output Parameter: 4330 . dim - The embedding dimension 4331 4332 Level: intermediate 4333 4334 .keywords: mesh, coordinates 4335 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4336 @*/ 4337 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4338 { 4339 PetscFunctionBegin; 4340 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4341 PetscValidPointer(dim, 2); 4342 if (dm->dimEmbed == PETSC_DEFAULT) { 4343 dm->dimEmbed = dm->dim; 4344 } 4345 *dim = dm->dimEmbed; 4346 PetscFunctionReturn(0); 4347 } 4348 4349 #undef __FUNCT__ 4350 #define __FUNCT__ "DMSetCoordinateDim" 4351 /*@ 4352 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4353 4354 Not Collective 4355 4356 Input Parameters: 4357 + dm - The DM object 4358 - dim - The embedding dimension 4359 4360 Level: intermediate 4361 4362 .keywords: mesh, coordinates 4363 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4364 @*/ 4365 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4366 { 4367 PetscFunctionBegin; 4368 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4369 dm->dimEmbed = dim; 4370 PetscFunctionReturn(0); 4371 } 4372 4373 #undef __FUNCT__ 4374 #define __FUNCT__ "DMGetCoordinateSection" 4375 /*@ 4376 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4377 4378 Not Collective 4379 4380 Input Parameter: 4381 . dm - The DM object 4382 4383 Output Parameter: 4384 . section - The PetscSection object 4385 4386 Level: intermediate 4387 4388 .keywords: mesh, coordinates 4389 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4390 @*/ 4391 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4392 { 4393 DM cdm; 4394 PetscErrorCode ierr; 4395 4396 PetscFunctionBegin; 4397 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4398 PetscValidPointer(section, 2); 4399 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4400 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4401 PetscFunctionReturn(0); 4402 } 4403 4404 #undef __FUNCT__ 4405 #define __FUNCT__ "DMSetCoordinateSection" 4406 /*@ 4407 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4408 4409 Not Collective 4410 4411 Input Parameters: 4412 + dm - The DM object 4413 . dim - The embedding dimension, or PETSC_DETERMINE 4414 - section - The PetscSection object 4415 4416 Level: intermediate 4417 4418 .keywords: mesh, coordinates 4419 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4420 @*/ 4421 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4422 { 4423 DM cdm; 4424 PetscErrorCode ierr; 4425 4426 PetscFunctionBegin; 4427 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4428 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4429 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4430 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4431 if (dim == PETSC_DETERMINE) { 4432 PetscInt d = dim; 4433 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4434 4435 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4436 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4437 pStart = PetscMax(vStart, pStart); 4438 pEnd = PetscMin(vEnd, pEnd); 4439 for (v = pStart; v < pEnd; ++v) { 4440 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4441 if (dd) {d = dd; break;} 4442 } 4443 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4444 } 4445 PetscFunctionReturn(0); 4446 } 4447 4448 #undef __FUNCT__ 4449 #define __FUNCT__ "DMGetPeriodicity" 4450 /*@C 4451 DMSetPeriodicity - Set the description of mesh periodicity 4452 4453 Input Parameters: 4454 + dm - The DM object 4455 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4456 . L - If we assume the mesh is a torus, this is the length of each coordinate 4457 - bd - This describes the type of periodicity in each topological dimension 4458 4459 Level: developer 4460 4461 .seealso: DMGetPeriodicity() 4462 @*/ 4463 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4464 { 4465 PetscFunctionBegin; 4466 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4467 if (L) *L = dm->L; 4468 if (maxCell) *maxCell = dm->maxCell; 4469 if (bd) *bd = dm->bdtype; 4470 PetscFunctionReturn(0); 4471 } 4472 4473 #undef __FUNCT__ 4474 #define __FUNCT__ "DMSetPeriodicity" 4475 /*@C 4476 DMSetPeriodicity - Set the description of mesh periodicity 4477 4478 Input Parameters: 4479 + dm - The DM object 4480 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4481 . L - If we assume the mesh is a torus, this is the length of each coordinate 4482 - bd - This describes the type of periodicity in each topological dimension 4483 4484 Level: developer 4485 4486 .seealso: DMGetPeriodicity() 4487 @*/ 4488 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4489 { 4490 PetscInt dim, d; 4491 PetscErrorCode ierr; 4492 4493 PetscFunctionBegin; 4494 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4495 PetscValidPointer(L,3);PetscValidPointer(maxCell,2);PetscValidPointer(bd,4); 4496 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4497 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4498 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4499 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4500 PetscFunctionReturn(0); 4501 } 4502 4503 #undef __FUNCT__ 4504 #define __FUNCT__ "DMLocalizeCoordinate" 4505 /*@ 4506 DMLocalizeCoordinate - If a mesh is periodic (a torus with lengths L_i, some of which can be infinite), project the coordinate onto [0, L_i) in each dimension. 4507 4508 Input Parameters: 4509 + dm - The DM 4510 - in - The input coordinate point (dim numbers) 4511 4512 Output Parameter: 4513 . out - The localized coordinate point 4514 4515 Level: developer 4516 4517 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4518 @*/ 4519 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscScalar out[]) 4520 { 4521 PetscInt dim, d; 4522 PetscErrorCode ierr; 4523 4524 PetscFunctionBegin; 4525 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 4526 if (!dm->maxCell) { 4527 for (d = 0; d < dim; ++d) out[d] = in[d]; 4528 } else { 4529 for (d = 0; d < dim; ++d) { 4530 out[d] = in[d] - dm->L[d]*floor(PetscRealPart(in[d])/dm->L[d]); 4531 } 4532 } 4533 PetscFunctionReturn(0); 4534 } 4535 4536 #undef __FUNCT__ 4537 #define __FUNCT__ "DMLocalizeCoordinate_Internal" 4538 /* 4539 DMLocalizeCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer. 4540 4541 Input Parameters: 4542 + dm - The DM 4543 . dim - The spatial dimension 4544 . anchor - The anchor point, the input point can be no more than maxCell away from it 4545 - in - The input coordinate point (dim numbers) 4546 4547 Output Parameter: 4548 . out - The localized coordinate point 4549 4550 Level: developer 4551 4552 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell 4553 4554 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4555 */ 4556 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4557 { 4558 PetscInt d; 4559 4560 PetscFunctionBegin; 4561 if (!dm->maxCell) { 4562 for (d = 0; d < dim; ++d) out[d] = in[d]; 4563 } else { 4564 for (d = 0; d < dim; ++d) { 4565 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 4566 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4567 } else { 4568 out[d] = in[d]; 4569 } 4570 } 4571 } 4572 PetscFunctionReturn(0); 4573 } 4574 #undef __FUNCT__ 4575 #define __FUNCT__ "DMLocalizeCoordinateReal_Internal" 4576 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 4577 { 4578 PetscInt d; 4579 4580 PetscFunctionBegin; 4581 if (!dm->maxCell) { 4582 for (d = 0; d < dim; ++d) out[d] = in[d]; 4583 } else { 4584 for (d = 0; d < dim; ++d) { 4585 if (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d]) { 4586 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4587 } else { 4588 out[d] = in[d]; 4589 } 4590 } 4591 } 4592 PetscFunctionReturn(0); 4593 } 4594 4595 #undef __FUNCT__ 4596 #define __FUNCT__ "DMLocalizeAddCoordinate_Internal" 4597 /* 4598 DMLocalizeAddCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer. 4599 4600 Input Parameters: 4601 + dm - The DM 4602 . dim - The spatial dimension 4603 . anchor - The anchor point, the input point can be no more than maxCell away from it 4604 . in - The input coordinate delta (dim numbers) 4605 - out - The input coordinate point (dim numbers) 4606 4607 Output Parameter: 4608 . out - The localized coordinate in + out 4609 4610 Level: developer 4611 4612 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell 4613 4614 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 4615 */ 4616 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4617 { 4618 PetscInt d; 4619 4620 PetscFunctionBegin; 4621 if (!dm->maxCell) { 4622 for (d = 0; d < dim; ++d) out[d] += in[d]; 4623 } else { 4624 for (d = 0; d < dim; ++d) { 4625 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 4626 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4627 } else { 4628 out[d] += in[d]; 4629 } 4630 } 4631 } 4632 PetscFunctionReturn(0); 4633 } 4634 4635 PETSC_EXTERN PetscErrorCode DMPlexGetDepthStratum(DM, PetscInt, PetscInt *, PetscInt *); 4636 PETSC_EXTERN PetscErrorCode DMPlexGetHeightStratum(DM, PetscInt, PetscInt *, PetscInt *); 4637 PETSC_EXTERN PetscErrorCode DMPlexVecGetClosure(DM, PetscSection, Vec, PetscInt, PetscInt *, PetscScalar *[]); 4638 PETSC_EXTERN PetscErrorCode DMPlexVecRestoreClosure(DM, PetscSection, Vec, PetscInt, PetscInt *, PetscScalar *[]); 4639 4640 #undef __FUNCT__ 4641 #define __FUNCT__ "DMGetCoordinatesLocalized" 4642 /*@ 4643 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 4644 4645 Input Parameter: 4646 . dm - The DM 4647 4648 Output Parameter: 4649 areLocalized - True if localized 4650 4651 Level: developer 4652 4653 .seealso: DMLocalizeCoordinates() 4654 @*/ 4655 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 4656 { 4657 DM cdm; 4658 PetscSection coordSection; 4659 PetscInt cStart, cEnd, c, sStart, sEnd, dof; 4660 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4661 PetscErrorCode ierr; 4662 4663 PetscFunctionBegin; 4664 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4665 if (!dm->maxCell) { 4666 *areLocalized = PETSC_FALSE; 4667 PetscFunctionReturn(0); 4668 } 4669 /* We need some generic way of refering to cells/vertices */ 4670 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4671 { 4672 PetscBool isplex; 4673 4674 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4675 if (isplex) { 4676 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4677 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4678 } 4679 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4680 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4681 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 4682 for (c = cStart; c < cEnd; ++c) { 4683 if (c < sStart || c >= sEnd) { 4684 alreadyLocalized = PETSC_FALSE; 4685 break; 4686 } 4687 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 4688 if (!dof) { 4689 alreadyLocalized = PETSC_FALSE; 4690 break; 4691 } 4692 } 4693 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4694 *areLocalized = alreadyLocalizedGlobal; 4695 PetscFunctionReturn(0); 4696 } 4697 4698 4699 #undef __FUNCT__ 4700 #define __FUNCT__ "DMLocalizeCoordinates" 4701 /*@ 4702 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for each cell 4703 4704 Input Parameter: 4705 . dm - The DM 4706 4707 Level: developer 4708 4709 .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 4710 @*/ 4711 PetscErrorCode DMLocalizeCoordinates(DM dm) 4712 { 4713 DM cdm; 4714 PetscSection coordSection, cSection; 4715 Vec coordinates, cVec; 4716 PetscScalar *coords, *coords2, *anchor; 4717 PetscInt Nc, cStart, cEnd, c, vStart, vEnd, v, sStart, sEnd, dof, d, off, off2, bs, coordSize; 4718 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4719 PetscErrorCode ierr; 4720 4721 PetscFunctionBegin; 4722 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4723 if (!dm->maxCell) PetscFunctionReturn(0); 4724 /* We need some generic way of refering to cells/vertices */ 4725 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4726 { 4727 PetscBool isplex; 4728 4729 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4730 if (isplex) { 4731 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4732 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4733 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4734 } 4735 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4736 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4737 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4738 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 4739 for (c = cStart; c < cEnd; ++c) { 4740 if (c < sStart || c >= sEnd) { 4741 alreadyLocalized = PETSC_FALSE; 4742 break; 4743 } 4744 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 4745 if (!dof) { 4746 alreadyLocalized = PETSC_FALSE; 4747 break; 4748 } 4749 } 4750 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4751 if (alreadyLocalizedGlobal) PetscFunctionReturn(0); 4752 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 4753 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 4754 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 4755 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 4756 ierr = PetscSectionSetChart(cSection, cStart, vEnd);CHKERRQ(ierr); 4757 for (v = vStart; v < vEnd; ++v) { 4758 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4759 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 4760 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 4761 } 4762 for (c = cStart; c < cEnd; ++c) { 4763 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, NULL);CHKERRQ(ierr); 4764 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 4765 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 4766 } 4767 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 4768 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 4769 ierr = VecCreate(PetscObjectComm((PetscObject) dm), &cVec);CHKERRQ(ierr); 4770 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 4771 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 4772 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 4773 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4774 ierr = VecSetType(cVec,VECSTANDARD);CHKERRQ(ierr); 4775 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4776 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 4777 for (v = vStart; v < vEnd; ++v) { 4778 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4779 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4780 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 4781 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 4782 } 4783 ierr = DMGetWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 4784 for (c = cStart; c < cEnd; ++c) { 4785 PetscScalar *cellCoords = NULL; 4786 PetscInt b; 4787 4788 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4789 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 4790 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4791 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 4792 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4793 } 4794 ierr = DMRestoreWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 4795 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4796 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 4797 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 4798 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 4799 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 4800 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4801 PetscFunctionReturn(0); 4802 } 4803 4804 #undef __FUNCT__ 4805 #define __FUNCT__ "DMLocatePoints" 4806 /*@ 4807 DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells 4808 4809 Not collective 4810 4811 Input Parameters: 4812 + dm - The DM 4813 - v - The Vec of points 4814 4815 Output Parameter: 4816 . cells - The local cell numbers for cells which contain the points 4817 4818 Level: developer 4819 4820 .keywords: point location, mesh 4821 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4822 @*/ 4823 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells) 4824 { 4825 PetscErrorCode ierr; 4826 4827 PetscFunctionBegin; 4828 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4829 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4830 PetscValidPointer(cells,3); 4831 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4832 if (dm->ops->locatepoints) { 4833 ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr); 4834 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4835 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4836 PetscFunctionReturn(0); 4837 } 4838 4839 #undef __FUNCT__ 4840 #define __FUNCT__ "DMGetOutputDM" 4841 /*@ 4842 DMGetOutputDM - Retrieve the DM associated with the layout for output 4843 4844 Input Parameter: 4845 . dm - The original DM 4846 4847 Output Parameter: 4848 . odm - The DM which provides the layout for output 4849 4850 Level: intermediate 4851 4852 .seealso: VecView(), DMGetDefaultGlobalSection() 4853 @*/ 4854 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4855 { 4856 PetscSection section; 4857 PetscBool hasConstraints; 4858 PetscErrorCode ierr; 4859 4860 PetscFunctionBegin; 4861 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4862 PetscValidPointer(odm,2); 4863 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4864 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4865 if (!hasConstraints) { 4866 *odm = dm; 4867 PetscFunctionReturn(0); 4868 } 4869 if (!dm->dmBC) { 4870 PetscDS ds; 4871 PetscSection newSection, gsection; 4872 PetscSF sf; 4873 4874 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4875 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 4876 ierr = DMSetDS(dm->dmBC, ds);CHKERRQ(ierr); 4877 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4878 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4879 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4880 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4881 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 4882 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4883 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4884 } 4885 *odm = dm->dmBC; 4886 PetscFunctionReturn(0); 4887 } 4888 4889 #undef __FUNCT__ 4890 #define __FUNCT__ "DMGetOutputSequenceNumber" 4891 /*@ 4892 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 4893 4894 Input Parameter: 4895 . dm - The original DM 4896 4897 Output Parameters: 4898 + num - The output sequence number 4899 - val - The output sequence value 4900 4901 Level: intermediate 4902 4903 Note: This is intended for output that should appear in sequence, for instance 4904 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4905 4906 .seealso: VecView() 4907 @*/ 4908 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 4909 { 4910 PetscFunctionBegin; 4911 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4912 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 4913 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 4914 PetscFunctionReturn(0); 4915 } 4916 4917 #undef __FUNCT__ 4918 #define __FUNCT__ "DMSetOutputSequenceNumber" 4919 /*@ 4920 DMSetOutputSequenceNumber - Set the sequence number/value for output 4921 4922 Input Parameters: 4923 + dm - The original DM 4924 . num - The output sequence number 4925 - val - The output sequence value 4926 4927 Level: intermediate 4928 4929 Note: This is intended for output that should appear in sequence, for instance 4930 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4931 4932 .seealso: VecView() 4933 @*/ 4934 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 4935 { 4936 PetscFunctionBegin; 4937 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4938 dm->outputSequenceNum = num; 4939 dm->outputSequenceVal = val; 4940 PetscFunctionReturn(0); 4941 } 4942 4943 #undef __FUNCT__ 4944 #define __FUNCT__ "DMOutputSequenceLoad" 4945 /*@C 4946 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 4947 4948 Input Parameters: 4949 + dm - The original DM 4950 . name - The sequence name 4951 - num - The output sequence number 4952 4953 Output Parameter: 4954 . val - The output sequence value 4955 4956 Level: intermediate 4957 4958 Note: This is intended for output that should appear in sequence, for instance 4959 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4960 4961 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 4962 @*/ 4963 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 4964 { 4965 PetscBool ishdf5; 4966 PetscErrorCode ierr; 4967 4968 PetscFunctionBegin; 4969 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4970 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4971 PetscValidPointer(val,4); 4972 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4973 if (ishdf5) { 4974 #if defined(PETSC_HAVE_HDF5) 4975 PetscScalar value; 4976 4977 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 4978 *val = PetscRealPart(value); 4979 #endif 4980 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 4981 PetscFunctionReturn(0); 4982 } 4983 4984 #undef __FUNCT__ 4985 #define __FUNCT__ "DMGetUseNatural" 4986 /*@ 4987 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 4988 4989 Not collective 4990 4991 Input Parameter: 4992 . dm - The DM 4993 4994 Output Parameter: 4995 . useNatural - The flag to build the mapping to a natural order during distribution 4996 4997 Level: beginner 4998 4999 .seealso: DMSetUseNatural(), DMCreate() 5000 @*/ 5001 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 5002 { 5003 PetscFunctionBegin; 5004 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5005 PetscValidPointer(useNatural, 2); 5006 *useNatural = dm->useNatural; 5007 PetscFunctionReturn(0); 5008 } 5009 5010 #undef __FUNCT__ 5011 #define __FUNCT__ "DMSetUseNatural" 5012 /*@ 5013 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 5014 5015 Collective on dm 5016 5017 Input Parameters: 5018 + dm - The DM 5019 - useNatural - The flag to build the mapping to a natural order during distribution 5020 5021 Level: beginner 5022 5023 .seealso: DMGetUseNatural(), DMCreate() 5024 @*/ 5025 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 5026 { 5027 PetscFunctionBegin; 5028 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5029 PetscValidLogicalCollectiveInt(dm, useNatural, 2); 5030 dm->useNatural = useNatural; 5031 PetscFunctionReturn(0); 5032 } 5033 5034 #undef __FUNCT__ 5035 #define __FUNCT__ 5036 5037 #undef __FUNCT__ 5038 #define __FUNCT__ "DMCreateLabel" 5039 /*@C 5040 DMCreateLabel - Create a label of the given name if it does not already exist 5041 5042 Not Collective 5043 5044 Input Parameters: 5045 + dm - The DM object 5046 - name - The label name 5047 5048 Level: intermediate 5049 5050 .keywords: mesh 5051 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5052 @*/ 5053 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 5054 { 5055 DMLabelLink next = dm->labels->next; 5056 PetscBool flg = PETSC_FALSE; 5057 PetscErrorCode ierr; 5058 5059 PetscFunctionBegin; 5060 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5061 PetscValidCharPointer(name, 2); 5062 while (next) { 5063 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5064 if (flg) break; 5065 next = next->next; 5066 } 5067 if (!flg) { 5068 DMLabelLink tmpLabel; 5069 5070 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5071 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 5072 tmpLabel->output = PETSC_TRUE; 5073 tmpLabel->next = dm->labels->next; 5074 dm->labels->next = tmpLabel; 5075 } 5076 PetscFunctionReturn(0); 5077 } 5078 5079 #undef __FUNCT__ 5080 #define __FUNCT__ "DMGetLabelValue" 5081 /*@C 5082 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 5083 5084 Not Collective 5085 5086 Input Parameters: 5087 + dm - The DM object 5088 . name - The label name 5089 - point - The mesh point 5090 5091 Output Parameter: 5092 . value - The label value for this point, or -1 if the point is not in the label 5093 5094 Level: beginner 5095 5096 .keywords: mesh 5097 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 5098 @*/ 5099 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 5100 { 5101 DMLabel label; 5102 PetscErrorCode ierr; 5103 5104 PetscFunctionBegin; 5105 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5106 PetscValidCharPointer(name, 2); 5107 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5108 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);CHKERRQ(ierr); 5109 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5110 PetscFunctionReturn(0); 5111 } 5112 5113 #undef __FUNCT__ 5114 #define __FUNCT__ "DMSetLabelValue" 5115 /*@C 5116 DMSetLabelValue - Add a point to a Sieve Label with given value 5117 5118 Not Collective 5119 5120 Input Parameters: 5121 + dm - The DM object 5122 . name - The label name 5123 . point - The mesh point 5124 - value - The label value for this point 5125 5126 Output Parameter: 5127 5128 Level: beginner 5129 5130 .keywords: mesh 5131 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5132 @*/ 5133 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5134 { 5135 DMLabel label; 5136 PetscErrorCode ierr; 5137 5138 PetscFunctionBegin; 5139 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5140 PetscValidCharPointer(name, 2); 5141 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5142 if (!label) { 5143 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5144 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5145 } 5146 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5147 PetscFunctionReturn(0); 5148 } 5149 5150 #undef __FUNCT__ 5151 #define __FUNCT__ "DMClearLabelValue" 5152 /*@C 5153 DMClearLabelValue - Remove a point from a Sieve Label with given value 5154 5155 Not Collective 5156 5157 Input Parameters: 5158 + dm - The DM object 5159 . name - The label name 5160 . point - The mesh point 5161 - value - The label value for this point 5162 5163 Output Parameter: 5164 5165 Level: beginner 5166 5167 .keywords: mesh 5168 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5169 @*/ 5170 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5171 { 5172 DMLabel label; 5173 PetscErrorCode ierr; 5174 5175 PetscFunctionBegin; 5176 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5177 PetscValidCharPointer(name, 2); 5178 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5179 if (!label) PetscFunctionReturn(0); 5180 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5181 PetscFunctionReturn(0); 5182 } 5183 5184 #undef __FUNCT__ 5185 #define __FUNCT__ "DMGetLabelSize" 5186 /*@C 5187 DMGetLabelSize - Get the number of different integer ids in a Label 5188 5189 Not Collective 5190 5191 Input Parameters: 5192 + dm - The DM object 5193 - name - The label name 5194 5195 Output Parameter: 5196 . size - The number of different integer ids, or 0 if the label does not exist 5197 5198 Level: beginner 5199 5200 .keywords: mesh 5201 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 5202 @*/ 5203 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5204 { 5205 DMLabel label; 5206 PetscErrorCode ierr; 5207 5208 PetscFunctionBegin; 5209 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5210 PetscValidCharPointer(name, 2); 5211 PetscValidPointer(size, 3); 5212 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5213 *size = 0; 5214 if (!label) PetscFunctionReturn(0); 5215 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5216 PetscFunctionReturn(0); 5217 } 5218 5219 #undef __FUNCT__ 5220 #define __FUNCT__ "DMGetLabelIdIS" 5221 /*@C 5222 DMGetLabelIdIS - Get the integer ids in a label 5223 5224 Not Collective 5225 5226 Input Parameters: 5227 + mesh - The DM object 5228 - name - The label name 5229 5230 Output Parameter: 5231 . ids - The integer ids, or NULL if the label does not exist 5232 5233 Level: beginner 5234 5235 .keywords: mesh 5236 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5237 @*/ 5238 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5239 { 5240 DMLabel label; 5241 PetscErrorCode ierr; 5242 5243 PetscFunctionBegin; 5244 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5245 PetscValidCharPointer(name, 2); 5246 PetscValidPointer(ids, 3); 5247 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5248 *ids = NULL; 5249 if (!label) PetscFunctionReturn(0); 5250 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5251 PetscFunctionReturn(0); 5252 } 5253 5254 #undef __FUNCT__ 5255 #define __FUNCT__ "DMGetStratumSize" 5256 /*@C 5257 DMGetStratumSize - Get the number of points in a label stratum 5258 5259 Not Collective 5260 5261 Input Parameters: 5262 + dm - The DM object 5263 . name - The label name 5264 - value - The stratum value 5265 5266 Output Parameter: 5267 . size - The stratum size 5268 5269 Level: beginner 5270 5271 .keywords: mesh 5272 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5273 @*/ 5274 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5275 { 5276 DMLabel label; 5277 PetscErrorCode ierr; 5278 5279 PetscFunctionBegin; 5280 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5281 PetscValidCharPointer(name, 2); 5282 PetscValidPointer(size, 4); 5283 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5284 *size = 0; 5285 if (!label) PetscFunctionReturn(0); 5286 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5287 PetscFunctionReturn(0); 5288 } 5289 5290 #undef __FUNCT__ 5291 #define __FUNCT__ "DMGetStratumIS" 5292 /*@C 5293 DMGetStratumIS - Get the points in a label stratum 5294 5295 Not Collective 5296 5297 Input Parameters: 5298 + dm - The DM object 5299 . name - The label name 5300 - value - The stratum value 5301 5302 Output Parameter: 5303 . points - The stratum points, or NULL if the label does not exist or does not have that value 5304 5305 Level: beginner 5306 5307 .keywords: mesh 5308 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5309 @*/ 5310 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5311 { 5312 DMLabel label; 5313 PetscErrorCode ierr; 5314 5315 PetscFunctionBegin; 5316 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5317 PetscValidCharPointer(name, 2); 5318 PetscValidPointer(points, 4); 5319 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5320 *points = NULL; 5321 if (!label) PetscFunctionReturn(0); 5322 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5323 PetscFunctionReturn(0); 5324 } 5325 5326 #undef __FUNCT__ 5327 #define __FUNCT__ "DMClearLabelStratum" 5328 /*@C 5329 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 5330 5331 Not Collective 5332 5333 Input Parameters: 5334 + dm - The DM object 5335 . name - The label name 5336 - value - The label value for this point 5337 5338 Output Parameter: 5339 5340 Level: beginner 5341 5342 .keywords: mesh 5343 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 5344 @*/ 5345 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 5346 { 5347 DMLabel label; 5348 PetscErrorCode ierr; 5349 5350 PetscFunctionBegin; 5351 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5352 PetscValidCharPointer(name, 2); 5353 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5354 if (!label) PetscFunctionReturn(0); 5355 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 5356 PetscFunctionReturn(0); 5357 } 5358 5359 #undef __FUNCT__ 5360 #define __FUNCT__ "DMGetNumLabels" 5361 /*@ 5362 DMGetNumLabels - Return the number of labels defined by the mesh 5363 5364 Not Collective 5365 5366 Input Parameter: 5367 . dm - The DM object 5368 5369 Output Parameter: 5370 . numLabels - the number of Labels 5371 5372 Level: intermediate 5373 5374 .keywords: mesh 5375 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5376 @*/ 5377 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 5378 { 5379 DMLabelLink next = dm->labels->next; 5380 PetscInt n = 0; 5381 5382 PetscFunctionBegin; 5383 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5384 PetscValidPointer(numLabels, 2); 5385 while (next) {++n; next = next->next;} 5386 *numLabels = n; 5387 PetscFunctionReturn(0); 5388 } 5389 5390 #undef __FUNCT__ 5391 #define __FUNCT__ "DMGetLabelName" 5392 /*@C 5393 DMGetLabelName - Return the name of nth label 5394 5395 Not Collective 5396 5397 Input Parameters: 5398 + dm - The DM object 5399 - n - the label number 5400 5401 Output Parameter: 5402 . name - the label name 5403 5404 Level: intermediate 5405 5406 .keywords: mesh 5407 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5408 @*/ 5409 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 5410 { 5411 DMLabelLink next = dm->labels->next; 5412 PetscInt l = 0; 5413 5414 PetscFunctionBegin; 5415 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5416 PetscValidPointer(name, 3); 5417 while (next) { 5418 if (l == n) { 5419 *name = next->label->name; 5420 PetscFunctionReturn(0); 5421 } 5422 ++l; 5423 next = next->next; 5424 } 5425 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5426 } 5427 5428 #undef __FUNCT__ 5429 #define __FUNCT__ "DMHasLabel" 5430 /*@C 5431 DMHasLabel - Determine whether the mesh has a label of a given name 5432 5433 Not Collective 5434 5435 Input Parameters: 5436 + dm - The DM object 5437 - name - The label name 5438 5439 Output Parameter: 5440 . hasLabel - PETSC_TRUE if the label is present 5441 5442 Level: intermediate 5443 5444 .keywords: mesh 5445 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5446 @*/ 5447 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 5448 { 5449 DMLabelLink next = dm->labels->next; 5450 PetscErrorCode ierr; 5451 5452 PetscFunctionBegin; 5453 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5454 PetscValidCharPointer(name, 2); 5455 PetscValidPointer(hasLabel, 3); 5456 *hasLabel = PETSC_FALSE; 5457 while (next) { 5458 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 5459 if (*hasLabel) break; 5460 next = next->next; 5461 } 5462 PetscFunctionReturn(0); 5463 } 5464 5465 #undef __FUNCT__ 5466 #define __FUNCT__ "DMGetLabel" 5467 /*@C 5468 DMGetLabel - Return the label of a given name, or NULL 5469 5470 Not Collective 5471 5472 Input Parameters: 5473 + dm - The DM object 5474 - name - The label name 5475 5476 Output Parameter: 5477 . label - The DMLabel, or NULL if the label is absent 5478 5479 Level: intermediate 5480 5481 .keywords: mesh 5482 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5483 @*/ 5484 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 5485 { 5486 DMLabelLink next = dm->labels->next; 5487 PetscBool hasLabel; 5488 PetscErrorCode ierr; 5489 5490 PetscFunctionBegin; 5491 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5492 PetscValidCharPointer(name, 2); 5493 PetscValidPointer(label, 3); 5494 *label = NULL; 5495 while (next) { 5496 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5497 if (hasLabel) { 5498 *label = next->label; 5499 break; 5500 } 5501 next = next->next; 5502 } 5503 PetscFunctionReturn(0); 5504 } 5505 5506 #undef __FUNCT__ 5507 #define __FUNCT__ "DMGetLabelByNum" 5508 /*@C 5509 DMGetLabelByNum - Return the nth label 5510 5511 Not Collective 5512 5513 Input Parameters: 5514 + dm - The DM object 5515 - n - the label number 5516 5517 Output Parameter: 5518 . label - the label 5519 5520 Level: intermediate 5521 5522 .keywords: mesh 5523 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5524 @*/ 5525 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5526 { 5527 DMLabelLink next = dm->labels->next; 5528 PetscInt l = 0; 5529 5530 PetscFunctionBegin; 5531 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5532 PetscValidPointer(label, 3); 5533 while (next) { 5534 if (l == n) { 5535 *label = next->label; 5536 PetscFunctionReturn(0); 5537 } 5538 ++l; 5539 next = next->next; 5540 } 5541 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5542 } 5543 5544 #undef __FUNCT__ 5545 #define __FUNCT__ "DMAddLabel" 5546 /*@C 5547 DMAddLabel - Add the label to this mesh 5548 5549 Not Collective 5550 5551 Input Parameters: 5552 + dm - The DM object 5553 - label - The DMLabel 5554 5555 Level: developer 5556 5557 .keywords: mesh 5558 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5559 @*/ 5560 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5561 { 5562 DMLabelLink tmpLabel; 5563 PetscBool hasLabel; 5564 PetscErrorCode ierr; 5565 5566 PetscFunctionBegin; 5567 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5568 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5569 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5570 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5571 tmpLabel->label = label; 5572 tmpLabel->output = PETSC_TRUE; 5573 tmpLabel->next = dm->labels->next; 5574 dm->labels->next = tmpLabel; 5575 PetscFunctionReturn(0); 5576 } 5577 5578 #undef __FUNCT__ 5579 #define __FUNCT__ "DMRemoveLabel" 5580 /*@C 5581 DMRemoveLabel - Remove the label from this mesh 5582 5583 Not Collective 5584 5585 Input Parameters: 5586 + dm - The DM object 5587 - name - The label name 5588 5589 Output Parameter: 5590 . label - The DMLabel, or NULL if the label is absent 5591 5592 Level: developer 5593 5594 .keywords: mesh 5595 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5596 @*/ 5597 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5598 { 5599 DMLabelLink next = dm->labels->next; 5600 DMLabelLink last = NULL; 5601 PetscBool hasLabel; 5602 PetscErrorCode ierr; 5603 5604 PetscFunctionBegin; 5605 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5606 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5607 *label = NULL; 5608 if (!hasLabel) PetscFunctionReturn(0); 5609 while (next) { 5610 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5611 if (hasLabel) { 5612 if (last) last->next = next->next; 5613 else dm->labels->next = next->next; 5614 next->next = NULL; 5615 *label = next->label; 5616 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5617 if (hasLabel) { 5618 dm->depthLabel = NULL; 5619 } 5620 ierr = PetscFree(next);CHKERRQ(ierr); 5621 break; 5622 } 5623 last = next; 5624 next = next->next; 5625 } 5626 PetscFunctionReturn(0); 5627 } 5628 5629 #undef __FUNCT__ 5630 #define __FUNCT__ "DMGetLabelOutput" 5631 /*@C 5632 DMGetLabelOutput - Get the output flag for a given label 5633 5634 Not Collective 5635 5636 Input Parameters: 5637 + dm - The DM object 5638 - name - The label name 5639 5640 Output Parameter: 5641 . output - The flag for output 5642 5643 Level: developer 5644 5645 .keywords: mesh 5646 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5647 @*/ 5648 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5649 { 5650 DMLabelLink next = dm->labels->next; 5651 PetscErrorCode ierr; 5652 5653 PetscFunctionBegin; 5654 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5655 PetscValidPointer(name, 2); 5656 PetscValidPointer(output, 3); 5657 while (next) { 5658 PetscBool flg; 5659 5660 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5661 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5662 next = next->next; 5663 } 5664 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5665 } 5666 5667 #undef __FUNCT__ 5668 #define __FUNCT__ "DMSetLabelOutput" 5669 /*@C 5670 DMSetLabelOutput - Set the output flag for a given label 5671 5672 Not Collective 5673 5674 Input Parameters: 5675 + dm - The DM object 5676 . name - The label name 5677 - output - The flag for output 5678 5679 Level: developer 5680 5681 .keywords: mesh 5682 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5683 @*/ 5684 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 5685 { 5686 DMLabelLink next = dm->labels->next; 5687 PetscErrorCode ierr; 5688 5689 PetscFunctionBegin; 5690 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5691 PetscValidPointer(name, 2); 5692 while (next) { 5693 PetscBool flg; 5694 5695 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5696 if (flg) {next->output = output; PetscFunctionReturn(0);} 5697 next = next->next; 5698 } 5699 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5700 } 5701 5702 5703 #undef __FUNCT__ 5704 #define __FUNCT__ "DMCopyLabels" 5705 /*@ 5706 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 5707 5708 Collective on DM 5709 5710 Input Parameter: 5711 . dmA - The DM object with initial labels 5712 5713 Output Parameter: 5714 . dmB - The DM object with copied labels 5715 5716 Level: intermediate 5717 5718 Note: This is typically used when interpolating or otherwise adding to a mesh 5719 5720 .keywords: mesh 5721 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 5722 @*/ 5723 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 5724 { 5725 PetscInt numLabels, l; 5726 PetscErrorCode ierr; 5727 5728 PetscFunctionBegin; 5729 if (dmA == dmB) PetscFunctionReturn(0); 5730 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 5731 for (l = 0; l < numLabels; ++l) { 5732 DMLabel label, labelNew; 5733 const char *name; 5734 PetscBool flg; 5735 5736 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 5737 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 5738 if (flg) continue; 5739 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 5740 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 5741 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 5742 } 5743 PetscFunctionReturn(0); 5744 } 5745 5746 #undef __FUNCT__ 5747 #define __FUNCT__ "DMGetCoarseDM" 5748 /*@ 5749 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5750 5751 Input Parameter: 5752 . dm - The DM object 5753 5754 Output Parameter: 5755 . cdm - The coarse DM 5756 5757 Level: intermediate 5758 5759 .seealso: DMSetCoarseDM() 5760 @*/ 5761 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 5762 { 5763 PetscFunctionBegin; 5764 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5765 PetscValidPointer(cdm, 2); 5766 *cdm = dm->coarseMesh; 5767 PetscFunctionReturn(0); 5768 } 5769 5770 #undef __FUNCT__ 5771 #define __FUNCT__ "DMSetCoarseDM" 5772 /*@ 5773 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5774 5775 Input Parameters: 5776 + dm - The DM object 5777 - cdm - The coarse DM 5778 5779 Level: intermediate 5780 5781 .seealso: DMGetCoarseDM() 5782 @*/ 5783 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 5784 { 5785 PetscErrorCode ierr; 5786 5787 PetscFunctionBegin; 5788 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5789 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5790 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5791 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 5792 dm->coarseMesh = cdm; 5793 PetscFunctionReturn(0); 5794 } 5795 5796 #undef __FUNCT__ 5797 #define __FUNCT__ "DMGetFineDM" 5798 /*@ 5799 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 5800 5801 Input Parameter: 5802 . dm - The DM object 5803 5804 Output Parameter: 5805 . fdm - The fine DM 5806 5807 Level: intermediate 5808 5809 .seealso: DMSetFineDM() 5810 @*/ 5811 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 5812 { 5813 PetscFunctionBegin; 5814 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5815 PetscValidPointer(fdm, 2); 5816 *fdm = dm->fineMesh; 5817 PetscFunctionReturn(0); 5818 } 5819 5820 #undef __FUNCT__ 5821 #define __FUNCT__ "DMSetFineDM" 5822 /*@ 5823 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 5824 5825 Input Parameters: 5826 + dm - The DM object 5827 - fdm - The fine DM 5828 5829 Level: intermediate 5830 5831 .seealso: DMGetFineDM() 5832 @*/ 5833 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 5834 { 5835 PetscErrorCode ierr; 5836 5837 PetscFunctionBegin; 5838 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5839 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 5840 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 5841 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 5842 dm->fineMesh = fdm; 5843 PetscFunctionReturn(0); 5844 } 5845 5846 /*=== DMBoundary code ===*/ 5847 5848 #undef __FUNCT__ 5849 #define __FUNCT__ "DMBoundaryDuplicate" 5850 PetscErrorCode DMBoundaryDuplicate(DMBoundaryLinkList bd, DMBoundaryLinkList *boundary) 5851 { 5852 DMBoundary b = bd->next, b2, bold = NULL; 5853 PetscErrorCode ierr; 5854 5855 PetscFunctionBegin; 5856 ierr = PetscNew(boundary);CHKERRQ(ierr); 5857 (*boundary)->refct = 1; 5858 (*boundary)->next = NULL; 5859 for (; b; b = b->next, bold = b2) { 5860 ierr = PetscNew(&b2);CHKERRQ(ierr); 5861 ierr = PetscStrallocpy(b->name, (char **) &b2->name);CHKERRQ(ierr); 5862 ierr = PetscStrallocpy(b->labelname, (char **) &b2->labelname);CHKERRQ(ierr); 5863 ierr = PetscMalloc1(b->numids, &b2->ids);CHKERRQ(ierr); 5864 ierr = PetscMemcpy(b2->ids, b->ids, b->numids*sizeof(PetscInt));CHKERRQ(ierr); 5865 ierr = PetscMalloc1(b->numcomps, &b2->comps);CHKERRQ(ierr); 5866 ierr = PetscMemcpy(b2->comps, b->comps, b->numcomps*sizeof(PetscInt));CHKERRQ(ierr); 5867 b2->label = NULL; 5868 b2->essential = b->essential; 5869 b2->field = b->field; 5870 b2->numcomps = b->numcomps; 5871 b2->func = b->func; 5872 b2->numids = b->numids; 5873 b2->ctx = b->ctx; 5874 b2->next = NULL; 5875 if (!(*boundary)->next) (*boundary)->next = b2; 5876 if (bold) bold->next = b2; 5877 } 5878 PetscFunctionReturn(0); 5879 } 5880 5881 #undef __FUNCT__ 5882 #define __FUNCT__ "DMBoundaryDestroy" 5883 PetscErrorCode DMBoundaryDestroy(DMBoundaryLinkList *boundary) 5884 { 5885 DMBoundary b, next; 5886 PetscErrorCode ierr; 5887 5888 PetscFunctionBegin; 5889 if (!boundary) PetscFunctionReturn(0); 5890 if (--((*boundary)->refct)) { 5891 *boundary = NULL; 5892 PetscFunctionReturn(0); 5893 } 5894 b = (*boundary)->next; 5895 for (; b; b = next) { 5896 next = b->next; 5897 ierr = PetscFree(b->comps);CHKERRQ(ierr); 5898 ierr = PetscFree(b->ids);CHKERRQ(ierr); 5899 ierr = PetscFree(b->name);CHKERRQ(ierr); 5900 ierr = PetscFree(b->labelname);CHKERRQ(ierr); 5901 ierr = PetscFree(b);CHKERRQ(ierr); 5902 } 5903 ierr = PetscFree(*boundary);CHKERRQ(ierr); 5904 PetscFunctionReturn(0); 5905 } 5906 5907 #undef __FUNCT__ 5908 #define __FUNCT__ "DMCopyBoundary" 5909 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 5910 { 5911 DMBoundary b; 5912 PetscErrorCode ierr; 5913 5914 PetscFunctionBegin; 5915 ierr = DMBoundaryDestroy(&dmNew->boundary);CHKERRQ(ierr); 5916 ierr = DMBoundaryDuplicate(dm->boundary, &dmNew->boundary);CHKERRQ(ierr); 5917 for (b = dmNew->boundary->next; b; b = b->next) { 5918 if (b->labelname) { 5919 ierr = DMGetLabel(dmNew, b->labelname, &b->label);CHKERRQ(ierr); 5920 if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 5921 } 5922 } 5923 PetscFunctionReturn(0); 5924 } 5925 5926 #undef __FUNCT__ 5927 #define __FUNCT__ "DMAddBoundary" 5928 /*@C 5929 DMAddBoundary - Add a boundary condition to the model 5930 5931 Input Parameters: 5932 + dm - The mesh object 5933 . isEssential - Flag for an essential (Dirichlet) condition, as opposed to a natural (Neumann) condition 5934 . name - The BC name 5935 . labelname - The label defining constrained points 5936 . field - The field to constrain 5937 . numcomps - The number of constrained field components 5938 . comps - An array of constrained component numbers 5939 . bcFunc - A pointwise function giving boundary values 5940 . numids - The number of DMLabel ids for constrained points 5941 . ids - An array of ids for constrained points 5942 - ctx - An optional user context for bcFunc 5943 5944 Options Database Keys: 5945 + -bc_<boundary name> <num> - Overrides the boundary ids 5946 - -bc_<boundary name>_comp <num> - Overrides the boundary components 5947 5948 Level: developer 5949 5950 .seealso: DMGetBoundary() 5951 @*/ 5952 PetscErrorCode DMAddBoundary(DM dm, PetscBool isEssential, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(), PetscInt numids, const PetscInt *ids, void *ctx) 5953 { 5954 DMBoundary b; 5955 PetscErrorCode ierr; 5956 5957 PetscFunctionBegin; 5958 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5959 ierr = PetscNew(&b);CHKERRQ(ierr); 5960 ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); 5961 ierr = PetscStrallocpy(labelname, (char **) &b->labelname);CHKERRQ(ierr); 5962 ierr = PetscMalloc1(numcomps, &b->comps);CHKERRQ(ierr); 5963 if (numcomps) {ierr = PetscMemcpy(b->comps, comps, numcomps*sizeof(PetscInt));CHKERRQ(ierr);} 5964 ierr = PetscMalloc1(numids, &b->ids);CHKERRQ(ierr); 5965 if (numids) {ierr = PetscMemcpy(b->ids, ids, numids*sizeof(PetscInt));CHKERRQ(ierr);} 5966 if (b->labelname) { 5967 ierr = DMGetLabel(dm, b->labelname, &b->label);CHKERRQ(ierr); 5968 if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 5969 } 5970 b->essential = isEssential; 5971 b->field = field; 5972 b->numcomps = numcomps; 5973 b->func = bcFunc; 5974 b->numids = numids; 5975 b->ctx = ctx; 5976 b->next = dm->boundary->next; 5977 dm->boundary->next = b; 5978 PetscFunctionReturn(0); 5979 } 5980 5981 #undef __FUNCT__ 5982 #define __FUNCT__ "DMGetNumBoundary" 5983 /*@ 5984 DMGetNumBoundary - Get the number of registered BC 5985 5986 Input Parameters: 5987 . dm - The mesh object 5988 5989 Output Parameters: 5990 . numBd - The number of BC 5991 5992 Level: intermediate 5993 5994 .seealso: DMAddBoundary(), DMGetBoundary() 5995 @*/ 5996 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 5997 { 5998 DMBoundary b = dm->boundary->next; 5999 6000 PetscFunctionBegin; 6001 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6002 PetscValidPointer(numBd, 2); 6003 *numBd = 0; 6004 while (b) {++(*numBd); b = b->next;} 6005 PetscFunctionReturn(0); 6006 } 6007 6008 #undef __FUNCT__ 6009 #define __FUNCT__ "DMGetBoundary" 6010 /*@C 6011 DMGetBoundary - Add a boundary condition to the model 6012 6013 Input Parameters: 6014 + dm - The mesh object 6015 - bd - The BC number 6016 6017 Output Parameters: 6018 + isEssential - Flag for an essential (Dirichlet) condition, as opposed to a natural (Neumann) condition 6019 . name - The BC name 6020 . labelname - The label defining constrained points 6021 . field - The field to constrain 6022 . numcomps - The number of constrained field components 6023 . comps - An array of constrained component numbers 6024 . bcFunc - A pointwise function giving boundary values 6025 . numids - The number of DMLabel ids for constrained points 6026 . ids - An array of ids for constrained points 6027 - ctx - An optional user context for bcFunc 6028 6029 Options Database Keys: 6030 + -bc_<boundary name> <num> - Overrides the boundary ids 6031 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6032 6033 Level: developer 6034 6035 .seealso: DMAddBoundary() 6036 @*/ 6037 PetscErrorCode DMGetBoundary(DM dm, PetscInt bd, PetscBool *isEssential, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(), PetscInt *numids, const PetscInt **ids, void **ctx) 6038 { 6039 DMBoundary b = dm->boundary->next; 6040 PetscInt n = 0; 6041 6042 PetscFunctionBegin; 6043 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6044 while (b) { 6045 if (n == bd) break; 6046 b = b->next; 6047 ++n; 6048 } 6049 if (n != bd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n); 6050 if (isEssential) { 6051 PetscValidPointer(isEssential, 3); 6052 *isEssential = b->essential; 6053 } 6054 if (name) { 6055 PetscValidPointer(name, 4); 6056 *name = b->name; 6057 } 6058 if (labelname) { 6059 PetscValidPointer(labelname, 5); 6060 *labelname = b->labelname; 6061 } 6062 if (field) { 6063 PetscValidPointer(field, 6); 6064 *field = b->field; 6065 } 6066 if (numcomps) { 6067 PetscValidPointer(numcomps, 7); 6068 *numcomps = b->numcomps; 6069 } 6070 if (comps) { 6071 PetscValidPointer(comps, 8); 6072 *comps = b->comps; 6073 } 6074 if (func) { 6075 PetscValidPointer(func, 9); 6076 *func = b->func; 6077 } 6078 if (numids) { 6079 PetscValidPointer(numids, 10); 6080 *numids = b->numids; 6081 } 6082 if (ids) { 6083 PetscValidPointer(ids, 11); 6084 *ids = b->ids; 6085 } 6086 if (ctx) { 6087 PetscValidPointer(ctx, 12); 6088 *ctx = b->ctx; 6089 } 6090 PetscFunctionReturn(0); 6091 } 6092 6093 #undef __FUNCT__ 6094 #define __FUNCT__ "DMIsBoundaryPoint" 6095 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 6096 { 6097 DMBoundary b = dm->boundary->next; 6098 PetscErrorCode ierr; 6099 6100 PetscFunctionBegin; 6101 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6102 PetscValidPointer(isBd, 3); 6103 *isBd = PETSC_FALSE; 6104 while (b && !(*isBd)) { 6105 if (b->label) { 6106 PetscInt i; 6107 6108 for (i = 0; i < b->numids && !(*isBd); ++i) { 6109 ierr = DMLabelStratumHasPoint(b->label, b->ids[i], point, isBd);CHKERRQ(ierr); 6110 } 6111 } 6112 b = b->next; 6113 } 6114 PetscFunctionReturn(0); 6115 } 6116 6117 #undef __FUNCT__ 6118 #define __FUNCT__ "DMProjectFunction" 6119 /*@C 6120 DMProjectFunction - This projects the given function into the function space provided. 6121 6122 Input Parameters: 6123 + dm - The DM 6124 . time - The time 6125 . funcs - The coordinate functions to evaluate, one per field 6126 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6127 - mode - The insertion mode for values 6128 6129 Output Parameter: 6130 . X - vector 6131 6132 Calling sequence of func: 6133 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6134 6135 + dim - The spatial dimension 6136 . x - The coordinates 6137 . Nf - The number of fields 6138 . u - The output field values 6139 - ctx - optional user-defined function context 6140 6141 Level: developer 6142 6143 .seealso: DMComputeL2Diff() 6144 @*/ 6145 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6146 { 6147 Vec localX; 6148 PetscErrorCode ierr; 6149 6150 PetscFunctionBegin; 6151 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6152 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6153 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6154 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6155 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6156 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6157 PetscFunctionReturn(0); 6158 } 6159 6160 #undef __FUNCT__ 6161 #define __FUNCT__ "DMProjectFunctionLocal" 6162 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6163 { 6164 PetscErrorCode ierr; 6165 6166 PetscFunctionBegin; 6167 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6168 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6169 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6170 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6171 PetscFunctionReturn(0); 6172 } 6173 6174 #undef __FUNCT__ 6175 #define __FUNCT__ "DMProjectFieldLocal" 6176 PetscErrorCode DMProjectFieldLocal(DM dm, Vec localU, 6177 void (**funcs)(PetscInt, PetscInt, PetscInt, 6178 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6179 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6180 PetscReal, const PetscReal[], PetscScalar[]), 6181 InsertMode mode, Vec localX) 6182 { 6183 PetscErrorCode ierr; 6184 6185 PetscFunctionBegin; 6186 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6187 PetscValidHeaderSpecific(localU,VEC_CLASSID,2); 6188 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6189 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFieldLocal",((PetscObject)dm)->type_name); 6190 ierr = (dm->ops->projectfieldlocal) (dm, localU, funcs, mode, localX);CHKERRQ(ierr); 6191 PetscFunctionReturn(0); 6192 } 6193 6194 #undef __FUNCT__ 6195 #define __FUNCT__ "DMProjectFunctionLabelLocal" 6196 PetscErrorCode DMProjectFunctionLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6197 { 6198 PetscErrorCode ierr; 6199 6200 PetscFunctionBegin; 6201 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6202 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6203 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6204 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6205 PetscFunctionReturn(0); 6206 } 6207 6208 #undef __FUNCT__ 6209 #define __FUNCT__ "DMComputeL2Diff" 6210 /*@C 6211 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6212 6213 Input Parameters: 6214 + dm - The DM 6215 . time - The time 6216 . funcs - The functions to evaluate for each field component 6217 . ctxs - Optional array of contexts to pass to each function, or NULL. 6218 - X - The coefficient vector u_h 6219 6220 Output Parameter: 6221 . diff - The diff ||u - u_h||_2 6222 6223 Level: developer 6224 6225 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6226 @*/ 6227 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6228 { 6229 PetscErrorCode ierr; 6230 6231 PetscFunctionBegin; 6232 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6233 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6234 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2Diff",((PetscObject)dm)->type_name); 6235 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6236 PetscFunctionReturn(0); 6237 } 6238 6239 #undef __FUNCT__ 6240 #define __FUNCT__ "DMComputeL2GradientDiff" 6241 /*@C 6242 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6243 6244 Input Parameters: 6245 + dm - The DM 6246 , time - The time 6247 . funcs - The gradient functions to evaluate for each field component 6248 . ctxs - Optional array of contexts to pass to each function, or NULL. 6249 . X - The coefficient vector u_h 6250 - n - The vector to project along 6251 6252 Output Parameter: 6253 . diff - The diff ||(grad u - grad u_h) . n||_2 6254 6255 Level: developer 6256 6257 .seealso: DMProjectFunction(), DMComputeL2Diff() 6258 @*/ 6259 PetscErrorCode DMComputeL2GradientDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], const PetscReal[], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff) 6260 { 6261 PetscErrorCode ierr; 6262 6263 PetscFunctionBegin; 6264 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6265 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6266 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6267 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6268 PetscFunctionReturn(0); 6269 } 6270 6271 #undef __FUNCT__ 6272 #define __FUNCT__ "DMComputeL2FieldDiff" 6273 /*@C 6274 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 6275 6276 Input Parameters: 6277 + dm - The DM 6278 . time - The time 6279 . funcs - The functions to evaluate for each field component 6280 . ctxs - Optional array of contexts to pass to each function, or NULL. 6281 - X - The coefficient vector u_h 6282 6283 Output Parameter: 6284 . diff - The array of differences, ||u^f - u^f_h||_2 6285 6286 Level: developer 6287 6288 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6289 @*/ 6290 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 6291 { 6292 PetscErrorCode ierr; 6293 6294 PetscFunctionBegin; 6295 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6296 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6297 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6298 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6299 PetscFunctionReturn(0); 6300 } 6301 6302