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