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