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