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