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