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