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