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