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