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