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