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