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