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