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