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