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