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 - the number of fields in this subproblem 1522 - fields - the fields in the subproblem 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, const 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 . interp - 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 if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 2324 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2325 PetscFunctionReturn(0); 2326 } 2327 2328 /*@ 2329 DMLocalToLocalEnd - Maps from a local vector (including ghost points 2330 that contain irrelevant values) to another local vector where the ghost 2331 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 2332 2333 Neighbor-wise Collective on DM and Vec 2334 2335 Input Parameters: 2336 + da - the DM object 2337 . g - the original local vector 2338 - mode - one of INSERT_VALUES or ADD_VALUES 2339 2340 Output Parameter: 2341 . l - the local vector with correct ghost values 2342 2343 Level: intermediate 2344 2345 Notes: 2346 The local vectors used here need not be the same as those 2347 obtained from DMCreateLocalVector(), BUT they 2348 must have the same parallel data layout; they could, for example, be 2349 obtained with VecDuplicate() from the DM originating vectors. 2350 2351 .keywords: DM, local-to-local, end 2352 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2353 2354 @*/ 2355 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2356 { 2357 PetscErrorCode ierr; 2358 2359 PetscFunctionBegin; 2360 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2361 if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 2362 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2363 PetscFunctionReturn(0); 2364 } 2365 2366 2367 /*@ 2368 DMCoarsen - Coarsens a DM object 2369 2370 Collective on DM 2371 2372 Input Parameter: 2373 + dm - the DM object 2374 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2375 2376 Output Parameter: 2377 . dmc - the coarsened DM 2378 2379 Level: developer 2380 2381 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2382 2383 @*/ 2384 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 2385 { 2386 PetscErrorCode ierr; 2387 DMCoarsenHookLink link; 2388 2389 PetscFunctionBegin; 2390 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2391 if (!dm->ops->coarsen) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot coarsen"); 2392 ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2393 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 2394 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 2395 ierr = DMSetCoarseDM(dm,*dmc);CHKERRQ(ierr); 2396 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2397 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2398 (*dmc)->ctx = dm->ctx; 2399 (*dmc)->levelup = dm->levelup; 2400 (*dmc)->leveldown = dm->leveldown + 1; 2401 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2402 for (link=dm->coarsenhook; link; link=link->next) { 2403 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2404 } 2405 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2406 PetscFunctionReturn(0); 2407 } 2408 2409 /*@C 2410 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2411 2412 Logically Collective 2413 2414 Input Arguments: 2415 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2416 . coarsenhook - function to run when setting up a coarser level 2417 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2418 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2419 2420 Calling sequence of coarsenhook: 2421 $ coarsenhook(DM fine,DM coarse,void *ctx); 2422 2423 + fine - fine level DM 2424 . coarse - coarse level DM to restrict problem to 2425 - ctx - optional user-defined function context 2426 2427 Calling sequence for restricthook: 2428 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2429 2430 + fine - fine level DM 2431 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2432 . rscale - scaling vector for restriction 2433 . inject - matrix restricting by injection 2434 . coarse - coarse level DM to update 2435 - ctx - optional user-defined function context 2436 2437 Level: advanced 2438 2439 Notes: 2440 This function is only needed if auxiliary data needs to be set up on coarse grids. 2441 2442 If this function is called multiple times, the hooks will be run in the order they are added. 2443 2444 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2445 extract the finest level information from its context (instead of from the SNES). 2446 2447 This function is currently not available from Fortran. 2448 2449 .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2450 @*/ 2451 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2452 { 2453 PetscErrorCode ierr; 2454 DMCoarsenHookLink link,*p; 2455 2456 PetscFunctionBegin; 2457 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2458 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 2459 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 2460 } 2461 ierr = PetscNew(&link);CHKERRQ(ierr); 2462 link->coarsenhook = coarsenhook; 2463 link->restricthook = restricthook; 2464 link->ctx = ctx; 2465 link->next = NULL; 2466 *p = link; 2467 PetscFunctionReturn(0); 2468 } 2469 2470 /*@C 2471 DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid 2472 2473 Logically Collective 2474 2475 Input Arguments: 2476 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2477 . coarsenhook - function to run when setting up a coarser level 2478 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2479 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2480 2481 Level: advanced 2482 2483 Notes: 2484 This function does nothing if the hook is not in the list. 2485 2486 This function is currently not available from Fortran. 2487 2488 .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2489 @*/ 2490 PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2491 { 2492 PetscErrorCode ierr; 2493 DMCoarsenHookLink link,*p; 2494 2495 PetscFunctionBegin; 2496 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2497 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 2498 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 2499 link = *p; 2500 *p = link->next; 2501 ierr = PetscFree(link);CHKERRQ(ierr); 2502 break; 2503 } 2504 } 2505 PetscFunctionReturn(0); 2506 } 2507 2508 2509 /*@ 2510 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 2511 2512 Collective if any hooks are 2513 2514 Input Arguments: 2515 + fine - finer DM to use as a base 2516 . restrct - restriction matrix, apply using MatRestrict() 2517 . rscale - scaling vector for restriction 2518 . inject - injection matrix, also use MatRestrict() 2519 - coarse - coarser DM to update 2520 2521 Level: developer 2522 2523 .seealso: DMCoarsenHookAdd(), MatRestrict() 2524 @*/ 2525 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 2526 { 2527 PetscErrorCode ierr; 2528 DMCoarsenHookLink link; 2529 2530 PetscFunctionBegin; 2531 for (link=fine->coarsenhook; link; link=link->next) { 2532 if (link->restricthook) { 2533 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 2534 } 2535 } 2536 PetscFunctionReturn(0); 2537 } 2538 2539 /*@C 2540 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 2541 2542 Logically Collective 2543 2544 Input Arguments: 2545 + global - global DM 2546 . ddhook - function to run to pass data to the decomposition DM upon its creation 2547 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2548 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2549 2550 2551 Calling sequence for ddhook: 2552 $ ddhook(DM global,DM block,void *ctx) 2553 2554 + global - global DM 2555 . block - block DM 2556 - ctx - optional user-defined function context 2557 2558 Calling sequence for restricthook: 2559 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 2560 2561 + global - global DM 2562 . out - scatter to the outer (with ghost and overlap points) block vector 2563 . in - scatter to block vector values only owned locally 2564 . block - block DM 2565 - ctx - optional user-defined function context 2566 2567 Level: advanced 2568 2569 Notes: 2570 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 2571 2572 If this function is called multiple times, the hooks will be run in the order they are added. 2573 2574 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2575 extract the global information from its context (instead of from the SNES). 2576 2577 This function is currently not available from Fortran. 2578 2579 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2580 @*/ 2581 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2582 { 2583 PetscErrorCode ierr; 2584 DMSubDomainHookLink link,*p; 2585 2586 PetscFunctionBegin; 2587 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2588 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 2589 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 2590 } 2591 ierr = PetscNew(&link);CHKERRQ(ierr); 2592 link->restricthook = restricthook; 2593 link->ddhook = ddhook; 2594 link->ctx = ctx; 2595 link->next = NULL; 2596 *p = link; 2597 PetscFunctionReturn(0); 2598 } 2599 2600 /*@C 2601 DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid 2602 2603 Logically Collective 2604 2605 Input Arguments: 2606 + global - global DM 2607 . ddhook - function to run to pass data to the decomposition DM upon its creation 2608 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2609 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2610 2611 Level: advanced 2612 2613 Notes: 2614 2615 This function is currently not available from Fortran. 2616 2617 .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2618 @*/ 2619 PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2620 { 2621 PetscErrorCode ierr; 2622 DMSubDomainHookLink link,*p; 2623 2624 PetscFunctionBegin; 2625 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2626 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 2627 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 2628 link = *p; 2629 *p = link->next; 2630 ierr = PetscFree(link);CHKERRQ(ierr); 2631 break; 2632 } 2633 } 2634 PetscFunctionReturn(0); 2635 } 2636 2637 /*@ 2638 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 2639 2640 Collective if any hooks are 2641 2642 Input Arguments: 2643 + fine - finer DM to use as a base 2644 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 2645 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 2646 - coarse - coarer DM to update 2647 2648 Level: developer 2649 2650 .seealso: DMCoarsenHookAdd(), MatRestrict() 2651 @*/ 2652 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 2653 { 2654 PetscErrorCode ierr; 2655 DMSubDomainHookLink link; 2656 2657 PetscFunctionBegin; 2658 for (link=global->subdomainhook; link; link=link->next) { 2659 if (link->restricthook) { 2660 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2661 } 2662 } 2663 PetscFunctionReturn(0); 2664 } 2665 2666 /*@ 2667 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2668 2669 Not Collective 2670 2671 Input Parameter: 2672 . dm - the DM object 2673 2674 Output Parameter: 2675 . level - number of coarsenings 2676 2677 Level: developer 2678 2679 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2680 2681 @*/ 2682 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2683 { 2684 PetscFunctionBegin; 2685 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2686 *level = dm->leveldown; 2687 PetscFunctionReturn(0); 2688 } 2689 2690 2691 2692 /*@C 2693 DMRefineHierarchy - Refines a DM object, all levels at once 2694 2695 Collective on DM 2696 2697 Input Parameter: 2698 + dm - the DM object 2699 - nlevels - the number of levels of refinement 2700 2701 Output Parameter: 2702 . dmf - the refined DM hierarchy 2703 2704 Level: developer 2705 2706 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2707 2708 @*/ 2709 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 2710 { 2711 PetscErrorCode ierr; 2712 2713 PetscFunctionBegin; 2714 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2715 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2716 if (nlevels == 0) PetscFunctionReturn(0); 2717 if (dm->ops->refinehierarchy) { 2718 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2719 } else if (dm->ops->refine) { 2720 PetscInt i; 2721 2722 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2723 for (i=1; i<nlevels; i++) { 2724 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2725 } 2726 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2727 PetscFunctionReturn(0); 2728 } 2729 2730 /*@C 2731 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2732 2733 Collective on DM 2734 2735 Input Parameter: 2736 + dm - the DM object 2737 - nlevels - the number of levels of coarsening 2738 2739 Output Parameter: 2740 . dmc - the coarsened DM hierarchy 2741 2742 Level: developer 2743 2744 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2745 2746 @*/ 2747 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 2748 { 2749 PetscErrorCode ierr; 2750 2751 PetscFunctionBegin; 2752 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2753 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2754 if (nlevels == 0) PetscFunctionReturn(0); 2755 PetscValidPointer(dmc,3); 2756 if (dm->ops->coarsenhierarchy) { 2757 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 2758 } else if (dm->ops->coarsen) { 2759 PetscInt i; 2760 2761 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 2762 for (i=1; i<nlevels; i++) { 2763 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 2764 } 2765 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 2766 PetscFunctionReturn(0); 2767 } 2768 2769 /*@ 2770 DMCreateAggregates - Gets the aggregates that map between 2771 grids associated with two DMs. 2772 2773 Collective on DM 2774 2775 Input Parameters: 2776 + dmc - the coarse grid DM 2777 - dmf - the fine grid DM 2778 2779 Output Parameters: 2780 . rest - the restriction matrix (transpose of the projection matrix) 2781 2782 Level: intermediate 2783 2784 .keywords: interpolation, restriction, multigrid 2785 2786 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 2787 @*/ 2788 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 2789 { 2790 PetscErrorCode ierr; 2791 2792 PetscFunctionBegin; 2793 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 2794 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 2795 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 2796 PetscFunctionReturn(0); 2797 } 2798 2799 /*@C 2800 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 2801 2802 Not Collective 2803 2804 Input Parameters: 2805 + dm - the DM object 2806 - destroy - the destroy function 2807 2808 Level: intermediate 2809 2810 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2811 2812 @*/ 2813 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 2814 { 2815 PetscFunctionBegin; 2816 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2817 dm->ctxdestroy = destroy; 2818 PetscFunctionReturn(0); 2819 } 2820 2821 /*@ 2822 DMSetApplicationContext - Set a user context into a DM object 2823 2824 Not Collective 2825 2826 Input Parameters: 2827 + dm - the DM object 2828 - ctx - the user context 2829 2830 Level: intermediate 2831 2832 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2833 2834 @*/ 2835 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 2836 { 2837 PetscFunctionBegin; 2838 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2839 dm->ctx = ctx; 2840 PetscFunctionReturn(0); 2841 } 2842 2843 /*@ 2844 DMGetApplicationContext - Gets a user context from a DM object 2845 2846 Not Collective 2847 2848 Input Parameter: 2849 . dm - the DM object 2850 2851 Output Parameter: 2852 . ctx - the user context 2853 2854 Level: intermediate 2855 2856 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2857 2858 @*/ 2859 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 2860 { 2861 PetscFunctionBegin; 2862 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2863 *(void**)ctx = dm->ctx; 2864 PetscFunctionReturn(0); 2865 } 2866 2867 /*@C 2868 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 2869 2870 Logically Collective on DM 2871 2872 Input Parameter: 2873 + dm - the DM object 2874 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 2875 2876 Level: intermediate 2877 2878 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 2879 DMSetJacobian() 2880 2881 @*/ 2882 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 2883 { 2884 PetscFunctionBegin; 2885 dm->ops->computevariablebounds = f; 2886 PetscFunctionReturn(0); 2887 } 2888 2889 /*@ 2890 DMHasVariableBounds - does the DM object have a variable bounds function? 2891 2892 Not Collective 2893 2894 Input Parameter: 2895 . dm - the DM object to destroy 2896 2897 Output Parameter: 2898 . flg - PETSC_TRUE if the variable bounds function exists 2899 2900 Level: developer 2901 2902 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2903 2904 @*/ 2905 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 2906 { 2907 PetscFunctionBegin; 2908 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 2909 PetscFunctionReturn(0); 2910 } 2911 2912 /*@C 2913 DMComputeVariableBounds - compute variable bounds used by SNESVI. 2914 2915 Logically Collective on DM 2916 2917 Input Parameters: 2918 . dm - the DM object 2919 2920 Output parameters: 2921 + xl - lower bound 2922 - xu - upper bound 2923 2924 Level: advanced 2925 2926 Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 2927 2928 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2929 2930 @*/ 2931 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 2932 { 2933 PetscErrorCode ierr; 2934 2935 PetscFunctionBegin; 2936 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 2937 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 2938 if (dm->ops->computevariablebounds) { 2939 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 2940 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 2941 PetscFunctionReturn(0); 2942 } 2943 2944 /*@ 2945 DMHasColoring - does the DM object have a method of providing a coloring? 2946 2947 Not Collective 2948 2949 Input Parameter: 2950 . dm - the DM object 2951 2952 Output Parameter: 2953 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 2954 2955 Level: developer 2956 2957 .seealso DMHasFunction(), DMCreateColoring() 2958 2959 @*/ 2960 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 2961 { 2962 PetscFunctionBegin; 2963 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 2964 PetscFunctionReturn(0); 2965 } 2966 2967 /*@ 2968 DMHasCreateRestriction - does the DM object have a method of providing a restriction? 2969 2970 Not Collective 2971 2972 Input Parameter: 2973 . dm - the DM object 2974 2975 Output Parameter: 2976 . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction(). 2977 2978 Level: developer 2979 2980 .seealso DMHasFunction(), DMCreateRestriction() 2981 2982 @*/ 2983 PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg) 2984 { 2985 PetscFunctionBegin; 2986 *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE; 2987 PetscFunctionReturn(0); 2988 } 2989 2990 /*@C 2991 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 2992 2993 Collective on DM 2994 2995 Input Parameter: 2996 + dm - the DM object 2997 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 2998 2999 Level: developer 3000 3001 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3002 3003 @*/ 3004 PetscErrorCode DMSetVec(DM dm,Vec x) 3005 { 3006 PetscErrorCode ierr; 3007 3008 PetscFunctionBegin; 3009 if (x) { 3010 if (!dm->x) { 3011 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 3012 } 3013 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 3014 } else if (dm->x) { 3015 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 3016 } 3017 PetscFunctionReturn(0); 3018 } 3019 3020 PetscFunctionList DMList = NULL; 3021 PetscBool DMRegisterAllCalled = PETSC_FALSE; 3022 3023 /*@C 3024 DMSetType - Builds a DM, for a particular DM implementation. 3025 3026 Collective on DM 3027 3028 Input Parameters: 3029 + dm - The DM object 3030 - method - The name of the DM type 3031 3032 Options Database Key: 3033 . -dm_type <type> - Sets the DM type; use -help for a list of available types 3034 3035 Notes: 3036 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 3037 3038 Level: intermediate 3039 3040 .keywords: DM, set, type 3041 .seealso: DMGetType(), DMCreate() 3042 @*/ 3043 PetscErrorCode DMSetType(DM dm, DMType method) 3044 { 3045 PetscErrorCode (*r)(DM); 3046 PetscBool match; 3047 PetscErrorCode ierr; 3048 3049 PetscFunctionBegin; 3050 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3051 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 3052 if (match) PetscFunctionReturn(0); 3053 3054 ierr = DMRegisterAll();CHKERRQ(ierr); 3055 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 3056 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 3057 3058 if (dm->ops->destroy) { 3059 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 3060 dm->ops->destroy = NULL; 3061 } 3062 ierr = (*r)(dm);CHKERRQ(ierr); 3063 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 3064 PetscFunctionReturn(0); 3065 } 3066 3067 /*@C 3068 DMGetType - Gets the DM type name (as a string) from the DM. 3069 3070 Not Collective 3071 3072 Input Parameter: 3073 . dm - The DM 3074 3075 Output Parameter: 3076 . type - The DM type name 3077 3078 Level: intermediate 3079 3080 .keywords: DM, get, type, name 3081 .seealso: DMSetType(), DMCreate() 3082 @*/ 3083 PetscErrorCode DMGetType(DM dm, DMType *type) 3084 { 3085 PetscErrorCode ierr; 3086 3087 PetscFunctionBegin; 3088 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3089 PetscValidPointer(type,2); 3090 ierr = DMRegisterAll();CHKERRQ(ierr); 3091 *type = ((PetscObject)dm)->type_name; 3092 PetscFunctionReturn(0); 3093 } 3094 3095 /*@C 3096 DMConvert - Converts a DM to another DM, either of the same or different type. 3097 3098 Collective on DM 3099 3100 Input Parameters: 3101 + dm - the DM 3102 - newtype - new DM type (use "same" for the same type) 3103 3104 Output Parameter: 3105 . M - pointer to new DM 3106 3107 Notes: 3108 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 3109 the MPI communicator of the generated DM is always the same as the communicator 3110 of the input DM. 3111 3112 Level: intermediate 3113 3114 .seealso: DMCreate() 3115 @*/ 3116 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 3117 { 3118 DM B; 3119 char convname[256]; 3120 PetscBool sametype/*, issame */; 3121 PetscErrorCode ierr; 3122 3123 PetscFunctionBegin; 3124 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3125 PetscValidType(dm,1); 3126 PetscValidPointer(M,3); 3127 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 3128 /* ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); */ 3129 if (sametype) { 3130 *M = dm; 3131 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 3132 PetscFunctionReturn(0); 3133 } else { 3134 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 3135 3136 /* 3137 Order of precedence: 3138 1) See if a specialized converter is known to the current DM. 3139 2) See if a specialized converter is known to the desired DM class. 3140 3) See if a good general converter is registered for the desired class 3141 4) See if a good general converter is known for the current matrix. 3142 5) Use a really basic converter. 3143 */ 3144 3145 /* 1) See if a specialized converter is known to the current DM and the desired class */ 3146 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 3147 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 3148 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 3149 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 3150 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 3151 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 3152 if (conv) goto foundconv; 3153 3154 /* 2) See if a specialized converter is known to the desired DM class. */ 3155 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 3156 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 3157 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 3158 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 3159 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 3160 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 3161 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 3162 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 3163 if (conv) { 3164 ierr = DMDestroy(&B);CHKERRQ(ierr); 3165 goto foundconv; 3166 } 3167 3168 #if 0 3169 /* 3) See if a good general converter is registered for the desired class */ 3170 conv = B->ops->convertfrom; 3171 ierr = DMDestroy(&B);CHKERRQ(ierr); 3172 if (conv) goto foundconv; 3173 3174 /* 4) See if a good general converter is known for the current matrix */ 3175 if (dm->ops->convert) { 3176 conv = dm->ops->convert; 3177 } 3178 if (conv) goto foundconv; 3179 #endif 3180 3181 /* 5) Use a really basic converter. */ 3182 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 3183 3184 foundconv: 3185 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3186 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 3187 /* Things that are independent of DM type: We should consult DMClone() here */ 3188 { 3189 PetscBool isper; 3190 const PetscReal *maxCell, *L; 3191 const DMBoundaryType *bd; 3192 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 3193 ierr = DMSetPeriodicity(*M, isper, maxCell, L, bd);CHKERRQ(ierr); 3194 } 3195 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3196 } 3197 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 3198 PetscFunctionReturn(0); 3199 } 3200 3201 /*--------------------------------------------------------------------------------------------------------------------*/ 3202 3203 /*@C 3204 DMRegister - Adds a new DM component implementation 3205 3206 Not Collective 3207 3208 Input Parameters: 3209 + name - The name of a new user-defined creation routine 3210 - create_func - The creation routine itself 3211 3212 Notes: 3213 DMRegister() may be called multiple times to add several user-defined DMs 3214 3215 3216 Sample usage: 3217 .vb 3218 DMRegister("my_da", MyDMCreate); 3219 .ve 3220 3221 Then, your DM type can be chosen with the procedural interface via 3222 .vb 3223 DMCreate(MPI_Comm, DM *); 3224 DMSetType(DM,"my_da"); 3225 .ve 3226 or at runtime via the option 3227 .vb 3228 -da_type my_da 3229 .ve 3230 3231 Level: advanced 3232 3233 .keywords: DM, register 3234 .seealso: DMRegisterAll(), DMRegisterDestroy() 3235 3236 @*/ 3237 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 3238 { 3239 PetscErrorCode ierr; 3240 3241 PetscFunctionBegin; 3242 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 3243 PetscFunctionReturn(0); 3244 } 3245 3246 /*@C 3247 DMLoad - Loads a DM that has been stored in binary with DMView(). 3248 3249 Collective on PetscViewer 3250 3251 Input Parameters: 3252 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 3253 some related function before a call to DMLoad(). 3254 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 3255 HDF5 file viewer, obtained from PetscViewerHDF5Open() 3256 3257 Level: intermediate 3258 3259 Notes: 3260 The type is determined by the data in the file, any type set into the DM before this call is ignored. 3261 3262 Notes for advanced users: 3263 Most users should not need to know the details of the binary storage 3264 format, since DMLoad() and DMView() completely hide these details. 3265 But for anyone who's interested, the standard binary matrix storage 3266 format is 3267 .vb 3268 has not yet been determined 3269 .ve 3270 3271 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 3272 @*/ 3273 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 3274 { 3275 PetscBool isbinary, ishdf5; 3276 PetscErrorCode ierr; 3277 3278 PetscFunctionBegin; 3279 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 3280 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3281 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 3282 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 3283 if (isbinary) { 3284 PetscInt classid; 3285 char type[256]; 3286 3287 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3288 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3289 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3290 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3291 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3292 } else if (ishdf5) { 3293 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3294 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3295 PetscFunctionReturn(0); 3296 } 3297 3298 /******************************** FEM Support **********************************/ 3299 3300 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3301 { 3302 PetscInt f; 3303 PetscErrorCode ierr; 3304 3305 PetscFunctionBegin; 3306 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3307 for (f = 0; f < len; ++f) { 3308 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3309 } 3310 PetscFunctionReturn(0); 3311 } 3312 3313 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3314 { 3315 PetscInt f, g; 3316 PetscErrorCode ierr; 3317 3318 PetscFunctionBegin; 3319 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3320 for (f = 0; f < rows; ++f) { 3321 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3322 for (g = 0; g < cols; ++g) { 3323 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3324 } 3325 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3326 } 3327 PetscFunctionReturn(0); 3328 } 3329 3330 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3331 { 3332 PetscInt localSize, bs; 3333 PetscMPIInt size; 3334 Vec x, xglob; 3335 const PetscScalar *xarray; 3336 PetscErrorCode ierr; 3337 3338 PetscFunctionBegin; 3339 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);CHKERRQ(ierr); 3340 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3341 ierr = VecCopy(X, x);CHKERRQ(ierr); 3342 ierr = VecChop(x, tol);CHKERRQ(ierr); 3343 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);CHKERRQ(ierr); 3344 if (size > 1) { 3345 ierr = VecGetLocalSize(x,&localSize);CHKERRQ(ierr); 3346 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr); 3347 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 3348 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);CHKERRQ(ierr); 3349 } else { 3350 xglob = x; 3351 } 3352 ierr = VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));CHKERRQ(ierr); 3353 if (size > 1) { 3354 ierr = VecDestroy(&xglob);CHKERRQ(ierr); 3355 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 3356 } 3357 ierr = VecDestroy(&x);CHKERRQ(ierr); 3358 PetscFunctionReturn(0); 3359 } 3360 3361 /*@ 3362 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 3363 3364 Input Parameter: 3365 . dm - The DM 3366 3367 Output Parameter: 3368 . section - The PetscSection 3369 3370 Level: intermediate 3371 3372 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3373 3374 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3375 @*/ 3376 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 3377 { 3378 PetscErrorCode ierr; 3379 3380 PetscFunctionBegin; 3381 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3382 PetscValidPointer(section, 2); 3383 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3384 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3385 if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 3386 } 3387 *section = dm->defaultSection; 3388 PetscFunctionReturn(0); 3389 } 3390 3391 /*@ 3392 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3393 3394 Input Parameters: 3395 + dm - The DM 3396 - section - The PetscSection 3397 3398 Level: intermediate 3399 3400 Note: Any existing Section will be destroyed 3401 3402 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3403 @*/ 3404 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 3405 { 3406 PetscInt numFields = 0; 3407 PetscInt f; 3408 PetscErrorCode ierr; 3409 3410 PetscFunctionBegin; 3411 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3412 if (section) { 3413 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3414 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3415 } 3416 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3417 dm->defaultSection = section; 3418 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3419 if (numFields) { 3420 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3421 for (f = 0; f < numFields; ++f) { 3422 PetscObject disc; 3423 const char *name; 3424 3425 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3426 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3427 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3428 } 3429 } 3430 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3431 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3432 PetscFunctionReturn(0); 3433 } 3434 3435 /*@ 3436 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3437 3438 not collective 3439 3440 Input Parameter: 3441 . dm - The DM 3442 3443 Output Parameter: 3444 + 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. 3445 - 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. 3446 3447 Level: advanced 3448 3449 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3450 3451 .seealso: DMSetDefaultConstraints() 3452 @*/ 3453 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3454 { 3455 PetscErrorCode ierr; 3456 3457 PetscFunctionBegin; 3458 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3459 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3460 if (section) {*section = dm->defaultConstraintSection;} 3461 if (mat) {*mat = dm->defaultConstraintMat;} 3462 PetscFunctionReturn(0); 3463 } 3464 3465 /*@ 3466 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3467 3468 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(). 3469 3470 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. 3471 3472 collective on dm 3473 3474 Input Parameters: 3475 + dm - The DM 3476 + 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). 3477 - 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). 3478 3479 Level: advanced 3480 3481 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3482 3483 .seealso: DMGetDefaultConstraints() 3484 @*/ 3485 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3486 { 3487 PetscMPIInt result; 3488 PetscErrorCode ierr; 3489 3490 PetscFunctionBegin; 3491 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3492 if (section) { 3493 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3494 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3495 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3496 } 3497 if (mat) { 3498 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3499 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3500 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3501 } 3502 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3503 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3504 dm->defaultConstraintSection = section; 3505 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3506 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3507 dm->defaultConstraintMat = mat; 3508 PetscFunctionReturn(0); 3509 } 3510 3511 #ifdef PETSC_USE_DEBUG 3512 /* 3513 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3514 3515 Input Parameters: 3516 + dm - The DM 3517 . localSection - PetscSection describing the local data layout 3518 - globalSection - PetscSection describing the global data layout 3519 3520 Level: intermediate 3521 3522 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3523 */ 3524 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3525 { 3526 MPI_Comm comm; 3527 PetscLayout layout; 3528 const PetscInt *ranges; 3529 PetscInt pStart, pEnd, p, nroots; 3530 PetscMPIInt size, rank; 3531 PetscBool valid = PETSC_TRUE, gvalid; 3532 PetscErrorCode ierr; 3533 3534 PetscFunctionBegin; 3535 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3536 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3537 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3538 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3539 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3540 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3541 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3542 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3543 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3544 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3545 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3546 for (p = pStart; p < pEnd; ++p) { 3547 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3548 3549 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3550 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3551 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3552 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3553 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3554 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3555 if (!gdof) continue; /* Censored point */ 3556 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;} 3557 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;} 3558 if (gdof < 0) { 3559 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3560 for (d = 0; d < gsize; ++d) { 3561 PetscInt offset = -(goff+1) + d, r; 3562 3563 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3564 if (r < 0) r = -(r+2); 3565 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;} 3566 } 3567 } 3568 } 3569 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3570 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3571 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3572 if (!gvalid) { 3573 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3574 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3575 } 3576 PetscFunctionReturn(0); 3577 } 3578 #endif 3579 3580 /*@ 3581 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3582 3583 Collective on DM 3584 3585 Input Parameter: 3586 . dm - The DM 3587 3588 Output Parameter: 3589 . section - The PetscSection 3590 3591 Level: intermediate 3592 3593 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3594 3595 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3596 @*/ 3597 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3598 { 3599 PetscErrorCode ierr; 3600 3601 PetscFunctionBegin; 3602 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3603 PetscValidPointer(section, 2); 3604 if (!dm->defaultGlobalSection) { 3605 PetscSection s; 3606 3607 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3608 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3609 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3610 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3611 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3612 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3613 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 3614 } 3615 *section = dm->defaultGlobalSection; 3616 PetscFunctionReturn(0); 3617 } 3618 3619 /*@ 3620 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3621 3622 Input Parameters: 3623 + dm - The DM 3624 - section - The PetscSection, or NULL 3625 3626 Level: intermediate 3627 3628 Note: Any existing Section will be destroyed 3629 3630 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3631 @*/ 3632 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3633 { 3634 PetscErrorCode ierr; 3635 3636 PetscFunctionBegin; 3637 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3638 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3639 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3640 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3641 dm->defaultGlobalSection = section; 3642 #ifdef PETSC_USE_DEBUG 3643 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3644 #endif 3645 PetscFunctionReturn(0); 3646 } 3647 3648 /*@ 3649 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3650 it is created from the default PetscSection layouts in the DM. 3651 3652 Input Parameter: 3653 . dm - The DM 3654 3655 Output Parameter: 3656 . sf - The PetscSF 3657 3658 Level: intermediate 3659 3660 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3661 3662 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3663 @*/ 3664 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3665 { 3666 PetscInt nroots; 3667 PetscErrorCode ierr; 3668 3669 PetscFunctionBegin; 3670 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3671 PetscValidPointer(sf, 2); 3672 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3673 if (nroots < 0) { 3674 PetscSection section, gSection; 3675 3676 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3677 if (section) { 3678 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3679 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3680 } else { 3681 *sf = NULL; 3682 PetscFunctionReturn(0); 3683 } 3684 } 3685 *sf = dm->defaultSF; 3686 PetscFunctionReturn(0); 3687 } 3688 3689 /*@ 3690 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3691 3692 Input Parameters: 3693 + dm - The DM 3694 - sf - The PetscSF 3695 3696 Level: intermediate 3697 3698 Note: Any previous SF is destroyed 3699 3700 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3701 @*/ 3702 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3703 { 3704 PetscErrorCode ierr; 3705 3706 PetscFunctionBegin; 3707 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3708 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3709 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3710 dm->defaultSF = sf; 3711 PetscFunctionReturn(0); 3712 } 3713 3714 /*@C 3715 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3716 describing the data layout. 3717 3718 Input Parameters: 3719 + dm - The DM 3720 . localSection - PetscSection describing the local data layout 3721 - globalSection - PetscSection describing the global data layout 3722 3723 Level: intermediate 3724 3725 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3726 @*/ 3727 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3728 { 3729 MPI_Comm comm; 3730 PetscLayout layout; 3731 const PetscInt *ranges; 3732 PetscInt *local; 3733 PetscSFNode *remote; 3734 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3735 PetscMPIInt size, rank; 3736 PetscErrorCode ierr; 3737 3738 PetscFunctionBegin; 3739 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3740 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3741 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3742 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3743 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3744 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3745 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3746 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3747 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3748 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3749 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3750 for (p = pStart; p < pEnd; ++p) { 3751 PetscInt gdof, gcdof; 3752 3753 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3754 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3755 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)); 3756 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3757 } 3758 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3759 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3760 for (p = pStart, l = 0; p < pEnd; ++p) { 3761 const PetscInt *cind; 3762 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3763 3764 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3765 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3766 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3767 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3768 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3769 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3770 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3771 if (!gdof) continue; /* Censored point */ 3772 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3773 if (gsize != dof-cdof) { 3774 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); 3775 cdof = 0; /* Ignore constraints */ 3776 } 3777 for (d = 0, c = 0; d < dof; ++d) { 3778 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3779 local[l+d-c] = off+d; 3780 } 3781 if (gdof < 0) { 3782 for (d = 0; d < gsize; ++d, ++l) { 3783 PetscInt offset = -(goff+1) + d, r; 3784 3785 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3786 if (r < 0) r = -(r+2); 3787 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); 3788 remote[l].rank = r; 3789 remote[l].index = offset - ranges[r]; 3790 } 3791 } else { 3792 for (d = 0; d < gsize; ++d, ++l) { 3793 remote[l].rank = rank; 3794 remote[l].index = goff+d - ranges[rank]; 3795 } 3796 } 3797 } 3798 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3799 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3800 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3801 PetscFunctionReturn(0); 3802 } 3803 3804 /*@ 3805 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3806 3807 Input Parameter: 3808 . dm - The DM 3809 3810 Output Parameter: 3811 . sf - The PetscSF 3812 3813 Level: intermediate 3814 3815 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3816 3817 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3818 @*/ 3819 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3820 { 3821 PetscFunctionBegin; 3822 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3823 PetscValidPointer(sf, 2); 3824 *sf = dm->sf; 3825 PetscFunctionReturn(0); 3826 } 3827 3828 /*@ 3829 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3830 3831 Input Parameters: 3832 + dm - The DM 3833 - sf - The PetscSF 3834 3835 Level: intermediate 3836 3837 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3838 @*/ 3839 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3840 { 3841 PetscErrorCode ierr; 3842 3843 PetscFunctionBegin; 3844 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3845 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3846 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3847 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3848 dm->sf = sf; 3849 PetscFunctionReturn(0); 3850 } 3851 3852 /*@ 3853 DMGetDS - Get the PetscDS 3854 3855 Input Parameter: 3856 . dm - The DM 3857 3858 Output Parameter: 3859 . prob - The PetscDS 3860 3861 Level: developer 3862 3863 .seealso: DMSetDS() 3864 @*/ 3865 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3866 { 3867 PetscFunctionBegin; 3868 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3869 PetscValidPointer(prob, 2); 3870 *prob = dm->prob; 3871 PetscFunctionReturn(0); 3872 } 3873 3874 /*@ 3875 DMSetDS - Set the PetscDS 3876 3877 Input Parameters: 3878 + dm - The DM 3879 - prob - The PetscDS 3880 3881 Level: developer 3882 3883 .seealso: DMGetDS() 3884 @*/ 3885 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3886 { 3887 PetscInt dimEmbed; 3888 PetscErrorCode ierr; 3889 3890 PetscFunctionBegin; 3891 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3892 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3893 ierr = PetscObjectReference((PetscObject) prob);CHKERRQ(ierr); 3894 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3895 dm->prob = prob; 3896 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 3897 ierr = PetscDSSetCoordinateDimension(prob, dimEmbed);CHKERRQ(ierr); 3898 PetscFunctionReturn(0); 3899 } 3900 3901 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3902 { 3903 PetscErrorCode ierr; 3904 3905 PetscFunctionBegin; 3906 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3907 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3908 PetscFunctionReturn(0); 3909 } 3910 3911 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3912 { 3913 PetscInt Nf, f; 3914 PetscErrorCode ierr; 3915 3916 PetscFunctionBegin; 3917 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3918 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3919 for (f = Nf; f < numFields; ++f) { 3920 PetscContainer obj; 3921 3922 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3923 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3924 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3925 } 3926 PetscFunctionReturn(0); 3927 } 3928 3929 /*@ 3930 DMGetField - Return the discretization object for a given DM field 3931 3932 Not collective 3933 3934 Input Parameters: 3935 + dm - The DM 3936 - f - The field number 3937 3938 Output Parameter: 3939 . field - The discretization object 3940 3941 Level: developer 3942 3943 .seealso: DMSetField() 3944 @*/ 3945 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3946 { 3947 PetscErrorCode ierr; 3948 3949 PetscFunctionBegin; 3950 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3951 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3952 PetscFunctionReturn(0); 3953 } 3954 3955 /*@ 3956 DMSetField - Set the discretization object for a given DM field 3957 3958 Logically collective on DM 3959 3960 Input Parameters: 3961 + dm - The DM 3962 . f - The field number 3963 - field - The discretization object 3964 3965 Level: developer 3966 3967 .seealso: DMGetField() 3968 @*/ 3969 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3970 { 3971 PetscErrorCode ierr; 3972 3973 PetscFunctionBegin; 3974 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3975 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3976 PetscFunctionReturn(0); 3977 } 3978 3979 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3980 { 3981 DM dm_coord,dmc_coord; 3982 PetscErrorCode ierr; 3983 Vec coords,ccoords; 3984 Mat inject; 3985 PetscFunctionBegin; 3986 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3987 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3988 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3989 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3990 if (coords && !ccoords) { 3991 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3992 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 3993 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 3994 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 3995 ierr = MatDestroy(&inject);CHKERRQ(ierr); 3996 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3997 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3998 } 3999 PetscFunctionReturn(0); 4000 } 4001 4002 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 4003 { 4004 DM dm_coord,subdm_coord; 4005 PetscErrorCode ierr; 4006 Vec coords,ccoords,clcoords; 4007 VecScatter *scat_i,*scat_g; 4008 PetscFunctionBegin; 4009 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4010 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 4011 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4012 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 4013 if (coords && !ccoords) { 4014 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 4015 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4016 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 4017 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 4018 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 4019 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4020 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4021 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4022 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4023 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 4024 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 4025 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 4026 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 4027 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4028 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 4029 ierr = PetscFree(scat_i);CHKERRQ(ierr); 4030 ierr = PetscFree(scat_g);CHKERRQ(ierr); 4031 } 4032 PetscFunctionReturn(0); 4033 } 4034 4035 /*@ 4036 DMGetDimension - Return the topological dimension of the DM 4037 4038 Not collective 4039 4040 Input Parameter: 4041 . dm - The DM 4042 4043 Output Parameter: 4044 . dim - The topological dimension 4045 4046 Level: beginner 4047 4048 .seealso: DMSetDimension(), DMCreate() 4049 @*/ 4050 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 4051 { 4052 PetscFunctionBegin; 4053 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4054 PetscValidPointer(dim, 2); 4055 *dim = dm->dim; 4056 PetscFunctionReturn(0); 4057 } 4058 4059 /*@ 4060 DMSetDimension - Set the topological dimension of the DM 4061 4062 Collective on dm 4063 4064 Input Parameters: 4065 + dm - The DM 4066 - dim - The topological dimension 4067 4068 Level: beginner 4069 4070 .seealso: DMGetDimension(), DMCreate() 4071 @*/ 4072 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 4073 { 4074 PetscErrorCode ierr; 4075 4076 PetscFunctionBegin; 4077 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4078 PetscValidLogicalCollectiveInt(dm, dim, 2); 4079 dm->dim = dim; 4080 if (dm->prob->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dim);CHKERRQ(ierr);} 4081 PetscFunctionReturn(0); 4082 } 4083 4084 /*@ 4085 DMGetDimPoints - Get the half-open interval for all points of a given dimension 4086 4087 Collective on DM 4088 4089 Input Parameters: 4090 + dm - the DM 4091 - dim - the dimension 4092 4093 Output Parameters: 4094 + pStart - The first point of the given dimension 4095 . pEnd - The first point following points of the given dimension 4096 4097 Note: 4098 The points are vertices in the Hasse diagram encoding the topology. This is explained in 4099 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 4100 then the interval is empty. 4101 4102 Level: intermediate 4103 4104 .keywords: point, Hasse Diagram, dimension 4105 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 4106 @*/ 4107 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4108 { 4109 PetscInt d; 4110 PetscErrorCode ierr; 4111 4112 PetscFunctionBegin; 4113 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4114 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 4115 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 4116 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 4117 PetscFunctionReturn(0); 4118 } 4119 4120 /*@ 4121 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 4122 4123 Collective on DM 4124 4125 Input Parameters: 4126 + dm - the DM 4127 - c - coordinate vector 4128 4129 Note: 4130 The coordinates do include those for ghost points, which are in the local vector 4131 4132 Level: intermediate 4133 4134 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4135 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 4136 @*/ 4137 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 4138 { 4139 PetscErrorCode ierr; 4140 4141 PetscFunctionBegin; 4142 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4143 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4144 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4145 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4146 dm->coordinates = c; 4147 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4148 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4149 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4150 PetscFunctionReturn(0); 4151 } 4152 4153 /*@ 4154 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 4155 4156 Collective on DM 4157 4158 Input Parameters: 4159 + dm - the DM 4160 - c - coordinate vector 4161 4162 Note: 4163 The coordinates of ghost points can be set using DMSetCoordinates() 4164 followed by DMGetCoordinatesLocal(). This is intended to enable the 4165 setting of ghost coordinates outside of the domain. 4166 4167 Level: intermediate 4168 4169 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4170 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 4171 @*/ 4172 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 4173 { 4174 PetscErrorCode ierr; 4175 4176 PetscFunctionBegin; 4177 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4178 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4179 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4180 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4181 4182 dm->coordinatesLocal = c; 4183 4184 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4185 PetscFunctionReturn(0); 4186 } 4187 4188 /*@ 4189 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 4190 4191 Not Collective 4192 4193 Input Parameter: 4194 . dm - the DM 4195 4196 Output Parameter: 4197 . c - global coordinate vector 4198 4199 Note: 4200 This is a borrowed reference, so the user should NOT destroy this vector 4201 4202 Each process has only the local coordinates (does NOT have the ghost coordinates). 4203 4204 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4205 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4206 4207 Level: intermediate 4208 4209 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4210 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4211 @*/ 4212 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4213 { 4214 PetscErrorCode ierr; 4215 4216 PetscFunctionBegin; 4217 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4218 PetscValidPointer(c,2); 4219 if (!dm->coordinates && dm->coordinatesLocal) { 4220 DM cdm = NULL; 4221 4222 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4223 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4224 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4225 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4226 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4227 } 4228 *c = dm->coordinates; 4229 PetscFunctionReturn(0); 4230 } 4231 4232 /*@ 4233 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4234 4235 Collective on DM 4236 4237 Input Parameter: 4238 . dm - the DM 4239 4240 Output Parameter: 4241 . c - coordinate vector 4242 4243 Note: 4244 This is a borrowed reference, so the user should NOT destroy this vector 4245 4246 Each process has the local and ghost coordinates 4247 4248 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4249 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4250 4251 Level: intermediate 4252 4253 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4254 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4255 @*/ 4256 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4257 { 4258 PetscErrorCode ierr; 4259 4260 PetscFunctionBegin; 4261 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4262 PetscValidPointer(c,2); 4263 if (!dm->coordinatesLocal && dm->coordinates) { 4264 DM cdm = NULL; 4265 4266 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4267 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4268 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4269 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4270 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4271 } 4272 *c = dm->coordinatesLocal; 4273 PetscFunctionReturn(0); 4274 } 4275 4276 /*@ 4277 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4278 4279 Collective on DM 4280 4281 Input Parameter: 4282 . dm - the DM 4283 4284 Output Parameter: 4285 . cdm - coordinate DM 4286 4287 Level: intermediate 4288 4289 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4290 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4291 @*/ 4292 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4293 { 4294 PetscErrorCode ierr; 4295 4296 PetscFunctionBegin; 4297 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4298 PetscValidPointer(cdm,2); 4299 if (!dm->coordinateDM) { 4300 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4301 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 4302 } 4303 *cdm = dm->coordinateDM; 4304 PetscFunctionReturn(0); 4305 } 4306 4307 /*@ 4308 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4309 4310 Logically Collective on DM 4311 4312 Input Parameters: 4313 + dm - the DM 4314 - cdm - coordinate DM 4315 4316 Level: intermediate 4317 4318 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4319 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4320 @*/ 4321 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4322 { 4323 PetscErrorCode ierr; 4324 4325 PetscFunctionBegin; 4326 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4327 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4328 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 4329 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4330 dm->coordinateDM = cdm; 4331 PetscFunctionReturn(0); 4332 } 4333 4334 /*@ 4335 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4336 4337 Not Collective 4338 4339 Input Parameter: 4340 . dm - The DM object 4341 4342 Output Parameter: 4343 . dim - The embedding dimension 4344 4345 Level: intermediate 4346 4347 .keywords: mesh, coordinates 4348 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4349 @*/ 4350 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4351 { 4352 PetscFunctionBegin; 4353 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4354 PetscValidPointer(dim, 2); 4355 if (dm->dimEmbed == PETSC_DEFAULT) { 4356 dm->dimEmbed = dm->dim; 4357 } 4358 *dim = dm->dimEmbed; 4359 PetscFunctionReturn(0); 4360 } 4361 4362 /*@ 4363 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4364 4365 Not Collective 4366 4367 Input Parameters: 4368 + dm - The DM object 4369 - dim - The embedding dimension 4370 4371 Level: intermediate 4372 4373 .keywords: mesh, coordinates 4374 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4375 @*/ 4376 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4377 { 4378 PetscErrorCode ierr; 4379 4380 PetscFunctionBegin; 4381 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4382 dm->dimEmbed = dim; 4383 ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dimEmbed);CHKERRQ(ierr); 4384 PetscFunctionReturn(0); 4385 } 4386 4387 /*@ 4388 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4389 4390 Not Collective 4391 4392 Input Parameter: 4393 . dm - The DM object 4394 4395 Output Parameter: 4396 . section - The PetscSection object 4397 4398 Level: intermediate 4399 4400 .keywords: mesh, coordinates 4401 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4402 @*/ 4403 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4404 { 4405 DM cdm; 4406 PetscErrorCode ierr; 4407 4408 PetscFunctionBegin; 4409 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4410 PetscValidPointer(section, 2); 4411 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4412 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4413 PetscFunctionReturn(0); 4414 } 4415 4416 /*@ 4417 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4418 4419 Not Collective 4420 4421 Input Parameters: 4422 + dm - The DM object 4423 . dim - The embedding dimension, or PETSC_DETERMINE 4424 - section - The PetscSection object 4425 4426 Level: intermediate 4427 4428 .keywords: mesh, coordinates 4429 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4430 @*/ 4431 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4432 { 4433 DM cdm; 4434 PetscErrorCode ierr; 4435 4436 PetscFunctionBegin; 4437 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4438 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4439 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4440 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4441 if (dim == PETSC_DETERMINE) { 4442 PetscInt d = PETSC_DEFAULT; 4443 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4444 4445 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4446 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4447 pStart = PetscMax(vStart, pStart); 4448 pEnd = PetscMin(vEnd, pEnd); 4449 for (v = pStart; v < pEnd; ++v) { 4450 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4451 if (dd) {d = dd; break;} 4452 } 4453 if (d < 0) d = PETSC_DEFAULT; 4454 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4455 } 4456 PetscFunctionReturn(0); 4457 } 4458 4459 /*@C 4460 DMGetPeriodicity - Get the description of mesh periodicity 4461 4462 Input Parameters: 4463 . dm - The DM object 4464 4465 Output Parameters: 4466 + per - Whether the DM is periodic or not 4467 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4468 . L - If we assume the mesh is a torus, this is the length of each coordinate 4469 - bd - This describes the type of periodicity in each topological dimension 4470 4471 Level: developer 4472 4473 .seealso: DMGetPeriodicity() 4474 @*/ 4475 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4476 { 4477 PetscFunctionBegin; 4478 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4479 if (per) *per = dm->periodic; 4480 if (L) *L = dm->L; 4481 if (maxCell) *maxCell = dm->maxCell; 4482 if (bd) *bd = dm->bdtype; 4483 PetscFunctionReturn(0); 4484 } 4485 4486 /*@C 4487 DMSetPeriodicity - Set the description of mesh periodicity 4488 4489 Input Parameters: 4490 + dm - The DM object 4491 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 4492 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4493 . L - If we assume the mesh is a torus, this is the length of each coordinate 4494 - bd - This describes the type of periodicity in each topological dimension 4495 4496 Level: developer 4497 4498 .seealso: DMGetPeriodicity() 4499 @*/ 4500 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4501 { 4502 PetscInt dim, d; 4503 PetscErrorCode ierr; 4504 4505 PetscFunctionBegin; 4506 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4507 PetscValidLogicalCollectiveBool(dm,per,2); 4508 if (maxCell) { 4509 PetscValidPointer(maxCell,3); 4510 PetscValidPointer(L,4); 4511 PetscValidPointer(bd,5); 4512 } 4513 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4514 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4515 if (maxCell) { 4516 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4517 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4518 dm->periodic = PETSC_TRUE; 4519 } else { 4520 dm->periodic = per; 4521 } 4522 PetscFunctionReturn(0); 4523 } 4524 4525 /*@ 4526 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. 4527 4528 Input Parameters: 4529 + dm - The DM 4530 . in - The input coordinate point (dim numbers) 4531 - endpoint - Include the endpoint L_i 4532 4533 Output Parameter: 4534 . out - The localized coordinate point 4535 4536 Level: developer 4537 4538 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4539 @*/ 4540 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 4541 { 4542 PetscInt dim, d; 4543 PetscErrorCode ierr; 4544 4545 PetscFunctionBegin; 4546 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 4547 if (!dm->maxCell) { 4548 for (d = 0; d < dim; ++d) out[d] = in[d]; 4549 } else { 4550 if (endpoint) { 4551 for (d = 0; d < dim; ++d) { 4552 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)) { 4553 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 4554 } else { 4555 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 4556 } 4557 } 4558 } else { 4559 for (d = 0; d < dim; ++d) { 4560 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 4561 } 4562 } 4563 } 4564 PetscFunctionReturn(0); 4565 } 4566 4567 /* 4568 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. 4569 4570 Input Parameters: 4571 + dm - The DM 4572 . dim - The spatial dimension 4573 . anchor - The anchor point, the input point can be no more than maxCell away from it 4574 - in - The input coordinate point (dim numbers) 4575 4576 Output Parameter: 4577 . out - The localized coordinate point 4578 4579 Level: developer 4580 4581 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 4582 4583 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4584 */ 4585 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4586 { 4587 PetscInt d; 4588 4589 PetscFunctionBegin; 4590 if (!dm->maxCell) { 4591 for (d = 0; d < dim; ++d) out[d] = in[d]; 4592 } else { 4593 for (d = 0; d < dim; ++d) { 4594 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 4595 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4596 } else { 4597 out[d] = in[d]; 4598 } 4599 } 4600 } 4601 PetscFunctionReturn(0); 4602 } 4603 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 4604 { 4605 PetscInt d; 4606 4607 PetscFunctionBegin; 4608 if (!dm->maxCell) { 4609 for (d = 0; d < dim; ++d) out[d] = in[d]; 4610 } else { 4611 for (d = 0; d < dim; ++d) { 4612 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 4613 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4614 } else { 4615 out[d] = in[d]; 4616 } 4617 } 4618 } 4619 PetscFunctionReturn(0); 4620 } 4621 4622 /* 4623 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. 4624 4625 Input Parameters: 4626 + dm - The DM 4627 . dim - The spatial dimension 4628 . anchor - The anchor point, the input point can be no more than maxCell away from it 4629 . in - The input coordinate delta (dim numbers) 4630 - out - The input coordinate point (dim numbers) 4631 4632 Output Parameter: 4633 . out - The localized coordinate in + out 4634 4635 Level: developer 4636 4637 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 4638 4639 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 4640 */ 4641 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4642 { 4643 PetscInt d; 4644 4645 PetscFunctionBegin; 4646 if (!dm->maxCell) { 4647 for (d = 0; d < dim; ++d) out[d] += in[d]; 4648 } else { 4649 for (d = 0; d < dim; ++d) { 4650 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 4651 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4652 } else { 4653 out[d] += in[d]; 4654 } 4655 } 4656 } 4657 PetscFunctionReturn(0); 4658 } 4659 4660 /*@ 4661 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 4662 4663 Input Parameter: 4664 . dm - The DM 4665 4666 Output Parameter: 4667 areLocalized - True if localized 4668 4669 Level: developer 4670 4671 .seealso: DMLocalizeCoordinates() 4672 @*/ 4673 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 4674 { 4675 DM cdm; 4676 PetscSection coordSection; 4677 PetscInt cStart, cEnd, c, sStart, sEnd, dof; 4678 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4679 PetscErrorCode ierr; 4680 4681 PetscFunctionBegin; 4682 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4683 if (!dm->periodic) { 4684 *areLocalized = PETSC_FALSE; 4685 PetscFunctionReturn(0); 4686 } 4687 /* We need some generic way of refering to cells/vertices */ 4688 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4689 { 4690 PetscBool isplex; 4691 4692 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4693 if (isplex) { 4694 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4695 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4696 } 4697 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4698 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4699 alreadyLocalized = alreadyLocalizedGlobal = PETSC_FALSE; 4700 for (c = cStart; c < cEnd; ++c) { 4701 if (c < sStart || c >= sEnd) { 4702 alreadyLocalized = PETSC_FALSE; 4703 break; 4704 } 4705 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 4706 if (dof) { 4707 alreadyLocalized = PETSC_TRUE; 4708 break; 4709 } 4710 } 4711 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4712 *areLocalized = alreadyLocalizedGlobal; 4713 PetscFunctionReturn(0); 4714 } 4715 4716 4717 /*@ 4718 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 4719 4720 Input Parameter: 4721 . dm - The DM 4722 4723 Level: developer 4724 4725 .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 4726 @*/ 4727 PetscErrorCode DMLocalizeCoordinates(DM dm) 4728 { 4729 DM cdm; 4730 PetscSection coordSection, cSection; 4731 Vec coordinates, cVec; 4732 PetscScalar *coords, *coords2, *anchor, *localized; 4733 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 4734 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4735 PetscInt maxHeight = 0, h; 4736 PetscInt *pStart = NULL, *pEnd = NULL; 4737 PetscErrorCode ierr; 4738 4739 PetscFunctionBegin; 4740 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4741 if (!dm->periodic) PetscFunctionReturn(0); 4742 /* We need some generic way of refering to cells/vertices */ 4743 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4744 { 4745 PetscBool isplex; 4746 4747 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4748 if (isplex) { 4749 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4750 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 4751 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4752 pEnd = &pStart[maxHeight + 1]; 4753 newStart = vStart; 4754 newEnd = vEnd; 4755 for (h = 0; h <= maxHeight; h++) { 4756 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 4757 newStart = PetscMin(newStart,pStart[h]); 4758 newEnd = PetscMax(newEnd,pEnd[h]); 4759 } 4760 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4761 } 4762 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4763 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4764 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 4765 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4766 4767 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 4768 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 4769 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 4770 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 4771 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 4772 4773 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 4774 localized = &anchor[bs]; 4775 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 4776 for (h = 0; h <= maxHeight; h++) { 4777 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 4778 4779 for (c = cStart; c < cEnd; ++c) { 4780 PetscScalar *cellCoords = NULL; 4781 PetscInt b; 4782 4783 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 4784 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4785 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4786 for (d = 0; d < dof/bs; ++d) { 4787 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 4788 for (b = 0; b < bs; b++) { 4789 if (cellCoords[d*bs + b] != localized[b]) break; 4790 } 4791 if (b < bs) break; 4792 } 4793 if (d < dof/bs) { 4794 if (c >= sStart && c < sEnd) { 4795 PetscInt cdof; 4796 4797 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 4798 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 4799 } 4800 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 4801 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 4802 } 4803 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4804 } 4805 } 4806 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4807 if (alreadyLocalizedGlobal) { 4808 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 4809 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4810 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4811 PetscFunctionReturn(0); 4812 } 4813 for (v = vStart; v < vEnd; ++v) { 4814 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4815 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 4816 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 4817 } 4818 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 4819 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 4820 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 4821 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 4822 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 4823 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4824 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 4825 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 4826 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 4827 for (v = vStart; v < vEnd; ++v) { 4828 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4829 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4830 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 4831 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 4832 } 4833 for (h = 0; h <= maxHeight; h++) { 4834 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 4835 4836 for (c = cStart; c < cEnd; ++c) { 4837 PetscScalar *cellCoords = NULL; 4838 PetscInt b, cdof; 4839 4840 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 4841 if (!cdof) continue; 4842 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4843 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 4844 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4845 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 4846 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4847 } 4848 } 4849 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 4850 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4851 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 4852 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 4853 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 4854 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 4855 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 4856 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4857 PetscFunctionReturn(0); 4858 } 4859 4860 /*@ 4861 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 4862 4863 Collective on Vec v (see explanation below) 4864 4865 Input Parameters: 4866 + dm - The DM 4867 . v - The Vec of points 4868 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 4869 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 4870 4871 Output Parameter: 4872 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 4873 - cells - The PetscSF containing the ranks and local indices of the containing points. 4874 4875 4876 Level: developer 4877 4878 Notes: 4879 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 4880 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 4881 4882 If *cellSF is NULL on input, a PetscSF will be created. 4883 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 4884 4885 An array that maps each point to its containing cell can be obtained with 4886 4887 $ const PetscSFNode *cells; 4888 $ PetscInt nFound; 4889 $ const PetscSFNode *found; 4890 $ 4891 $ PetscSFGetGraph(cells,NULL,&nFound,&found,&cells); 4892 4893 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 4894 the index of the cell in its rank's local numbering. 4895 4896 .keywords: point location, mesh 4897 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 4898 @*/ 4899 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 4900 { 4901 PetscErrorCode ierr; 4902 4903 PetscFunctionBegin; 4904 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4905 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4906 PetscValidPointer(cellSF,4); 4907 if (*cellSF) { 4908 PetscMPIInt result; 4909 4910 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 4911 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 4912 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 4913 } else { 4914 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 4915 } 4916 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4917 if (dm->ops->locatepoints) { 4918 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 4919 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4920 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4921 PetscFunctionReturn(0); 4922 } 4923 4924 /*@ 4925 DMGetOutputDM - Retrieve the DM associated with the layout for output 4926 4927 Input Parameter: 4928 . dm - The original DM 4929 4930 Output Parameter: 4931 . odm - The DM which provides the layout for output 4932 4933 Level: intermediate 4934 4935 .seealso: VecView(), DMGetDefaultGlobalSection() 4936 @*/ 4937 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4938 { 4939 PetscSection section; 4940 PetscBool hasConstraints, ghasConstraints; 4941 PetscErrorCode ierr; 4942 4943 PetscFunctionBegin; 4944 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4945 PetscValidPointer(odm,2); 4946 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4947 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4948 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 4949 if (!ghasConstraints) { 4950 *odm = dm; 4951 PetscFunctionReturn(0); 4952 } 4953 if (!dm->dmBC) { 4954 PetscDS ds; 4955 PetscSection newSection, gsection; 4956 PetscSF sf; 4957 4958 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4959 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 4960 ierr = DMSetDS(dm->dmBC, ds);CHKERRQ(ierr); 4961 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4962 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4963 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4964 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4965 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 4966 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4967 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4968 } 4969 *odm = dm->dmBC; 4970 PetscFunctionReturn(0); 4971 } 4972 4973 /*@ 4974 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 4975 4976 Input Parameter: 4977 . dm - The original DM 4978 4979 Output Parameters: 4980 + num - The output sequence number 4981 - val - The output sequence value 4982 4983 Level: intermediate 4984 4985 Note: This is intended for output that should appear in sequence, for instance 4986 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4987 4988 .seealso: VecView() 4989 @*/ 4990 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 4991 { 4992 PetscFunctionBegin; 4993 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4994 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 4995 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 4996 PetscFunctionReturn(0); 4997 } 4998 4999 /*@ 5000 DMSetOutputSequenceNumber - Set the sequence number/value for output 5001 5002 Input Parameters: 5003 + dm - The original DM 5004 . num - The output sequence number 5005 - val - The output sequence value 5006 5007 Level: intermediate 5008 5009 Note: This is intended for output that should appear in sequence, for instance 5010 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5011 5012 .seealso: VecView() 5013 @*/ 5014 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 5015 { 5016 PetscFunctionBegin; 5017 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5018 dm->outputSequenceNum = num; 5019 dm->outputSequenceVal = val; 5020 PetscFunctionReturn(0); 5021 } 5022 5023 /*@C 5024 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 5025 5026 Input Parameters: 5027 + dm - The original DM 5028 . name - The sequence name 5029 - num - The output sequence number 5030 5031 Output Parameter: 5032 . val - The output sequence value 5033 5034 Level: intermediate 5035 5036 Note: This is intended for output that should appear in sequence, for instance 5037 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5038 5039 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 5040 @*/ 5041 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 5042 { 5043 PetscBool ishdf5; 5044 PetscErrorCode ierr; 5045 5046 PetscFunctionBegin; 5047 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5048 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 5049 PetscValidPointer(val,4); 5050 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 5051 if (ishdf5) { 5052 #if defined(PETSC_HAVE_HDF5) 5053 PetscScalar value; 5054 5055 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 5056 *val = PetscRealPart(value); 5057 #endif 5058 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 5059 PetscFunctionReturn(0); 5060 } 5061 5062 /*@ 5063 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 5064 5065 Not collective 5066 5067 Input Parameter: 5068 . dm - The DM 5069 5070 Output Parameter: 5071 . useNatural - The flag to build the mapping to a natural order during distribution 5072 5073 Level: beginner 5074 5075 .seealso: DMSetUseNatural(), DMCreate() 5076 @*/ 5077 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 5078 { 5079 PetscFunctionBegin; 5080 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5081 PetscValidPointer(useNatural, 2); 5082 *useNatural = dm->useNatural; 5083 PetscFunctionReturn(0); 5084 } 5085 5086 /*@ 5087 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 5088 5089 Collective on dm 5090 5091 Input Parameters: 5092 + dm - The DM 5093 - useNatural - The flag to build the mapping to a natural order during distribution 5094 5095 Level: beginner 5096 5097 .seealso: DMGetUseNatural(), DMCreate() 5098 @*/ 5099 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 5100 { 5101 PetscFunctionBegin; 5102 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5103 PetscValidLogicalCollectiveInt(dm, useNatural, 2); 5104 dm->useNatural = useNatural; 5105 PetscFunctionReturn(0); 5106 } 5107 5108 5109 /*@C 5110 DMCreateLabel - Create a label of the given name if it does not already exist 5111 5112 Not Collective 5113 5114 Input Parameters: 5115 + dm - The DM object 5116 - name - The label name 5117 5118 Level: intermediate 5119 5120 .keywords: mesh 5121 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5122 @*/ 5123 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 5124 { 5125 DMLabelLink next = dm->labels->next; 5126 PetscBool flg = PETSC_FALSE; 5127 PetscErrorCode ierr; 5128 5129 PetscFunctionBegin; 5130 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5131 PetscValidCharPointer(name, 2); 5132 while (next) { 5133 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5134 if (flg) break; 5135 next = next->next; 5136 } 5137 if (!flg) { 5138 DMLabelLink tmpLabel; 5139 5140 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5141 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 5142 tmpLabel->output = PETSC_TRUE; 5143 tmpLabel->next = dm->labels->next; 5144 dm->labels->next = tmpLabel; 5145 } 5146 PetscFunctionReturn(0); 5147 } 5148 5149 /*@C 5150 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 5151 5152 Not Collective 5153 5154 Input Parameters: 5155 + dm - The DM object 5156 . name - The label name 5157 - point - The mesh point 5158 5159 Output Parameter: 5160 . value - The label value for this point, or -1 if the point is not in the label 5161 5162 Level: beginner 5163 5164 .keywords: mesh 5165 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 5166 @*/ 5167 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 5168 { 5169 DMLabel label; 5170 PetscErrorCode ierr; 5171 5172 PetscFunctionBegin; 5173 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5174 PetscValidCharPointer(name, 2); 5175 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5176 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 5177 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5178 PetscFunctionReturn(0); 5179 } 5180 5181 /*@C 5182 DMSetLabelValue - Add a point to a Sieve Label with given value 5183 5184 Not Collective 5185 5186 Input Parameters: 5187 + dm - The DM object 5188 . name - The label name 5189 . point - The mesh point 5190 - value - The label value for this point 5191 5192 Output Parameter: 5193 5194 Level: beginner 5195 5196 .keywords: mesh 5197 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5198 @*/ 5199 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5200 { 5201 DMLabel label; 5202 PetscErrorCode ierr; 5203 5204 PetscFunctionBegin; 5205 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5206 PetscValidCharPointer(name, 2); 5207 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5208 if (!label) { 5209 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5210 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5211 } 5212 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5213 PetscFunctionReturn(0); 5214 } 5215 5216 /*@C 5217 DMClearLabelValue - Remove a point from a Sieve Label with given value 5218 5219 Not Collective 5220 5221 Input Parameters: 5222 + dm - The DM object 5223 . name - The label name 5224 . point - The mesh point 5225 - value - The label value for this point 5226 5227 Output Parameter: 5228 5229 Level: beginner 5230 5231 .keywords: mesh 5232 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5233 @*/ 5234 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5235 { 5236 DMLabel label; 5237 PetscErrorCode ierr; 5238 5239 PetscFunctionBegin; 5240 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5241 PetscValidCharPointer(name, 2); 5242 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5243 if (!label) PetscFunctionReturn(0); 5244 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5245 PetscFunctionReturn(0); 5246 } 5247 5248 /*@C 5249 DMGetLabelSize - Get the number of different integer ids in a Label 5250 5251 Not Collective 5252 5253 Input Parameters: 5254 + dm - The DM object 5255 - name - The label name 5256 5257 Output Parameter: 5258 . size - The number of different integer ids, or 0 if the label does not exist 5259 5260 Level: beginner 5261 5262 .keywords: mesh 5263 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 5264 @*/ 5265 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5266 { 5267 DMLabel label; 5268 PetscErrorCode ierr; 5269 5270 PetscFunctionBegin; 5271 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5272 PetscValidCharPointer(name, 2); 5273 PetscValidPointer(size, 3); 5274 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5275 *size = 0; 5276 if (!label) PetscFunctionReturn(0); 5277 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5278 PetscFunctionReturn(0); 5279 } 5280 5281 /*@C 5282 DMGetLabelIdIS - Get the integer ids in a label 5283 5284 Not Collective 5285 5286 Input Parameters: 5287 + mesh - The DM object 5288 - name - The label name 5289 5290 Output Parameter: 5291 . ids - The integer ids, or NULL if the label does not exist 5292 5293 Level: beginner 5294 5295 .keywords: mesh 5296 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5297 @*/ 5298 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5299 { 5300 DMLabel label; 5301 PetscErrorCode ierr; 5302 5303 PetscFunctionBegin; 5304 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5305 PetscValidCharPointer(name, 2); 5306 PetscValidPointer(ids, 3); 5307 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5308 *ids = NULL; 5309 if (!label) PetscFunctionReturn(0); 5310 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5311 PetscFunctionReturn(0); 5312 } 5313 5314 /*@C 5315 DMGetStratumSize - Get the number of points in a label stratum 5316 5317 Not Collective 5318 5319 Input Parameters: 5320 + dm - The DM object 5321 . name - The label name 5322 - value - The stratum value 5323 5324 Output Parameter: 5325 . size - The stratum size 5326 5327 Level: beginner 5328 5329 .keywords: mesh 5330 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5331 @*/ 5332 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5333 { 5334 DMLabel label; 5335 PetscErrorCode ierr; 5336 5337 PetscFunctionBegin; 5338 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5339 PetscValidCharPointer(name, 2); 5340 PetscValidPointer(size, 4); 5341 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5342 *size = 0; 5343 if (!label) PetscFunctionReturn(0); 5344 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5345 PetscFunctionReturn(0); 5346 } 5347 5348 /*@C 5349 DMGetStratumIS - Get the points in a label stratum 5350 5351 Not Collective 5352 5353 Input Parameters: 5354 + dm - The DM object 5355 . name - The label name 5356 - value - The stratum value 5357 5358 Output Parameter: 5359 . points - The stratum points, or NULL if the label does not exist or does not have that value 5360 5361 Level: beginner 5362 5363 .keywords: mesh 5364 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5365 @*/ 5366 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5367 { 5368 DMLabel label; 5369 PetscErrorCode ierr; 5370 5371 PetscFunctionBegin; 5372 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5373 PetscValidCharPointer(name, 2); 5374 PetscValidPointer(points, 4); 5375 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5376 *points = NULL; 5377 if (!label) PetscFunctionReturn(0); 5378 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5379 PetscFunctionReturn(0); 5380 } 5381 5382 /*@C 5383 DMGetStratumIS - Set the points in a label stratum 5384 5385 Not Collective 5386 5387 Input Parameters: 5388 + dm - The DM object 5389 . name - The label name 5390 . value - The stratum value 5391 - points - The stratum points 5392 5393 Level: beginner 5394 5395 .keywords: mesh 5396 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 5397 @*/ 5398 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 5399 { 5400 DMLabel label; 5401 PetscErrorCode ierr; 5402 5403 PetscFunctionBegin; 5404 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5405 PetscValidCharPointer(name, 2); 5406 PetscValidPointer(points, 4); 5407 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5408 if (!label) PetscFunctionReturn(0); 5409 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 5410 PetscFunctionReturn(0); 5411 } 5412 5413 /*@C 5414 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 5415 5416 Not Collective 5417 5418 Input Parameters: 5419 + dm - The DM object 5420 . name - The label name 5421 - value - The label value for this point 5422 5423 Output Parameter: 5424 5425 Level: beginner 5426 5427 .keywords: mesh 5428 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 5429 @*/ 5430 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 5431 { 5432 DMLabel label; 5433 PetscErrorCode ierr; 5434 5435 PetscFunctionBegin; 5436 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5437 PetscValidCharPointer(name, 2); 5438 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5439 if (!label) PetscFunctionReturn(0); 5440 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 5441 PetscFunctionReturn(0); 5442 } 5443 5444 /*@ 5445 DMGetNumLabels - Return the number of labels defined by the mesh 5446 5447 Not Collective 5448 5449 Input Parameter: 5450 . dm - The DM object 5451 5452 Output Parameter: 5453 . numLabels - the number of Labels 5454 5455 Level: intermediate 5456 5457 .keywords: mesh 5458 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5459 @*/ 5460 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 5461 { 5462 DMLabelLink next = dm->labels->next; 5463 PetscInt n = 0; 5464 5465 PetscFunctionBegin; 5466 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5467 PetscValidPointer(numLabels, 2); 5468 while (next) {++n; next = next->next;} 5469 *numLabels = n; 5470 PetscFunctionReturn(0); 5471 } 5472 5473 /*@C 5474 DMGetLabelName - Return the name of nth label 5475 5476 Not Collective 5477 5478 Input Parameters: 5479 + dm - The DM object 5480 - n - the label number 5481 5482 Output Parameter: 5483 . name - the label name 5484 5485 Level: intermediate 5486 5487 .keywords: mesh 5488 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5489 @*/ 5490 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 5491 { 5492 DMLabelLink next = dm->labels->next; 5493 PetscInt l = 0; 5494 5495 PetscFunctionBegin; 5496 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5497 PetscValidPointer(name, 3); 5498 while (next) { 5499 if (l == n) { 5500 *name = next->label->name; 5501 PetscFunctionReturn(0); 5502 } 5503 ++l; 5504 next = next->next; 5505 } 5506 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5507 } 5508 5509 /*@C 5510 DMHasLabel - Determine whether the mesh has a label of a given name 5511 5512 Not Collective 5513 5514 Input Parameters: 5515 + dm - The DM object 5516 - name - The label name 5517 5518 Output Parameter: 5519 . hasLabel - PETSC_TRUE if the label is present 5520 5521 Level: intermediate 5522 5523 .keywords: mesh 5524 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5525 @*/ 5526 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 5527 { 5528 DMLabelLink next = dm->labels->next; 5529 PetscErrorCode ierr; 5530 5531 PetscFunctionBegin; 5532 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5533 PetscValidCharPointer(name, 2); 5534 PetscValidPointer(hasLabel, 3); 5535 *hasLabel = PETSC_FALSE; 5536 while (next) { 5537 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 5538 if (*hasLabel) break; 5539 next = next->next; 5540 } 5541 PetscFunctionReturn(0); 5542 } 5543 5544 /*@C 5545 DMGetLabel - Return the label of a given name, or NULL 5546 5547 Not Collective 5548 5549 Input Parameters: 5550 + dm - The DM object 5551 - name - The label name 5552 5553 Output Parameter: 5554 . label - The DMLabel, or NULL if the label is absent 5555 5556 Level: intermediate 5557 5558 .keywords: mesh 5559 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5560 @*/ 5561 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 5562 { 5563 DMLabelLink next = dm->labels->next; 5564 PetscBool hasLabel; 5565 PetscErrorCode ierr; 5566 5567 PetscFunctionBegin; 5568 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5569 PetscValidCharPointer(name, 2); 5570 PetscValidPointer(label, 3); 5571 *label = NULL; 5572 while (next) { 5573 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5574 if (hasLabel) { 5575 *label = next->label; 5576 break; 5577 } 5578 next = next->next; 5579 } 5580 PetscFunctionReturn(0); 5581 } 5582 5583 /*@C 5584 DMGetLabelByNum - Return the nth label 5585 5586 Not Collective 5587 5588 Input Parameters: 5589 + dm - The DM object 5590 - n - the label number 5591 5592 Output Parameter: 5593 . label - the label 5594 5595 Level: intermediate 5596 5597 .keywords: mesh 5598 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5599 @*/ 5600 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5601 { 5602 DMLabelLink next = dm->labels->next; 5603 PetscInt l = 0; 5604 5605 PetscFunctionBegin; 5606 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5607 PetscValidPointer(label, 3); 5608 while (next) { 5609 if (l == n) { 5610 *label = next->label; 5611 PetscFunctionReturn(0); 5612 } 5613 ++l; 5614 next = next->next; 5615 } 5616 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5617 } 5618 5619 /*@C 5620 DMAddLabel - Add the label to this mesh 5621 5622 Not Collective 5623 5624 Input Parameters: 5625 + dm - The DM object 5626 - label - The DMLabel 5627 5628 Level: developer 5629 5630 .keywords: mesh 5631 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5632 @*/ 5633 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5634 { 5635 DMLabelLink tmpLabel; 5636 PetscBool hasLabel; 5637 PetscErrorCode ierr; 5638 5639 PetscFunctionBegin; 5640 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5641 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5642 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5643 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5644 tmpLabel->label = label; 5645 tmpLabel->output = PETSC_TRUE; 5646 tmpLabel->next = dm->labels->next; 5647 dm->labels->next = tmpLabel; 5648 PetscFunctionReturn(0); 5649 } 5650 5651 /*@C 5652 DMRemoveLabel - Remove the label from this mesh 5653 5654 Not Collective 5655 5656 Input Parameters: 5657 + dm - The DM object 5658 - name - The label name 5659 5660 Output Parameter: 5661 . label - The DMLabel, or NULL if the label is absent 5662 5663 Level: developer 5664 5665 .keywords: mesh 5666 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5667 @*/ 5668 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5669 { 5670 DMLabelLink next = dm->labels->next; 5671 DMLabelLink last = NULL; 5672 PetscBool hasLabel; 5673 PetscErrorCode ierr; 5674 5675 PetscFunctionBegin; 5676 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5677 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5678 *label = NULL; 5679 if (!hasLabel) PetscFunctionReturn(0); 5680 while (next) { 5681 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5682 if (hasLabel) { 5683 if (last) last->next = next->next; 5684 else dm->labels->next = next->next; 5685 next->next = NULL; 5686 *label = next->label; 5687 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5688 if (hasLabel) { 5689 dm->depthLabel = NULL; 5690 } 5691 ierr = PetscFree(next);CHKERRQ(ierr); 5692 break; 5693 } 5694 last = next; 5695 next = next->next; 5696 } 5697 PetscFunctionReturn(0); 5698 } 5699 5700 /*@C 5701 DMGetLabelOutput - Get the output flag for a given label 5702 5703 Not Collective 5704 5705 Input Parameters: 5706 + dm - The DM object 5707 - name - The label name 5708 5709 Output Parameter: 5710 . output - The flag for output 5711 5712 Level: developer 5713 5714 .keywords: mesh 5715 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5716 @*/ 5717 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5718 { 5719 DMLabelLink next = dm->labels->next; 5720 PetscErrorCode ierr; 5721 5722 PetscFunctionBegin; 5723 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5724 PetscValidPointer(name, 2); 5725 PetscValidPointer(output, 3); 5726 while (next) { 5727 PetscBool flg; 5728 5729 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5730 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5731 next = next->next; 5732 } 5733 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5734 } 5735 5736 /*@C 5737 DMSetLabelOutput - Set the output flag for a given label 5738 5739 Not Collective 5740 5741 Input Parameters: 5742 + dm - The DM object 5743 . name - The label name 5744 - output - The flag for output 5745 5746 Level: developer 5747 5748 .keywords: mesh 5749 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5750 @*/ 5751 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 5752 { 5753 DMLabelLink next = dm->labels->next; 5754 PetscErrorCode ierr; 5755 5756 PetscFunctionBegin; 5757 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5758 PetscValidPointer(name, 2); 5759 while (next) { 5760 PetscBool flg; 5761 5762 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5763 if (flg) {next->output = output; PetscFunctionReturn(0);} 5764 next = next->next; 5765 } 5766 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5767 } 5768 5769 5770 /*@ 5771 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 5772 5773 Collective on DM 5774 5775 Input Parameter: 5776 . dmA - The DM object with initial labels 5777 5778 Output Parameter: 5779 . dmB - The DM object with copied labels 5780 5781 Level: intermediate 5782 5783 Note: This is typically used when interpolating or otherwise adding to a mesh 5784 5785 .keywords: mesh 5786 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 5787 @*/ 5788 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 5789 { 5790 PetscInt numLabels, l; 5791 PetscErrorCode ierr; 5792 5793 PetscFunctionBegin; 5794 if (dmA == dmB) PetscFunctionReturn(0); 5795 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 5796 for (l = 0; l < numLabels; ++l) { 5797 DMLabel label, labelNew; 5798 const char *name; 5799 PetscBool flg; 5800 5801 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 5802 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 5803 if (flg) continue; 5804 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 5805 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 5806 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 5807 } 5808 PetscFunctionReturn(0); 5809 } 5810 5811 /*@ 5812 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5813 5814 Input Parameter: 5815 . dm - The DM object 5816 5817 Output Parameter: 5818 . cdm - The coarse DM 5819 5820 Level: intermediate 5821 5822 .seealso: DMSetCoarseDM() 5823 @*/ 5824 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 5825 { 5826 PetscFunctionBegin; 5827 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5828 PetscValidPointer(cdm, 2); 5829 *cdm = dm->coarseMesh; 5830 PetscFunctionReturn(0); 5831 } 5832 5833 /*@ 5834 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5835 5836 Input Parameters: 5837 + dm - The DM object 5838 - cdm - The coarse DM 5839 5840 Level: intermediate 5841 5842 .seealso: DMGetCoarseDM() 5843 @*/ 5844 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 5845 { 5846 PetscErrorCode ierr; 5847 5848 PetscFunctionBegin; 5849 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5850 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5851 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5852 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 5853 dm->coarseMesh = cdm; 5854 PetscFunctionReturn(0); 5855 } 5856 5857 /*@ 5858 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 5859 5860 Input Parameter: 5861 . dm - The DM object 5862 5863 Output Parameter: 5864 . fdm - The fine DM 5865 5866 Level: intermediate 5867 5868 .seealso: DMSetFineDM() 5869 @*/ 5870 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 5871 { 5872 PetscFunctionBegin; 5873 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5874 PetscValidPointer(fdm, 2); 5875 *fdm = dm->fineMesh; 5876 PetscFunctionReturn(0); 5877 } 5878 5879 /*@ 5880 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 5881 5882 Input Parameters: 5883 + dm - The DM object 5884 - fdm - The fine DM 5885 5886 Level: intermediate 5887 5888 .seealso: DMGetFineDM() 5889 @*/ 5890 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 5891 { 5892 PetscErrorCode ierr; 5893 5894 PetscFunctionBegin; 5895 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5896 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 5897 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 5898 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 5899 dm->fineMesh = fdm; 5900 PetscFunctionReturn(0); 5901 } 5902 5903 /*=== DMBoundary code ===*/ 5904 5905 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 5906 { 5907 PetscErrorCode ierr; 5908 5909 PetscFunctionBegin; 5910 ierr = PetscDSCopyBoundary(dm->prob,dmNew->prob);CHKERRQ(ierr); 5911 PetscFunctionReturn(0); 5912 } 5913 5914 /*@C 5915 DMAddBoundary - Add a boundary condition to the model 5916 5917 Input Parameters: 5918 + dm - The DM, with a PetscDS that matches the problem being constrained 5919 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 5920 . name - The BC name 5921 . labelname - The label defining constrained points 5922 . field - The field to constrain 5923 . numcomps - The number of constrained field components 5924 . comps - An array of constrained component numbers 5925 . bcFunc - A pointwise function giving boundary values 5926 . numids - The number of DMLabel ids for constrained points 5927 . ids - An array of ids for constrained points 5928 - ctx - An optional user context for bcFunc 5929 5930 Options Database Keys: 5931 + -bc_<boundary name> <num> - Overrides the boundary ids 5932 - -bc_<boundary name>_comp <num> - Overrides the boundary components 5933 5934 Level: developer 5935 5936 .seealso: DMGetBoundary() 5937 @*/ 5938 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) 5939 { 5940 PetscErrorCode ierr; 5941 5942 PetscFunctionBegin; 5943 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5944 ierr = PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);CHKERRQ(ierr); 5945 PetscFunctionReturn(0); 5946 } 5947 5948 /*@ 5949 DMGetNumBoundary - Get the number of registered BC 5950 5951 Input Parameters: 5952 . dm - The mesh object 5953 5954 Output Parameters: 5955 . numBd - The number of BC 5956 5957 Level: intermediate 5958 5959 .seealso: DMAddBoundary(), DMGetBoundary() 5960 @*/ 5961 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 5962 { 5963 PetscErrorCode ierr; 5964 5965 PetscFunctionBegin; 5966 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5967 ierr = PetscDSGetNumBoundary(dm->prob,numBd);CHKERRQ(ierr); 5968 PetscFunctionReturn(0); 5969 } 5970 5971 /*@C 5972 DMGetBoundary - Get a model boundary condition 5973 5974 Input Parameters: 5975 + dm - The mesh object 5976 - bd - The BC number 5977 5978 Output Parameters: 5979 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 5980 . name - The BC name 5981 . labelname - The label defining constrained points 5982 . field - The field to constrain 5983 . numcomps - The number of constrained field components 5984 . comps - An array of constrained component numbers 5985 . bcFunc - A pointwise function giving boundary values 5986 . numids - The number of DMLabel ids for constrained points 5987 . ids - An array of ids for constrained points 5988 - ctx - An optional user context for bcFunc 5989 5990 Options Database Keys: 5991 + -bc_<boundary name> <num> - Overrides the boundary ids 5992 - -bc_<boundary name>_comp <num> - Overrides the boundary components 5993 5994 Level: developer 5995 5996 .seealso: DMAddBoundary() 5997 @*/ 5998 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) 5999 { 6000 PetscErrorCode ierr; 6001 6002 PetscFunctionBegin; 6003 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6004 ierr = PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);CHKERRQ(ierr); 6005 PetscFunctionReturn(0); 6006 } 6007 6008 static PetscErrorCode DMPopulateBoundary(DM dm) 6009 { 6010 DMBoundary *lastnext; 6011 DSBoundary dsbound; 6012 PetscErrorCode ierr; 6013 6014 PetscFunctionBegin; 6015 dsbound = dm->prob->boundary; 6016 if (dm->boundary) { 6017 DMBoundary next = dm->boundary; 6018 6019 /* quick check to see if the PetscDS has changed */ 6020 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 6021 /* the PetscDS has changed: tear down and rebuild */ 6022 while (next) { 6023 DMBoundary b = next; 6024 6025 next = b->next; 6026 ierr = PetscFree(b);CHKERRQ(ierr); 6027 } 6028 dm->boundary = NULL; 6029 } 6030 6031 lastnext = &(dm->boundary); 6032 while (dsbound) { 6033 DMBoundary dmbound; 6034 6035 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 6036 dmbound->dsboundary = dsbound; 6037 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 6038 if (!dmbound->label) PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr); 6039 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 6040 *lastnext = dmbound; 6041 lastnext = &(dmbound->next); 6042 dsbound = dsbound->next; 6043 } 6044 PetscFunctionReturn(0); 6045 } 6046 6047 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 6048 { 6049 DMBoundary b; 6050 PetscErrorCode ierr; 6051 6052 PetscFunctionBegin; 6053 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6054 PetscValidPointer(isBd, 3); 6055 *isBd = PETSC_FALSE; 6056 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 6057 b = dm->boundary; 6058 while (b && !(*isBd)) { 6059 DMLabel label = b->label; 6060 DSBoundary dsb = b->dsboundary; 6061 6062 if (label) { 6063 PetscInt i; 6064 6065 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 6066 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 6067 } 6068 } 6069 b = b->next; 6070 } 6071 PetscFunctionReturn(0); 6072 } 6073 6074 /*@C 6075 DMProjectFunction - This projects the given function into the function space provided. 6076 6077 Input Parameters: 6078 + dm - The DM 6079 . time - The time 6080 . funcs - The coordinate functions to evaluate, one per field 6081 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6082 - mode - The insertion mode for values 6083 6084 Output Parameter: 6085 . X - vector 6086 6087 Calling sequence of func: 6088 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6089 6090 + dim - The spatial dimension 6091 . x - The coordinates 6092 . Nf - The number of fields 6093 . u - The output field values 6094 - ctx - optional user-defined function context 6095 6096 Level: developer 6097 6098 .seealso: DMComputeL2Diff() 6099 @*/ 6100 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6101 { 6102 Vec localX; 6103 PetscErrorCode ierr; 6104 6105 PetscFunctionBegin; 6106 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6107 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6108 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6109 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6110 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6111 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6112 PetscFunctionReturn(0); 6113 } 6114 6115 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, 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->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6123 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6124 PetscFunctionReturn(0); 6125 } 6126 6127 PetscErrorCode DMProjectFunctionLabel(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6128 { 6129 Vec localX; 6130 PetscErrorCode ierr; 6131 6132 PetscFunctionBegin; 6133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6134 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6135 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6136 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6137 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6138 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6139 PetscFunctionReturn(0); 6140 } 6141 6142 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) 6143 { 6144 PetscErrorCode ierr; 6145 6146 PetscFunctionBegin; 6147 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6148 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6149 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6150 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6151 PetscFunctionReturn(0); 6152 } 6153 6154 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 6155 void (**funcs)(PetscInt, PetscInt, PetscInt, 6156 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6157 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6158 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6159 InsertMode mode, Vec localX) 6160 { 6161 PetscErrorCode ierr; 6162 6163 PetscFunctionBegin; 6164 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6165 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 6166 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 6167 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6168 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 6169 PetscFunctionReturn(0); 6170 } 6171 6172 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 6173 void (**funcs)(PetscInt, PetscInt, PetscInt, 6174 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6175 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6176 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6177 InsertMode mode, Vec localX) 6178 { 6179 PetscErrorCode ierr; 6180 6181 PetscFunctionBegin; 6182 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6183 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 6184 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 6185 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6186 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 6187 PetscFunctionReturn(0); 6188 } 6189 6190 /*@C 6191 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6192 6193 Input Parameters: 6194 + dm - The DM 6195 . time - The time 6196 . funcs - The functions to evaluate for each field component 6197 . ctxs - Optional array of contexts to pass to each function, or NULL. 6198 - X - The coefficient vector u_h, a global vector 6199 6200 Output Parameter: 6201 . diff - The diff ||u - u_h||_2 6202 6203 Level: developer 6204 6205 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6206 @*/ 6207 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6208 { 6209 PetscErrorCode ierr; 6210 6211 PetscFunctionBegin; 6212 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6213 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6214 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 6215 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6216 PetscFunctionReturn(0); 6217 } 6218 6219 /*@C 6220 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6221 6222 Input Parameters: 6223 + dm - The DM 6224 , time - The time 6225 . funcs - The gradient functions to evaluate for each field component 6226 . ctxs - Optional array of contexts to pass to each function, or NULL. 6227 . X - The coefficient vector u_h, a global vector 6228 - n - The vector to project along 6229 6230 Output Parameter: 6231 . diff - The diff ||(grad u - grad u_h) . n||_2 6232 6233 Level: developer 6234 6235 .seealso: DMProjectFunction(), DMComputeL2Diff() 6236 @*/ 6237 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) 6238 { 6239 PetscErrorCode ierr; 6240 6241 PetscFunctionBegin; 6242 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6243 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6244 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6245 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6246 PetscFunctionReturn(0); 6247 } 6248 6249 /*@C 6250 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 6251 6252 Input Parameters: 6253 + dm - The DM 6254 . time - The time 6255 . funcs - The functions to evaluate for each field component 6256 . ctxs - Optional array of contexts to pass to each function, or NULL. 6257 - X - The coefficient vector u_h, a global vector 6258 6259 Output Parameter: 6260 . diff - The array of differences, ||u^f - u^f_h||_2 6261 6262 Level: developer 6263 6264 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6265 @*/ 6266 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 6267 { 6268 PetscErrorCode ierr; 6269 6270 PetscFunctionBegin; 6271 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6272 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6273 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6274 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6275 PetscFunctionReturn(0); 6276 } 6277 6278 /*@C 6279 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 6280 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 6281 6282 Collective on dm 6283 6284 Input parameters: 6285 + dm - the pre-adaptation DM object 6286 - label - label with the flags 6287 6288 Output parameters: 6289 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 6290 6291 Level: intermediate 6292 6293 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 6294 @*/ 6295 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 6296 { 6297 PetscErrorCode ierr; 6298 6299 PetscFunctionBegin; 6300 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6301 PetscValidPointer(label,2); 6302 PetscValidPointer(dmAdapt,3); 6303 *dmAdapt = NULL; 6304 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 6305 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 6306 PetscFunctionReturn(0); 6307 } 6308 6309 /*@C 6310 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 6311 6312 Input Parameters: 6313 + dm - The DM object 6314 . metric - The metric to which the mesh is adapted, defined vertex-wise. 6315 - 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_". 6316 6317 Output Parameter: 6318 . dmAdapt - Pointer to the DM object containing the adapted mesh 6319 6320 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 6321 6322 Level: advanced 6323 6324 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 6325 @*/ 6326 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 6327 { 6328 PetscErrorCode ierr; 6329 6330 PetscFunctionBegin; 6331 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6332 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 6333 if (bdLabel) PetscValidPointer(bdLabel, 3); 6334 PetscValidPointer(dmAdapt, 4); 6335 *dmAdapt = NULL; 6336 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 6337 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 6338 PetscFunctionReturn(0); 6339 } 6340 6341 /*@C 6342 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 6343 6344 Not Collective 6345 6346 Input Parameter: 6347 . dm - The DM 6348 6349 Output Parameter: 6350 . nranks - the number of neighbours 6351 . ranks - the neighbors ranks 6352 6353 Notes: 6354 Do not free the array, it is freed when the DM is destroyed. 6355 6356 Level: beginner 6357 6358 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 6359 @*/ 6360 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 6361 { 6362 PetscErrorCode ierr; 6363 6364 PetscFunctionBegin; 6365 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6366 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 6367 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 6368 PetscFunctionReturn(0); 6369 } 6370 6371 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 6372 6373 /* 6374 Converts the input vector to a ghosted vector and then calls the standard coloring code. 6375 This has be a different function because it requires DM which is not defined in the Mat library 6376 */ 6377 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 6378 { 6379 PetscErrorCode ierr; 6380 6381 PetscFunctionBegin; 6382 if (coloring->ctype == IS_COLORING_LOCAL) { 6383 Vec x1local; 6384 DM dm; 6385 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6386 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 6387 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 6388 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6389 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6390 x1 = x1local; 6391 } 6392 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 6393 if (coloring->ctype == IS_COLORING_LOCAL) { 6394 DM dm; 6395 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6396 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 6397 } 6398 PetscFunctionReturn(0); 6399 } 6400 6401 /*@ 6402 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 6403 6404 Input Parameter: 6405 . coloring - the MatFDColoring object 6406 6407 Developer Notes: this routine exists because the PETSc Mat library does not know about the DM objects 6408 6409 Level: advanced 6410 6411 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 6412 @*/ 6413 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 6414 { 6415 PetscFunctionBegin; 6416 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 6417 PetscFunctionReturn(0); 6418 } 6419