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