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