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