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