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