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