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