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