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