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