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