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