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