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 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 if (superdm) 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) { 1664 ierr = (*dms[0]->ops->createsuperdm)(dms, len, is, superdm);CHKERRQ(ierr); 1665 } else SETERRQ(PetscObjectComm((PetscObject) dms[0]), PETSC_ERR_SUP, "This type has no DMCreateSuperDM implementation defined"); 1666 } 1667 PetscFunctionReturn(0); 1668 } 1669 1670 1671 /*@C 1672 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems 1673 corresponding to restrictions to pairs nested subdomains: each IS contains the global 1674 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually 1675 define a nonoverlapping covering, while outer subdomains can overlap. 1676 The optional list of DMs define the DM for each subproblem. 1677 1678 Not collective 1679 1680 Input Parameter: 1681 . dm - the DM object 1682 1683 Output Parameters: 1684 + len - The number of subproblems in the domain decomposition (or NULL if not requested) 1685 . namelist - The name for each subdomain (or NULL if not requested) 1686 . innerislist - The global indices for each inner subdomain (or NULL, if not requested) 1687 . outerislist - The global indices for each outer subdomain (or NULL, if not requested) 1688 - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1689 1690 Level: intermediate 1691 1692 Notes: 1693 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1694 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1695 and all of the arrays should be freed with PetscFree(). 1696 1697 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition() 1698 @*/ 1699 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 1700 { 1701 PetscErrorCode ierr; 1702 DMSubDomainHookLink link; 1703 PetscInt i,l; 1704 1705 PetscFunctionBegin; 1706 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1707 if (len) {PetscValidPointer(len,2); *len = 0;} 1708 if (namelist) {PetscValidPointer(namelist,3); *namelist = NULL;} 1709 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = NULL;} 1710 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = NULL;} 1711 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = NULL;} 1712 /* 1713 Is it a good idea to apply the following check across all impls? 1714 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1715 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1716 */ 1717 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1718 if (dm->ops->createdomaindecomposition) { 1719 ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr); 1720 /* copy subdomain hooks and context over to the subdomain DMs */ 1721 if (dmlist && *dmlist) { 1722 for (i = 0; i < l; i++) { 1723 for (link=dm->subdomainhook; link; link=link->next) { 1724 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);} 1725 } 1726 if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx; 1727 } 1728 } 1729 if (len) *len = l; 1730 } 1731 PetscFunctionReturn(0); 1732 } 1733 1734 1735 /*@C 1736 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector 1737 1738 Not collective 1739 1740 Input Parameters: 1741 + dm - the DM object 1742 . n - the number of subdomain scatters 1743 - subdms - the local subdomains 1744 1745 Output Parameters: 1746 + n - the number of scatters returned 1747 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain 1748 . oscat - scatter from global vector to overlapping global vector entries on subdomain 1749 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts) 1750 1751 Notes: 1752 This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution 1753 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets 1754 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of 1755 solution and residual data. 1756 1757 Level: developer 1758 1759 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1760 @*/ 1761 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat) 1762 { 1763 PetscErrorCode ierr; 1764 1765 PetscFunctionBegin; 1766 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1767 PetscValidPointer(subdms,3); 1768 if (dm->ops->createddscatters) { 1769 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr); 1770 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionScatter implementation defined"); 1771 PetscFunctionReturn(0); 1772 } 1773 1774 /*@ 1775 DMRefine - Refines a DM object 1776 1777 Collective on DM 1778 1779 Input Parameter: 1780 + dm - the DM object 1781 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1782 1783 Output Parameter: 1784 . dmf - the refined DM, or NULL 1785 1786 Note: If no refinement was done, the return value is NULL 1787 1788 Level: developer 1789 1790 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1791 @*/ 1792 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 1793 { 1794 PetscErrorCode ierr; 1795 DMRefineHookLink link; 1796 1797 PetscFunctionBegin; 1798 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1799 ierr = PetscLogEventBegin(DM_Refine,dm,0,0,0);CHKERRQ(ierr); 1800 if (!dm->ops->refine) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot refine"); 1801 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr); 1802 if (*dmf) { 1803 (*dmf)->ops->creatematrix = dm->ops->creatematrix; 1804 1805 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr); 1806 1807 (*dmf)->ctx = dm->ctx; 1808 (*dmf)->leveldown = dm->leveldown; 1809 (*dmf)->levelup = dm->levelup + 1; 1810 1811 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr); 1812 for (link=dm->refinehook; link; link=link->next) { 1813 if (link->refinehook) { 1814 ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr); 1815 } 1816 } 1817 } 1818 ierr = PetscLogEventEnd(DM_Refine,dm,0,0,0);CHKERRQ(ierr); 1819 PetscFunctionReturn(0); 1820 } 1821 1822 /*@C 1823 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 1824 1825 Logically Collective 1826 1827 Input Arguments: 1828 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1829 . refinehook - function to run when setting up a coarser level 1830 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1831 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1832 1833 Calling sequence of refinehook: 1834 $ refinehook(DM coarse,DM fine,void *ctx); 1835 1836 + coarse - coarse level DM 1837 . fine - fine level DM to interpolate problem to 1838 - ctx - optional user-defined function context 1839 1840 Calling sequence for interphook: 1841 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 1842 1843 + coarse - coarse level DM 1844 . interp - matrix interpolating a coarse-level solution to the finer grid 1845 . fine - fine level DM to update 1846 - ctx - optional user-defined function context 1847 1848 Level: advanced 1849 1850 Notes: 1851 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 1852 1853 If this function is called multiple times, the hooks will be run in the order they are added. 1854 1855 This function is currently not available from Fortran. 1856 1857 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1858 @*/ 1859 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1860 { 1861 PetscErrorCode ierr; 1862 DMRefineHookLink link,*p; 1863 1864 PetscFunctionBegin; 1865 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1866 for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 1867 if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) PetscFunctionReturn(0); 1868 } 1869 ierr = PetscNew(&link);CHKERRQ(ierr); 1870 link->refinehook = refinehook; 1871 link->interphook = interphook; 1872 link->ctx = ctx; 1873 link->next = NULL; 1874 *p = link; 1875 PetscFunctionReturn(0); 1876 } 1877 1878 /*@C 1879 DMRefineHookRemove - remove a callback from the list of hooks to be run when interpolating a nonlinear problem to a finer grid 1880 1881 Logically Collective 1882 1883 Input Arguments: 1884 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1885 . refinehook - function to run when setting up a coarser level 1886 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1887 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1888 1889 Level: advanced 1890 1891 Notes: 1892 This function does nothing if the hook is not in the list. 1893 1894 This function is currently not available from Fortran. 1895 1896 .seealso: DMCoarsenHookRemove(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1897 @*/ 1898 PetscErrorCode DMRefineHookRemove(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1899 { 1900 PetscErrorCode ierr; 1901 DMRefineHookLink link,*p; 1902 1903 PetscFunctionBegin; 1904 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1905 for (p=&coarse->refinehook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 1906 if ((*p)->refinehook == refinehook && (*p)->interphook == interphook && (*p)->ctx == ctx) { 1907 link = *p; 1908 *p = link->next; 1909 ierr = PetscFree(link);CHKERRQ(ierr); 1910 break; 1911 } 1912 } 1913 PetscFunctionReturn(0); 1914 } 1915 1916 /*@ 1917 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 1918 1919 Collective if any hooks are 1920 1921 Input Arguments: 1922 + coarse - coarser DM to use as a base 1923 . interp - interpolation matrix, apply using MatInterpolate() 1924 - fine - finer DM to update 1925 1926 Level: developer 1927 1928 .seealso: DMRefineHookAdd(), MatInterpolate() 1929 @*/ 1930 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 1931 { 1932 PetscErrorCode ierr; 1933 DMRefineHookLink link; 1934 1935 PetscFunctionBegin; 1936 for (link=fine->refinehook; link; link=link->next) { 1937 if (link->interphook) { 1938 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr); 1939 } 1940 } 1941 PetscFunctionReturn(0); 1942 } 1943 1944 /*@ 1945 DMGetRefineLevel - Get's the number of refinements that have generated this DM. 1946 1947 Not Collective 1948 1949 Input Parameter: 1950 . dm - the DM object 1951 1952 Output Parameter: 1953 . level - number of refinements 1954 1955 Level: developer 1956 1957 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1958 1959 @*/ 1960 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 1961 { 1962 PetscFunctionBegin; 1963 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1964 *level = dm->levelup; 1965 PetscFunctionReturn(0); 1966 } 1967 1968 /*@ 1969 DMSetRefineLevel - Set's the number of refinements that have generated this DM. 1970 1971 Not Collective 1972 1973 Input Parameter: 1974 + dm - the DM object 1975 - level - number of refinements 1976 1977 Level: advanced 1978 1979 Notes: 1980 This value is used by PCMG to determine how many multigrid levels to use 1981 1982 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1983 1984 @*/ 1985 PetscErrorCode DMSetRefineLevel(DM dm,PetscInt level) 1986 { 1987 PetscFunctionBegin; 1988 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1989 dm->levelup = level; 1990 PetscFunctionReturn(0); 1991 } 1992 1993 /*@C 1994 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called 1995 1996 Logically Collective 1997 1998 Input Arguments: 1999 + dm - the DM 2000 . beginhook - function to run at the beginning of DMGlobalToLocalBegin() 2001 . endhook - function to run after DMGlobalToLocalEnd() has completed 2002 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2003 2004 Calling sequence for beginhook: 2005 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 2006 2007 + dm - global DM 2008 . g - global vector 2009 . mode - mode 2010 . l - local vector 2011 - ctx - optional user-defined function context 2012 2013 2014 Calling sequence for endhook: 2015 $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 2016 2017 + global - global DM 2018 - ctx - optional user-defined function context 2019 2020 Level: advanced 2021 2022 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2023 @*/ 2024 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 2025 { 2026 PetscErrorCode ierr; 2027 DMGlobalToLocalHookLink link,*p; 2028 2029 PetscFunctionBegin; 2030 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2031 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2032 ierr = PetscNew(&link);CHKERRQ(ierr); 2033 link->beginhook = beginhook; 2034 link->endhook = endhook; 2035 link->ctx = ctx; 2036 link->next = NULL; 2037 *p = link; 2038 PetscFunctionReturn(0); 2039 } 2040 2041 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx) 2042 { 2043 Mat cMat; 2044 Vec cVec; 2045 PetscSection section, cSec; 2046 PetscInt pStart, pEnd, p, dof; 2047 PetscErrorCode ierr; 2048 2049 PetscFunctionBegin; 2050 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2051 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 2052 if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) { 2053 PetscInt nRows; 2054 2055 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 2056 if (nRows <= 0) PetscFunctionReturn(0); 2057 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 2058 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 2059 ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr); 2060 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 2061 for (p = pStart; p < pEnd; p++) { 2062 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 2063 if (dof) { 2064 PetscScalar *vals; 2065 ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr); 2066 ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr); 2067 } 2068 } 2069 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2070 } 2071 PetscFunctionReturn(0); 2072 } 2073 2074 /*@ 2075 DMGlobalToLocalBegin - Begins updating local vectors from global vector 2076 2077 Neighbor-wise Collective on DM 2078 2079 Input Parameters: 2080 + dm - the DM object 2081 . g - the global vector 2082 . mode - INSERT_VALUES or ADD_VALUES 2083 - l - the local vector 2084 2085 2086 Level: beginner 2087 2088 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2089 2090 @*/ 2091 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2092 { 2093 PetscSF sf; 2094 PetscErrorCode ierr; 2095 DMGlobalToLocalHookLink link; 2096 2097 PetscFunctionBegin; 2098 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2099 for (link=dm->gtolhook; link; link=link->next) { 2100 if (link->beginhook) { 2101 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 2102 } 2103 } 2104 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2105 if (sf) { 2106 const PetscScalar *gArray; 2107 PetscScalar *lArray; 2108 2109 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2110 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 2111 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 2112 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 2113 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 2114 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 2115 } else { 2116 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2117 } 2118 PetscFunctionReturn(0); 2119 } 2120 2121 /*@ 2122 DMGlobalToLocalEnd - Ends updating local vectors from global vector 2123 2124 Neighbor-wise Collective on DM 2125 2126 Input Parameters: 2127 + dm - the DM object 2128 . g - the global vector 2129 . mode - INSERT_VALUES or ADD_VALUES 2130 - l - the local vector 2131 2132 2133 Level: beginner 2134 2135 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2136 2137 @*/ 2138 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2139 { 2140 PetscSF sf; 2141 PetscErrorCode ierr; 2142 const PetscScalar *gArray; 2143 PetscScalar *lArray; 2144 DMGlobalToLocalHookLink link; 2145 2146 PetscFunctionBegin; 2147 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2148 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2149 if (sf) { 2150 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2151 2152 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 2153 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 2154 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 2155 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 2156 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 2157 } else { 2158 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2159 } 2160 ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr); 2161 for (link=dm->gtolhook; link; link=link->next) { 2162 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2163 } 2164 PetscFunctionReturn(0); 2165 } 2166 2167 /*@C 2168 DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called 2169 2170 Logically Collective 2171 2172 Input Arguments: 2173 + dm - the DM 2174 . beginhook - function to run at the beginning of DMLocalToGlobalBegin() 2175 . endhook - function to run after DMLocalToGlobalEnd() has completed 2176 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2177 2178 Calling sequence for beginhook: 2179 $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2180 2181 + dm - global DM 2182 . l - local vector 2183 . mode - mode 2184 . g - global vector 2185 - ctx - optional user-defined function context 2186 2187 2188 Calling sequence for endhook: 2189 $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2190 2191 + global - global DM 2192 . l - local vector 2193 . mode - mode 2194 . g - global vector 2195 - ctx - optional user-defined function context 2196 2197 Level: advanced 2198 2199 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2200 @*/ 2201 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 2202 { 2203 PetscErrorCode ierr; 2204 DMLocalToGlobalHookLink link,*p; 2205 2206 PetscFunctionBegin; 2207 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2208 for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2209 ierr = PetscNew(&link);CHKERRQ(ierr); 2210 link->beginhook = beginhook; 2211 link->endhook = endhook; 2212 link->ctx = ctx; 2213 link->next = NULL; 2214 *p = link; 2215 PetscFunctionReturn(0); 2216 } 2217 2218 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx) 2219 { 2220 Mat cMat; 2221 Vec cVec; 2222 PetscSection section, cSec; 2223 PetscInt pStart, pEnd, p, dof; 2224 PetscErrorCode ierr; 2225 2226 PetscFunctionBegin; 2227 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2228 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 2229 if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) { 2230 PetscInt nRows; 2231 2232 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 2233 if (nRows <= 0) PetscFunctionReturn(0); 2234 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 2235 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 2236 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 2237 for (p = pStart; p < pEnd; p++) { 2238 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 2239 if (dof) { 2240 PetscInt d; 2241 PetscScalar *vals; 2242 ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr); 2243 ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr); 2244 /* for this to be the true transpose, we have to zero the values that 2245 * we just extracted */ 2246 for (d = 0; d < dof; d++) { 2247 vals[d] = 0.; 2248 } 2249 } 2250 } 2251 ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr); 2252 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2253 } 2254 PetscFunctionReturn(0); 2255 } 2256 2257 /*@ 2258 DMLocalToGlobalBegin - updates global vectors from local vectors 2259 2260 Neighbor-wise Collective on DM 2261 2262 Input Parameters: 2263 + dm - the DM object 2264 . l - the local vector 2265 . 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. 2266 - g - the global vector 2267 2268 Notes: 2269 In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 2270 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one. 2271 2272 Level: beginner 2273 2274 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 2275 2276 @*/ 2277 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 2278 { 2279 PetscSF sf; 2280 PetscSection s, gs; 2281 DMLocalToGlobalHookLink link; 2282 const PetscScalar *lArray; 2283 PetscScalar *gArray; 2284 PetscBool isInsert; 2285 PetscErrorCode ierr; 2286 2287 PetscFunctionBegin; 2288 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2289 for (link=dm->ltoghook; link; link=link->next) { 2290 if (link->beginhook) { 2291 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr); 2292 } 2293 } 2294 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr); 2295 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2296 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 2297 switch (mode) { 2298 case INSERT_VALUES: 2299 case INSERT_ALL_VALUES: 2300 case INSERT_BC_VALUES: 2301 isInsert = PETSC_TRUE; break; 2302 case ADD_VALUES: 2303 case ADD_ALL_VALUES: 2304 case ADD_BC_VALUES: 2305 isInsert = PETSC_FALSE; break; 2306 default: 2307 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2308 } 2309 if (sf && !isInsert) { 2310 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2311 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2312 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2313 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2314 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2315 } else if (s && isInsert) { 2316 PetscInt gStart, pStart, pEnd, p; 2317 2318 ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr); 2319 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 2320 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 2321 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2322 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2323 for (p = pStart; p < pEnd; ++p) { 2324 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 2325 2326 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 2327 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 2328 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 2329 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 2330 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 2331 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 2332 /* Ignore off-process data and points with no global data */ 2333 if (!gdof || goff < 0) continue; 2334 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); 2335 /* If no constraints are enforced in the global vector */ 2336 if (!gcdof) { 2337 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 2338 /* If constraints are enforced in the global vector */ 2339 } else if (cdof == gcdof) { 2340 const PetscInt *cdofs; 2341 PetscInt cind = 0; 2342 2343 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 2344 for (d = 0, e = 0; d < dof; ++d) { 2345 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 2346 gArray[goff-gStart+e++] = lArray[off+d]; 2347 } 2348 } 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); 2349 } 2350 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2351 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2352 } else { 2353 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2354 } 2355 PetscFunctionReturn(0); 2356 } 2357 2358 /*@ 2359 DMLocalToGlobalEnd - updates global vectors from local vectors 2360 2361 Neighbor-wise Collective on DM 2362 2363 Input Parameters: 2364 + dm - the DM object 2365 . l - the local vector 2366 . mode - INSERT_VALUES or ADD_VALUES 2367 - g - the global vector 2368 2369 2370 Level: beginner 2371 2372 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 2373 2374 @*/ 2375 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 2376 { 2377 PetscSF sf; 2378 PetscSection s; 2379 DMLocalToGlobalHookLink link; 2380 PetscBool isInsert; 2381 PetscErrorCode ierr; 2382 2383 PetscFunctionBegin; 2384 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2385 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2386 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 2387 switch (mode) { 2388 case INSERT_VALUES: 2389 case INSERT_ALL_VALUES: 2390 isInsert = PETSC_TRUE; break; 2391 case ADD_VALUES: 2392 case ADD_ALL_VALUES: 2393 isInsert = PETSC_FALSE; break; 2394 default: 2395 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2396 } 2397 if (sf && !isInsert) { 2398 const PetscScalar *lArray; 2399 PetscScalar *gArray; 2400 2401 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2402 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2403 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2404 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2405 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2406 } else if (s && isInsert) { 2407 } else { 2408 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2409 } 2410 for (link=dm->ltoghook; link; link=link->next) { 2411 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2412 } 2413 PetscFunctionReturn(0); 2414 } 2415 2416 /*@ 2417 DMLocalToLocalBegin - Maps from a local vector (including ghost points 2418 that contain irrelevant values) to another local vector where the ghost 2419 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 2420 2421 Neighbor-wise Collective on DM and Vec 2422 2423 Input Parameters: 2424 + dm - the DM object 2425 . g - the original local vector 2426 - mode - one of INSERT_VALUES or ADD_VALUES 2427 2428 Output Parameter: 2429 . l - the local vector with correct ghost values 2430 2431 Level: intermediate 2432 2433 Notes: 2434 The local vectors used here need not be the same as those 2435 obtained from DMCreateLocalVector(), BUT they 2436 must have the same parallel data layout; they could, for example, be 2437 obtained with VecDuplicate() from the DM originating vectors. 2438 2439 .keywords: DM, local-to-local, begin 2440 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2441 2442 @*/ 2443 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2444 { 2445 PetscErrorCode ierr; 2446 2447 PetscFunctionBegin; 2448 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2449 if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 2450 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2451 PetscFunctionReturn(0); 2452 } 2453 2454 /*@ 2455 DMLocalToLocalEnd - Maps from a local vector (including ghost points 2456 that contain irrelevant values) to another local vector where the ghost 2457 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 2458 2459 Neighbor-wise Collective on DM and Vec 2460 2461 Input Parameters: 2462 + da - the DM object 2463 . g - the original local vector 2464 - mode - one of INSERT_VALUES or ADD_VALUES 2465 2466 Output Parameter: 2467 . l - the local vector with correct ghost values 2468 2469 Level: intermediate 2470 2471 Notes: 2472 The local vectors used here need not be the same as those 2473 obtained from DMCreateLocalVector(), BUT they 2474 must have the same parallel data layout; they could, for example, be 2475 obtained with VecDuplicate() from the DM originating vectors. 2476 2477 .keywords: DM, local-to-local, end 2478 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2479 2480 @*/ 2481 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2482 { 2483 PetscErrorCode ierr; 2484 2485 PetscFunctionBegin; 2486 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2487 if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 2488 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2489 PetscFunctionReturn(0); 2490 } 2491 2492 2493 /*@ 2494 DMCoarsen - Coarsens a DM object 2495 2496 Collective on DM 2497 2498 Input Parameter: 2499 + dm - the DM object 2500 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2501 2502 Output Parameter: 2503 . dmc - the coarsened DM 2504 2505 Level: developer 2506 2507 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2508 2509 @*/ 2510 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 2511 { 2512 PetscErrorCode ierr; 2513 DMCoarsenHookLink link; 2514 2515 PetscFunctionBegin; 2516 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2517 if (!dm->ops->coarsen) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot coarsen"); 2518 ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2519 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 2520 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 2521 ierr = DMSetCoarseDM(dm,*dmc);CHKERRQ(ierr); 2522 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2523 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2524 (*dmc)->ctx = dm->ctx; 2525 (*dmc)->levelup = dm->levelup; 2526 (*dmc)->leveldown = dm->leveldown + 1; 2527 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2528 for (link=dm->coarsenhook; link; link=link->next) { 2529 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2530 } 2531 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2532 PetscFunctionReturn(0); 2533 } 2534 2535 /*@C 2536 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2537 2538 Logically Collective 2539 2540 Input Arguments: 2541 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2542 . coarsenhook - function to run when setting up a coarser level 2543 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2544 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2545 2546 Calling sequence of coarsenhook: 2547 $ coarsenhook(DM fine,DM coarse,void *ctx); 2548 2549 + fine - fine level DM 2550 . coarse - coarse level DM to restrict problem to 2551 - ctx - optional user-defined function context 2552 2553 Calling sequence for restricthook: 2554 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2555 2556 + fine - fine level DM 2557 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2558 . rscale - scaling vector for restriction 2559 . inject - matrix restricting by injection 2560 . coarse - coarse level DM to update 2561 - ctx - optional user-defined function context 2562 2563 Level: advanced 2564 2565 Notes: 2566 This function is only needed if auxiliary data needs to be set up on coarse grids. 2567 2568 If this function is called multiple times, the hooks will be run in the order they are added. 2569 2570 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2571 extract the finest level information from its context (instead of from the SNES). 2572 2573 This function is currently not available from Fortran. 2574 2575 .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2576 @*/ 2577 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2578 { 2579 PetscErrorCode ierr; 2580 DMCoarsenHookLink link,*p; 2581 2582 PetscFunctionBegin; 2583 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2584 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 2585 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 2586 } 2587 ierr = PetscNew(&link);CHKERRQ(ierr); 2588 link->coarsenhook = coarsenhook; 2589 link->restricthook = restricthook; 2590 link->ctx = ctx; 2591 link->next = NULL; 2592 *p = link; 2593 PetscFunctionReturn(0); 2594 } 2595 2596 /*@C 2597 DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid 2598 2599 Logically Collective 2600 2601 Input Arguments: 2602 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2603 . coarsenhook - function to run when setting up a coarser level 2604 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2605 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2606 2607 Level: advanced 2608 2609 Notes: 2610 This function does nothing if the hook is not in the list. 2611 2612 This function is currently not available from Fortran. 2613 2614 .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2615 @*/ 2616 PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2617 { 2618 PetscErrorCode ierr; 2619 DMCoarsenHookLink link,*p; 2620 2621 PetscFunctionBegin; 2622 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2623 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 2624 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 2625 link = *p; 2626 *p = link->next; 2627 ierr = PetscFree(link);CHKERRQ(ierr); 2628 break; 2629 } 2630 } 2631 PetscFunctionReturn(0); 2632 } 2633 2634 2635 /*@ 2636 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 2637 2638 Collective if any hooks are 2639 2640 Input Arguments: 2641 + fine - finer DM to use as a base 2642 . restrct - restriction matrix, apply using MatRestrict() 2643 . rscale - scaling vector for restriction 2644 . inject - injection matrix, also use MatRestrict() 2645 - coarse - coarser DM to update 2646 2647 Level: developer 2648 2649 .seealso: DMCoarsenHookAdd(), MatRestrict() 2650 @*/ 2651 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 2652 { 2653 PetscErrorCode ierr; 2654 DMCoarsenHookLink link; 2655 2656 PetscFunctionBegin; 2657 for (link=fine->coarsenhook; link; link=link->next) { 2658 if (link->restricthook) { 2659 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 2660 } 2661 } 2662 PetscFunctionReturn(0); 2663 } 2664 2665 /*@C 2666 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 2667 2668 Logically Collective 2669 2670 Input Arguments: 2671 + global - global DM 2672 . ddhook - function to run to pass data to the decomposition DM upon its creation 2673 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2674 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2675 2676 2677 Calling sequence for ddhook: 2678 $ ddhook(DM global,DM block,void *ctx) 2679 2680 + global - global DM 2681 . block - block DM 2682 - ctx - optional user-defined function context 2683 2684 Calling sequence for restricthook: 2685 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 2686 2687 + global - global DM 2688 . out - scatter to the outer (with ghost and overlap points) block vector 2689 . in - scatter to block vector values only owned locally 2690 . block - block DM 2691 - ctx - optional user-defined function context 2692 2693 Level: advanced 2694 2695 Notes: 2696 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 2697 2698 If this function is called multiple times, the hooks will be run in the order they are added. 2699 2700 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2701 extract the global information from its context (instead of from the SNES). 2702 2703 This function is currently not available from Fortran. 2704 2705 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2706 @*/ 2707 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2708 { 2709 PetscErrorCode ierr; 2710 DMSubDomainHookLink link,*p; 2711 2712 PetscFunctionBegin; 2713 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2714 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 2715 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 2716 } 2717 ierr = PetscNew(&link);CHKERRQ(ierr); 2718 link->restricthook = restricthook; 2719 link->ddhook = ddhook; 2720 link->ctx = ctx; 2721 link->next = NULL; 2722 *p = link; 2723 PetscFunctionReturn(0); 2724 } 2725 2726 /*@C 2727 DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid 2728 2729 Logically Collective 2730 2731 Input Arguments: 2732 + global - global DM 2733 . ddhook - function to run to pass data to the decomposition DM upon its creation 2734 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2735 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2736 2737 Level: advanced 2738 2739 Notes: 2740 2741 This function is currently not available from Fortran. 2742 2743 .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2744 @*/ 2745 PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2746 { 2747 PetscErrorCode ierr; 2748 DMSubDomainHookLink link,*p; 2749 2750 PetscFunctionBegin; 2751 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2752 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 2753 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 2754 link = *p; 2755 *p = link->next; 2756 ierr = PetscFree(link);CHKERRQ(ierr); 2757 break; 2758 } 2759 } 2760 PetscFunctionReturn(0); 2761 } 2762 2763 /*@ 2764 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 2765 2766 Collective if any hooks are 2767 2768 Input Arguments: 2769 + fine - finer DM to use as a base 2770 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 2771 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 2772 - coarse - coarer DM to update 2773 2774 Level: developer 2775 2776 .seealso: DMCoarsenHookAdd(), MatRestrict() 2777 @*/ 2778 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 2779 { 2780 PetscErrorCode ierr; 2781 DMSubDomainHookLink link; 2782 2783 PetscFunctionBegin; 2784 for (link=global->subdomainhook; link; link=link->next) { 2785 if (link->restricthook) { 2786 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2787 } 2788 } 2789 PetscFunctionReturn(0); 2790 } 2791 2792 /*@ 2793 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2794 2795 Not Collective 2796 2797 Input Parameter: 2798 . dm - the DM object 2799 2800 Output Parameter: 2801 . level - number of coarsenings 2802 2803 Level: developer 2804 2805 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2806 2807 @*/ 2808 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2809 { 2810 PetscFunctionBegin; 2811 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2812 *level = dm->leveldown; 2813 PetscFunctionReturn(0); 2814 } 2815 2816 2817 2818 /*@C 2819 DMRefineHierarchy - Refines a DM object, all levels at once 2820 2821 Collective on DM 2822 2823 Input Parameter: 2824 + dm - the DM object 2825 - nlevels - the number of levels of refinement 2826 2827 Output Parameter: 2828 . dmf - the refined DM hierarchy 2829 2830 Level: developer 2831 2832 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2833 2834 @*/ 2835 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 2836 { 2837 PetscErrorCode ierr; 2838 2839 PetscFunctionBegin; 2840 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2841 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2842 if (nlevels == 0) PetscFunctionReturn(0); 2843 if (dm->ops->refinehierarchy) { 2844 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2845 } else if (dm->ops->refine) { 2846 PetscInt i; 2847 2848 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2849 for (i=1; i<nlevels; i++) { 2850 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2851 } 2852 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2853 PetscFunctionReturn(0); 2854 } 2855 2856 /*@C 2857 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2858 2859 Collective on DM 2860 2861 Input Parameter: 2862 + dm - the DM object 2863 - nlevels - the number of levels of coarsening 2864 2865 Output Parameter: 2866 . dmc - the coarsened DM hierarchy 2867 2868 Level: developer 2869 2870 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2871 2872 @*/ 2873 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 2874 { 2875 PetscErrorCode ierr; 2876 2877 PetscFunctionBegin; 2878 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2879 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2880 if (nlevels == 0) PetscFunctionReturn(0); 2881 PetscValidPointer(dmc,3); 2882 if (dm->ops->coarsenhierarchy) { 2883 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 2884 } else if (dm->ops->coarsen) { 2885 PetscInt i; 2886 2887 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 2888 for (i=1; i<nlevels; i++) { 2889 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 2890 } 2891 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 2892 PetscFunctionReturn(0); 2893 } 2894 2895 /*@ 2896 DMCreateAggregates - Gets the aggregates that map between 2897 grids associated with two DMs. 2898 2899 Collective on DM 2900 2901 Input Parameters: 2902 + dmc - the coarse grid DM 2903 - dmf - the fine grid DM 2904 2905 Output Parameters: 2906 . rest - the restriction matrix (transpose of the projection matrix) 2907 2908 Level: intermediate 2909 2910 .keywords: interpolation, restriction, multigrid 2911 2912 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 2913 @*/ 2914 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 2915 { 2916 PetscErrorCode ierr; 2917 2918 PetscFunctionBegin; 2919 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 2920 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 2921 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 2922 PetscFunctionReturn(0); 2923 } 2924 2925 /*@C 2926 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 2927 2928 Not Collective 2929 2930 Input Parameters: 2931 + dm - the DM object 2932 - destroy - the destroy function 2933 2934 Level: intermediate 2935 2936 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2937 2938 @*/ 2939 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 2940 { 2941 PetscFunctionBegin; 2942 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2943 dm->ctxdestroy = destroy; 2944 PetscFunctionReturn(0); 2945 } 2946 2947 /*@ 2948 DMSetApplicationContext - Set a user context into a DM object 2949 2950 Not Collective 2951 2952 Input Parameters: 2953 + dm - the DM object 2954 - ctx - the user context 2955 2956 Level: intermediate 2957 2958 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2959 2960 @*/ 2961 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 2962 { 2963 PetscFunctionBegin; 2964 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2965 dm->ctx = ctx; 2966 PetscFunctionReturn(0); 2967 } 2968 2969 /*@ 2970 DMGetApplicationContext - Gets a user context from a DM object 2971 2972 Not Collective 2973 2974 Input Parameter: 2975 . dm - the DM object 2976 2977 Output Parameter: 2978 . ctx - the user context 2979 2980 Level: intermediate 2981 2982 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2983 2984 @*/ 2985 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 2986 { 2987 PetscFunctionBegin; 2988 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2989 *(void**)ctx = dm->ctx; 2990 PetscFunctionReturn(0); 2991 } 2992 2993 /*@C 2994 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 2995 2996 Logically Collective on DM 2997 2998 Input Parameter: 2999 + dm - the DM object 3000 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 3001 3002 Level: intermediate 3003 3004 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 3005 DMSetJacobian() 3006 3007 @*/ 3008 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 3009 { 3010 PetscFunctionBegin; 3011 dm->ops->computevariablebounds = f; 3012 PetscFunctionReturn(0); 3013 } 3014 3015 /*@ 3016 DMHasVariableBounds - does the DM object have a variable bounds function? 3017 3018 Not Collective 3019 3020 Input Parameter: 3021 . dm - the DM object to destroy 3022 3023 Output Parameter: 3024 . flg - PETSC_TRUE if the variable bounds function exists 3025 3026 Level: developer 3027 3028 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3029 3030 @*/ 3031 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 3032 { 3033 PetscFunctionBegin; 3034 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 3035 PetscFunctionReturn(0); 3036 } 3037 3038 /*@C 3039 DMComputeVariableBounds - compute variable bounds used by SNESVI. 3040 3041 Logically Collective on DM 3042 3043 Input Parameters: 3044 . dm - the DM object 3045 3046 Output parameters: 3047 + xl - lower bound 3048 - xu - upper bound 3049 3050 Level: advanced 3051 3052 Notes: 3053 This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 3054 3055 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3056 3057 @*/ 3058 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 3059 { 3060 PetscErrorCode ierr; 3061 3062 PetscFunctionBegin; 3063 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 3064 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 3065 if (dm->ops->computevariablebounds) { 3066 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 3067 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 3068 PetscFunctionReturn(0); 3069 } 3070 3071 /*@ 3072 DMHasColoring - does the DM object have a method of providing a coloring? 3073 3074 Not Collective 3075 3076 Input Parameter: 3077 . dm - the DM object 3078 3079 Output Parameter: 3080 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 3081 3082 Level: developer 3083 3084 .seealso DMHasFunction(), DMCreateColoring() 3085 3086 @*/ 3087 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 3088 { 3089 PetscFunctionBegin; 3090 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 3091 PetscFunctionReturn(0); 3092 } 3093 3094 /*@ 3095 DMHasCreateRestriction - does the DM object have a method of providing a restriction? 3096 3097 Not Collective 3098 3099 Input Parameter: 3100 . dm - the DM object 3101 3102 Output Parameter: 3103 . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction(). 3104 3105 Level: developer 3106 3107 .seealso DMHasFunction(), DMCreateRestriction() 3108 3109 @*/ 3110 PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg) 3111 { 3112 PetscFunctionBegin; 3113 *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE; 3114 PetscFunctionReturn(0); 3115 } 3116 3117 3118 /*@ 3119 DMHasCreateInjection - does the DM object have a method of providing an injection? 3120 3121 Not Collective 3122 3123 Input Parameter: 3124 . dm - the DM object 3125 3126 Output Parameter: 3127 . flg - PETSC_TRUE if the DM has facilities for DMCreateInjection(). 3128 3129 Level: developer 3130 3131 .seealso DMHasFunction(), DMCreateInjection() 3132 3133 @*/ 3134 PetscErrorCode DMHasCreateInjection(DM dm,PetscBool *flg) 3135 { 3136 PetscErrorCode ierr; 3137 PetscFunctionBegin; 3138 if (!dm->ops->hascreateinjection) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DMHasCreateInjection not implemented for this type"); 3139 ierr = (*dm->ops->hascreateinjection)(dm,flg);CHKERRQ(ierr); 3140 PetscFunctionReturn(0); 3141 } 3142 3143 /*@C 3144 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 3145 3146 Collective on DM 3147 3148 Input Parameter: 3149 + dm - the DM object 3150 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 3151 3152 Level: developer 3153 3154 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3155 3156 @*/ 3157 PetscErrorCode DMSetVec(DM dm,Vec x) 3158 { 3159 PetscErrorCode ierr; 3160 3161 PetscFunctionBegin; 3162 if (x) { 3163 if (!dm->x) { 3164 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 3165 } 3166 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 3167 } else if (dm->x) { 3168 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 3169 } 3170 PetscFunctionReturn(0); 3171 } 3172 3173 PetscFunctionList DMList = NULL; 3174 PetscBool DMRegisterAllCalled = PETSC_FALSE; 3175 3176 /*@C 3177 DMSetType - Builds a DM, for a particular DM implementation. 3178 3179 Collective on DM 3180 3181 Input Parameters: 3182 + dm - The DM object 3183 - method - The name of the DM type 3184 3185 Options Database Key: 3186 . -dm_type <type> - Sets the DM type; use -help for a list of available types 3187 3188 Notes: 3189 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 3190 3191 Level: intermediate 3192 3193 .keywords: DM, set, type 3194 .seealso: DMGetType(), DMCreate() 3195 @*/ 3196 PetscErrorCode DMSetType(DM dm, DMType method) 3197 { 3198 PetscErrorCode (*r)(DM); 3199 PetscBool match; 3200 PetscErrorCode ierr; 3201 3202 PetscFunctionBegin; 3203 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3204 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 3205 if (match) PetscFunctionReturn(0); 3206 3207 ierr = DMRegisterAll();CHKERRQ(ierr); 3208 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 3209 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 3210 3211 if (dm->ops->destroy) { 3212 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 3213 dm->ops->destroy = NULL; 3214 } 3215 ierr = (*r)(dm);CHKERRQ(ierr); 3216 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 3217 PetscFunctionReturn(0); 3218 } 3219 3220 /*@C 3221 DMGetType - Gets the DM type name (as a string) from the DM. 3222 3223 Not Collective 3224 3225 Input Parameter: 3226 . dm - The DM 3227 3228 Output Parameter: 3229 . type - The DM type name 3230 3231 Level: intermediate 3232 3233 .keywords: DM, get, type, name 3234 .seealso: DMSetType(), DMCreate() 3235 @*/ 3236 PetscErrorCode DMGetType(DM dm, DMType *type) 3237 { 3238 PetscErrorCode ierr; 3239 3240 PetscFunctionBegin; 3241 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3242 PetscValidPointer(type,2); 3243 ierr = DMRegisterAll();CHKERRQ(ierr); 3244 *type = ((PetscObject)dm)->type_name; 3245 PetscFunctionReturn(0); 3246 } 3247 3248 /*@C 3249 DMConvert - Converts a DM to another DM, either of the same or different type. 3250 3251 Collective on DM 3252 3253 Input Parameters: 3254 + dm - the DM 3255 - newtype - new DM type (use "same" for the same type) 3256 3257 Output Parameter: 3258 . M - pointer to new DM 3259 3260 Notes: 3261 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 3262 the MPI communicator of the generated DM is always the same as the communicator 3263 of the input DM. 3264 3265 Level: intermediate 3266 3267 .seealso: DMCreate() 3268 @*/ 3269 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 3270 { 3271 DM B; 3272 char convname[256]; 3273 PetscBool sametype/*, issame */; 3274 PetscErrorCode ierr; 3275 3276 PetscFunctionBegin; 3277 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3278 PetscValidType(dm,1); 3279 PetscValidPointer(M,3); 3280 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 3281 /* ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); */ 3282 if (sametype) { 3283 *M = dm; 3284 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 3285 PetscFunctionReturn(0); 3286 } else { 3287 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 3288 3289 /* 3290 Order of precedence: 3291 1) See if a specialized converter is known to the current DM. 3292 2) See if a specialized converter is known to the desired DM class. 3293 3) See if a good general converter is registered for the desired class 3294 4) See if a good general converter is known for the current matrix. 3295 5) Use a really basic converter. 3296 */ 3297 3298 /* 1) See if a specialized converter is known to the current DM and the desired class */ 3299 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3300 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3301 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3302 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3303 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3304 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 3305 if (conv) goto foundconv; 3306 3307 /* 2) See if a specialized converter is known to the desired DM class. */ 3308 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 3309 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 3310 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3311 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3312 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3313 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3314 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3315 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 3316 if (conv) { 3317 ierr = DMDestroy(&B);CHKERRQ(ierr); 3318 goto foundconv; 3319 } 3320 3321 #if 0 3322 /* 3) See if a good general converter is registered for the desired class */ 3323 conv = B->ops->convertfrom; 3324 ierr = DMDestroy(&B);CHKERRQ(ierr); 3325 if (conv) goto foundconv; 3326 3327 /* 4) See if a good general converter is known for the current matrix */ 3328 if (dm->ops->convert) { 3329 conv = dm->ops->convert; 3330 } 3331 if (conv) goto foundconv; 3332 #endif 3333 3334 /* 5) Use a really basic converter. */ 3335 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 3336 3337 foundconv: 3338 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3339 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 3340 /* Things that are independent of DM type: We should consult DMClone() here */ 3341 { 3342 PetscBool isper; 3343 const PetscReal *maxCell, *L; 3344 const DMBoundaryType *bd; 3345 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 3346 ierr = DMSetPeriodicity(*M, isper, maxCell, L, bd);CHKERRQ(ierr); 3347 } 3348 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3349 } 3350 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 3351 PetscFunctionReturn(0); 3352 } 3353 3354 /*--------------------------------------------------------------------------------------------------------------------*/ 3355 3356 /*@C 3357 DMRegister - Adds a new DM component implementation 3358 3359 Not Collective 3360 3361 Input Parameters: 3362 + name - The name of a new user-defined creation routine 3363 - create_func - The creation routine itself 3364 3365 Notes: 3366 DMRegister() may be called multiple times to add several user-defined DMs 3367 3368 3369 Sample usage: 3370 .vb 3371 DMRegister("my_da", MyDMCreate); 3372 .ve 3373 3374 Then, your DM type can be chosen with the procedural interface via 3375 .vb 3376 DMCreate(MPI_Comm, DM *); 3377 DMSetType(DM,"my_da"); 3378 .ve 3379 or at runtime via the option 3380 .vb 3381 -da_type my_da 3382 .ve 3383 3384 Level: advanced 3385 3386 .keywords: DM, register 3387 .seealso: DMRegisterAll(), DMRegisterDestroy() 3388 3389 @*/ 3390 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 3391 { 3392 PetscErrorCode ierr; 3393 3394 PetscFunctionBegin; 3395 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 3396 PetscFunctionReturn(0); 3397 } 3398 3399 /*@C 3400 DMLoad - Loads a DM that has been stored in binary with DMView(). 3401 3402 Collective on PetscViewer 3403 3404 Input Parameters: 3405 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 3406 some related function before a call to DMLoad(). 3407 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 3408 HDF5 file viewer, obtained from PetscViewerHDF5Open() 3409 3410 Level: intermediate 3411 3412 Notes: 3413 The type is determined by the data in the file, any type set into the DM before this call is ignored. 3414 3415 Notes for advanced users: 3416 Most users should not need to know the details of the binary storage 3417 format, since DMLoad() and DMView() completely hide these details. 3418 But for anyone who's interested, the standard binary matrix storage 3419 format is 3420 .vb 3421 has not yet been determined 3422 .ve 3423 3424 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 3425 @*/ 3426 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 3427 { 3428 PetscBool isbinary, ishdf5; 3429 PetscErrorCode ierr; 3430 3431 PetscFunctionBegin; 3432 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 3433 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3434 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 3435 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 3436 if (isbinary) { 3437 PetscInt classid; 3438 char type[256]; 3439 3440 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3441 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3442 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3443 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3444 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3445 } else if (ishdf5) { 3446 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3447 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3448 PetscFunctionReturn(0); 3449 } 3450 3451 /******************************** FEM Support **********************************/ 3452 3453 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3454 { 3455 PetscInt f; 3456 PetscErrorCode ierr; 3457 3458 PetscFunctionBegin; 3459 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3460 for (f = 0; f < len; ++f) { 3461 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3462 } 3463 PetscFunctionReturn(0); 3464 } 3465 3466 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3467 { 3468 PetscInt f, g; 3469 PetscErrorCode ierr; 3470 3471 PetscFunctionBegin; 3472 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3473 for (f = 0; f < rows; ++f) { 3474 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3475 for (g = 0; g < cols; ++g) { 3476 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3477 } 3478 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3479 } 3480 PetscFunctionReturn(0); 3481 } 3482 3483 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3484 { 3485 PetscInt localSize, bs; 3486 PetscMPIInt size; 3487 Vec x, xglob; 3488 const PetscScalar *xarray; 3489 PetscErrorCode ierr; 3490 3491 PetscFunctionBegin; 3492 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);CHKERRQ(ierr); 3493 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3494 ierr = VecCopy(X, x);CHKERRQ(ierr); 3495 ierr = VecChop(x, tol);CHKERRQ(ierr); 3496 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);CHKERRQ(ierr); 3497 if (size > 1) { 3498 ierr = VecGetLocalSize(x,&localSize);CHKERRQ(ierr); 3499 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr); 3500 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 3501 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);CHKERRQ(ierr); 3502 } else { 3503 xglob = x; 3504 } 3505 ierr = VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));CHKERRQ(ierr); 3506 if (size > 1) { 3507 ierr = VecDestroy(&xglob);CHKERRQ(ierr); 3508 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 3509 } 3510 ierr = VecDestroy(&x);CHKERRQ(ierr); 3511 PetscFunctionReturn(0); 3512 } 3513 3514 /*@ 3515 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 3516 3517 Input Parameter: 3518 . dm - The DM 3519 3520 Output Parameter: 3521 . section - The PetscSection 3522 3523 Level: intermediate 3524 3525 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3526 3527 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3528 @*/ 3529 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 3530 { 3531 PetscErrorCode ierr; 3532 3533 PetscFunctionBegin; 3534 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3535 PetscValidPointer(section, 2); 3536 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3537 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3538 if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 3539 } 3540 *section = dm->defaultSection; 3541 PetscFunctionReturn(0); 3542 } 3543 3544 /*@ 3545 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3546 3547 Input Parameters: 3548 + dm - The DM 3549 - section - The PetscSection 3550 3551 Level: intermediate 3552 3553 Note: Any existing Section will be destroyed 3554 3555 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3556 @*/ 3557 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 3558 { 3559 PetscInt numFields = 0; 3560 PetscInt f; 3561 PetscErrorCode ierr; 3562 3563 PetscFunctionBegin; 3564 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3565 if (section) { 3566 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3567 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3568 } 3569 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3570 dm->defaultSection = section; 3571 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3572 if (numFields) { 3573 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3574 for (f = 0; f < numFields; ++f) { 3575 PetscObject disc; 3576 const char *name; 3577 3578 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3579 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3580 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3581 } 3582 } 3583 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3584 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3585 PetscFunctionReturn(0); 3586 } 3587 3588 /*@ 3589 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3590 3591 not collective 3592 3593 Input Parameter: 3594 . dm - The DM 3595 3596 Output Parameter: 3597 + 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. 3598 - 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. 3599 3600 Level: advanced 3601 3602 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3603 3604 .seealso: DMSetDefaultConstraints() 3605 @*/ 3606 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3607 { 3608 PetscErrorCode ierr; 3609 3610 PetscFunctionBegin; 3611 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3612 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3613 if (section) {*section = dm->defaultConstraintSection;} 3614 if (mat) {*mat = dm->defaultConstraintMat;} 3615 PetscFunctionReturn(0); 3616 } 3617 3618 /*@ 3619 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3620 3621 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(). 3622 3623 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. 3624 3625 collective on dm 3626 3627 Input Parameters: 3628 + dm - The DM 3629 + 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). 3630 - 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). 3631 3632 Level: advanced 3633 3634 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3635 3636 .seealso: DMGetDefaultConstraints() 3637 @*/ 3638 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3639 { 3640 PetscMPIInt result; 3641 PetscErrorCode ierr; 3642 3643 PetscFunctionBegin; 3644 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3645 if (section) { 3646 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3647 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3648 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3649 } 3650 if (mat) { 3651 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3652 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3653 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3654 } 3655 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3656 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3657 dm->defaultConstraintSection = section; 3658 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3659 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3660 dm->defaultConstraintMat = mat; 3661 PetscFunctionReturn(0); 3662 } 3663 3664 #if defined(PETSC_USE_DEBUG) 3665 /* 3666 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3667 3668 Input Parameters: 3669 + dm - The DM 3670 . localSection - PetscSection describing the local data layout 3671 - globalSection - PetscSection describing the global data layout 3672 3673 Level: intermediate 3674 3675 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3676 */ 3677 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3678 { 3679 MPI_Comm comm; 3680 PetscLayout layout; 3681 const PetscInt *ranges; 3682 PetscInt pStart, pEnd, p, nroots; 3683 PetscMPIInt size, rank; 3684 PetscBool valid = PETSC_TRUE, gvalid; 3685 PetscErrorCode ierr; 3686 3687 PetscFunctionBegin; 3688 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3689 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3690 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3691 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3692 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3693 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3694 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3695 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3696 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3697 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3698 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3699 for (p = pStart; p < pEnd; ++p) { 3700 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3701 3702 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3703 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3704 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3705 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3706 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3707 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3708 if (!gdof) continue; /* Censored point */ 3709 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;} 3710 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;} 3711 if (gdof < 0) { 3712 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3713 for (d = 0; d < gsize; ++d) { 3714 PetscInt offset = -(goff+1) + d, r; 3715 3716 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3717 if (r < 0) r = -(r+2); 3718 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;} 3719 } 3720 } 3721 } 3722 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3723 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3724 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3725 if (!gvalid) { 3726 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3727 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3728 } 3729 PetscFunctionReturn(0); 3730 } 3731 #endif 3732 3733 /*@ 3734 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3735 3736 Collective on DM 3737 3738 Input Parameter: 3739 . dm - The DM 3740 3741 Output Parameter: 3742 . section - The PetscSection 3743 3744 Level: intermediate 3745 3746 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3747 3748 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3749 @*/ 3750 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3751 { 3752 PetscErrorCode ierr; 3753 3754 PetscFunctionBegin; 3755 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3756 PetscValidPointer(section, 2); 3757 if (!dm->defaultGlobalSection) { 3758 PetscSection s; 3759 3760 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3761 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3762 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3763 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3764 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3765 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3766 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 3767 } 3768 *section = dm->defaultGlobalSection; 3769 PetscFunctionReturn(0); 3770 } 3771 3772 /*@ 3773 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3774 3775 Input Parameters: 3776 + dm - The DM 3777 - section - The PetscSection, or NULL 3778 3779 Level: intermediate 3780 3781 Note: Any existing Section will be destroyed 3782 3783 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3784 @*/ 3785 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3786 { 3787 PetscErrorCode ierr; 3788 3789 PetscFunctionBegin; 3790 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3791 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3792 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3793 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3794 dm->defaultGlobalSection = section; 3795 #if defined(PETSC_USE_DEBUG) 3796 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3797 #endif 3798 PetscFunctionReturn(0); 3799 } 3800 3801 /*@ 3802 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3803 it is created from the default PetscSection layouts in the DM. 3804 3805 Input Parameter: 3806 . dm - The DM 3807 3808 Output Parameter: 3809 . sf - The PetscSF 3810 3811 Level: intermediate 3812 3813 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3814 3815 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3816 @*/ 3817 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3818 { 3819 PetscInt nroots; 3820 PetscErrorCode ierr; 3821 3822 PetscFunctionBegin; 3823 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3824 PetscValidPointer(sf, 2); 3825 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3826 if (nroots < 0) { 3827 PetscSection section, gSection; 3828 3829 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3830 if (section) { 3831 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3832 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3833 } else { 3834 *sf = NULL; 3835 PetscFunctionReturn(0); 3836 } 3837 } 3838 *sf = dm->defaultSF; 3839 PetscFunctionReturn(0); 3840 } 3841 3842 /*@ 3843 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3844 3845 Input Parameters: 3846 + dm - The DM 3847 - sf - The PetscSF 3848 3849 Level: intermediate 3850 3851 Note: Any previous SF is destroyed 3852 3853 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3854 @*/ 3855 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3856 { 3857 PetscErrorCode ierr; 3858 3859 PetscFunctionBegin; 3860 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3861 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3862 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3863 dm->defaultSF = sf; 3864 PetscFunctionReturn(0); 3865 } 3866 3867 /*@C 3868 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3869 describing the data layout. 3870 3871 Input Parameters: 3872 + dm - The DM 3873 . localSection - PetscSection describing the local data layout 3874 - globalSection - PetscSection describing the global data layout 3875 3876 Level: intermediate 3877 3878 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3879 @*/ 3880 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3881 { 3882 MPI_Comm comm; 3883 PetscLayout layout; 3884 const PetscInt *ranges; 3885 PetscInt *local; 3886 PetscSFNode *remote; 3887 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3888 PetscMPIInt size, rank; 3889 PetscErrorCode ierr; 3890 3891 PetscFunctionBegin; 3892 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3893 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3894 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3895 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3896 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3897 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3898 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3899 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3900 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3901 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3902 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3903 for (p = pStart; p < pEnd; ++p) { 3904 PetscInt gdof, gcdof; 3905 3906 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3907 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3908 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)); 3909 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3910 } 3911 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3912 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3913 for (p = pStart, l = 0; p < pEnd; ++p) { 3914 const PetscInt *cind; 3915 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3916 3917 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3918 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3919 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3920 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3921 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3922 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3923 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3924 if (!gdof) continue; /* Censored point */ 3925 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3926 if (gsize != dof-cdof) { 3927 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); 3928 cdof = 0; /* Ignore constraints */ 3929 } 3930 for (d = 0, c = 0; d < dof; ++d) { 3931 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3932 local[l+d-c] = off+d; 3933 } 3934 if (gdof < 0) { 3935 for (d = 0; d < gsize; ++d, ++l) { 3936 PetscInt offset = -(goff+1) + d, r; 3937 3938 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3939 if (r < 0) r = -(r+2); 3940 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); 3941 remote[l].rank = r; 3942 remote[l].index = offset - ranges[r]; 3943 } 3944 } else { 3945 for (d = 0; d < gsize; ++d, ++l) { 3946 remote[l].rank = rank; 3947 remote[l].index = goff+d - ranges[rank]; 3948 } 3949 } 3950 } 3951 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3952 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3953 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3954 PetscFunctionReturn(0); 3955 } 3956 3957 /*@ 3958 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3959 3960 Input Parameter: 3961 . dm - The DM 3962 3963 Output Parameter: 3964 . sf - The PetscSF 3965 3966 Level: intermediate 3967 3968 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3969 3970 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3971 @*/ 3972 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3973 { 3974 PetscFunctionBegin; 3975 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3976 PetscValidPointer(sf, 2); 3977 *sf = dm->sf; 3978 PetscFunctionReturn(0); 3979 } 3980 3981 /*@ 3982 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3983 3984 Input Parameters: 3985 + dm - The DM 3986 - sf - The PetscSF 3987 3988 Level: intermediate 3989 3990 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3991 @*/ 3992 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3993 { 3994 PetscErrorCode ierr; 3995 3996 PetscFunctionBegin; 3997 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3998 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3999 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 4000 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4001 dm->sf = sf; 4002 PetscFunctionReturn(0); 4003 } 4004 4005 /*@ 4006 DMGetDS - Get the PetscDS 4007 4008 Input Parameter: 4009 . dm - The DM 4010 4011 Output Parameter: 4012 . prob - The PetscDS 4013 4014 Level: developer 4015 4016 .seealso: DMSetDS() 4017 @*/ 4018 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 4019 { 4020 PetscFunctionBegin; 4021 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4022 PetscValidPointer(prob, 2); 4023 *prob = dm->prob; 4024 PetscFunctionReturn(0); 4025 } 4026 4027 /*@ 4028 DMSetDS - Set the PetscDS 4029 4030 Input Parameters: 4031 + dm - The DM 4032 - prob - The PetscDS 4033 4034 Level: developer 4035 4036 .seealso: DMGetDS() 4037 @*/ 4038 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 4039 { 4040 PetscInt dimEmbed; 4041 PetscErrorCode ierr; 4042 4043 PetscFunctionBegin; 4044 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4045 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 4046 ierr = PetscObjectReference((PetscObject) prob);CHKERRQ(ierr); 4047 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 4048 dm->prob = prob; 4049 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 4050 ierr = PetscDSSetCoordinateDimension(prob, dimEmbed);CHKERRQ(ierr); 4051 PetscFunctionReturn(0); 4052 } 4053 4054 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 4055 { 4056 PetscErrorCode ierr; 4057 4058 PetscFunctionBegin; 4059 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4060 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 4061 PetscFunctionReturn(0); 4062 } 4063 4064 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 4065 { 4066 PetscInt Nf, f; 4067 PetscErrorCode ierr; 4068 4069 PetscFunctionBegin; 4070 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4071 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 4072 for (f = Nf; f < numFields; ++f) { 4073 PetscContainer obj; 4074 4075 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 4076 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 4077 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 4078 } 4079 PetscFunctionReturn(0); 4080 } 4081 4082 /*@ 4083 DMGetField - Return the discretization object for a given DM field 4084 4085 Not collective 4086 4087 Input Parameters: 4088 + dm - The DM 4089 - f - The field number 4090 4091 Output Parameter: 4092 . field - The discretization object 4093 4094 Level: developer 4095 4096 .seealso: DMSetField() 4097 @*/ 4098 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 4099 { 4100 PetscErrorCode ierr; 4101 4102 PetscFunctionBegin; 4103 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4104 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 4105 PetscFunctionReturn(0); 4106 } 4107 4108 /*@ 4109 DMSetField - Set the discretization object for a given DM field 4110 4111 Logically collective on DM 4112 4113 Input Parameters: 4114 + dm - The DM 4115 . f - The field number 4116 - field - The discretization object 4117 4118 Level: developer 4119 4120 .seealso: DMGetField() 4121 @*/ 4122 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 4123 { 4124 PetscErrorCode ierr; 4125 4126 PetscFunctionBegin; 4127 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4128 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 4129 PetscFunctionReturn(0); 4130 } 4131 4132 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 4133 { 4134 DM dm_coord,dmc_coord; 4135 PetscErrorCode ierr; 4136 Vec coords,ccoords; 4137 Mat inject; 4138 PetscFunctionBegin; 4139 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4140 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 4141 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4142 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 4143 if (coords && !ccoords) { 4144 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 4145 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4146 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 4147 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 4148 ierr = MatDestroy(&inject);CHKERRQ(ierr); 4149 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 4150 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4151 } 4152 PetscFunctionReturn(0); 4153 } 4154 4155 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 4156 { 4157 DM dm_coord,subdm_coord; 4158 PetscErrorCode ierr; 4159 Vec coords,ccoords,clcoords; 4160 VecScatter *scat_i,*scat_g; 4161 PetscFunctionBegin; 4162 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4163 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 4164 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4165 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 4166 if (coords && !ccoords) { 4167 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 4168 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4169 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 4170 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 4171 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 4172 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4173 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4174 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4175 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4176 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 4177 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 4178 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 4179 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 4180 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4181 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 4182 ierr = PetscFree(scat_i);CHKERRQ(ierr); 4183 ierr = PetscFree(scat_g);CHKERRQ(ierr); 4184 } 4185 PetscFunctionReturn(0); 4186 } 4187 4188 /*@ 4189 DMGetDimension - Return the topological dimension of the DM 4190 4191 Not collective 4192 4193 Input Parameter: 4194 . dm - The DM 4195 4196 Output Parameter: 4197 . dim - The topological dimension 4198 4199 Level: beginner 4200 4201 .seealso: DMSetDimension(), DMCreate() 4202 @*/ 4203 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 4204 { 4205 PetscFunctionBegin; 4206 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4207 PetscValidPointer(dim, 2); 4208 *dim = dm->dim; 4209 PetscFunctionReturn(0); 4210 } 4211 4212 /*@ 4213 DMSetDimension - Set the topological dimension of the DM 4214 4215 Collective on dm 4216 4217 Input Parameters: 4218 + dm - The DM 4219 - dim - The topological dimension 4220 4221 Level: beginner 4222 4223 .seealso: DMGetDimension(), DMCreate() 4224 @*/ 4225 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 4226 { 4227 PetscErrorCode ierr; 4228 4229 PetscFunctionBegin; 4230 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4231 PetscValidLogicalCollectiveInt(dm, dim, 2); 4232 dm->dim = dim; 4233 if (dm->prob->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dim);CHKERRQ(ierr);} 4234 PetscFunctionReturn(0); 4235 } 4236 4237 /*@ 4238 DMGetDimPoints - Get the half-open interval for all points of a given dimension 4239 4240 Collective on DM 4241 4242 Input Parameters: 4243 + dm - the DM 4244 - dim - the dimension 4245 4246 Output Parameters: 4247 + pStart - The first point of the given dimension 4248 . pEnd - The first point following points of the given dimension 4249 4250 Note: 4251 The points are vertices in the Hasse diagram encoding the topology. This is explained in 4252 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 4253 then the interval is empty. 4254 4255 Level: intermediate 4256 4257 .keywords: point, Hasse Diagram, dimension 4258 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 4259 @*/ 4260 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4261 { 4262 PetscInt d; 4263 PetscErrorCode ierr; 4264 4265 PetscFunctionBegin; 4266 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4267 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 4268 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 4269 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 4270 PetscFunctionReturn(0); 4271 } 4272 4273 /*@ 4274 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 4275 4276 Collective on DM 4277 4278 Input Parameters: 4279 + dm - the DM 4280 - c - coordinate vector 4281 4282 Note: 4283 The coordinates do include those for ghost points, which are in the local vector 4284 4285 Level: intermediate 4286 4287 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4288 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 4289 @*/ 4290 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 4291 { 4292 PetscErrorCode ierr; 4293 4294 PetscFunctionBegin; 4295 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4296 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4297 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4298 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4299 dm->coordinates = c; 4300 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4301 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4302 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4303 PetscFunctionReturn(0); 4304 } 4305 4306 /*@ 4307 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 4308 4309 Collective on DM 4310 4311 Input Parameters: 4312 + dm - the DM 4313 - c - coordinate vector 4314 4315 Note: 4316 The coordinates of ghost points can be set using DMSetCoordinates() 4317 followed by DMGetCoordinatesLocal(). This is intended to enable the 4318 setting of ghost coordinates outside of the domain. 4319 4320 Level: intermediate 4321 4322 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4323 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 4324 @*/ 4325 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 4326 { 4327 PetscErrorCode ierr; 4328 4329 PetscFunctionBegin; 4330 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4331 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4332 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4333 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4334 4335 dm->coordinatesLocal = c; 4336 4337 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4338 PetscFunctionReturn(0); 4339 } 4340 4341 /*@ 4342 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 4343 4344 Not Collective 4345 4346 Input Parameter: 4347 . dm - the DM 4348 4349 Output Parameter: 4350 . c - global coordinate vector 4351 4352 Note: 4353 This is a borrowed reference, so the user should NOT destroy this vector 4354 4355 Each process has only the local coordinates (does NOT have the ghost coordinates). 4356 4357 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4358 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4359 4360 Level: intermediate 4361 4362 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4363 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4364 @*/ 4365 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4366 { 4367 PetscErrorCode ierr; 4368 4369 PetscFunctionBegin; 4370 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4371 PetscValidPointer(c,2); 4372 if (!dm->coordinates && dm->coordinatesLocal) { 4373 DM cdm = NULL; 4374 4375 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4376 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4377 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4378 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4379 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4380 } 4381 *c = dm->coordinates; 4382 PetscFunctionReturn(0); 4383 } 4384 4385 /*@ 4386 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4387 4388 Collective on DM 4389 4390 Input Parameter: 4391 . dm - the DM 4392 4393 Output Parameter: 4394 . c - coordinate vector 4395 4396 Note: 4397 This is a borrowed reference, so the user should NOT destroy this vector 4398 4399 Each process has the local and ghost coordinates 4400 4401 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4402 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4403 4404 Level: intermediate 4405 4406 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4407 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4408 @*/ 4409 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4410 { 4411 PetscErrorCode ierr; 4412 4413 PetscFunctionBegin; 4414 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4415 PetscValidPointer(c,2); 4416 if (!dm->coordinatesLocal && dm->coordinates) { 4417 DM cdm = NULL; 4418 4419 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4420 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4421 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4422 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4423 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4424 } 4425 *c = dm->coordinatesLocal; 4426 PetscFunctionReturn(0); 4427 } 4428 4429 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 4430 { 4431 PetscErrorCode ierr; 4432 4433 PetscFunctionBegin; 4434 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4435 PetscValidPointer(field,2); 4436 if (!dm->coordinateField) { 4437 if (dm->ops->createcoordinatefield) { 4438 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 4439 } 4440 } 4441 *field = dm->coordinateField; 4442 PetscFunctionReturn(0); 4443 } 4444 4445 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 4446 { 4447 PetscErrorCode ierr; 4448 4449 PetscFunctionBegin; 4450 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4451 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 4452 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 4453 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 4454 dm->coordinateField = field; 4455 PetscFunctionReturn(0); 4456 } 4457 4458 /*@ 4459 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4460 4461 Collective on DM 4462 4463 Input Parameter: 4464 . dm - the DM 4465 4466 Output Parameter: 4467 . cdm - coordinate DM 4468 4469 Level: intermediate 4470 4471 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4472 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4473 @*/ 4474 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4475 { 4476 PetscErrorCode ierr; 4477 4478 PetscFunctionBegin; 4479 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4480 PetscValidPointer(cdm,2); 4481 if (!dm->coordinateDM) { 4482 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4483 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 4484 } 4485 *cdm = dm->coordinateDM; 4486 PetscFunctionReturn(0); 4487 } 4488 4489 /*@ 4490 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4491 4492 Logically Collective on DM 4493 4494 Input Parameters: 4495 + dm - the DM 4496 - cdm - coordinate DM 4497 4498 Level: intermediate 4499 4500 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4501 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4502 @*/ 4503 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4504 { 4505 PetscErrorCode ierr; 4506 4507 PetscFunctionBegin; 4508 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4509 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4510 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 4511 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4512 dm->coordinateDM = cdm; 4513 PetscFunctionReturn(0); 4514 } 4515 4516 /*@ 4517 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4518 4519 Not Collective 4520 4521 Input Parameter: 4522 . dm - The DM object 4523 4524 Output Parameter: 4525 . dim - The embedding dimension 4526 4527 Level: intermediate 4528 4529 .keywords: mesh, coordinates 4530 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4531 @*/ 4532 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4533 { 4534 PetscFunctionBegin; 4535 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4536 PetscValidPointer(dim, 2); 4537 if (dm->dimEmbed == PETSC_DEFAULT) { 4538 dm->dimEmbed = dm->dim; 4539 } 4540 *dim = dm->dimEmbed; 4541 PetscFunctionReturn(0); 4542 } 4543 4544 /*@ 4545 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4546 4547 Not Collective 4548 4549 Input Parameters: 4550 + dm - The DM object 4551 - dim - The embedding dimension 4552 4553 Level: intermediate 4554 4555 .keywords: mesh, coordinates 4556 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4557 @*/ 4558 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4559 { 4560 PetscErrorCode ierr; 4561 4562 PetscFunctionBegin; 4563 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4564 dm->dimEmbed = dim; 4565 ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dimEmbed);CHKERRQ(ierr); 4566 PetscFunctionReturn(0); 4567 } 4568 4569 /*@ 4570 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4571 4572 Not Collective 4573 4574 Input Parameter: 4575 . dm - The DM object 4576 4577 Output Parameter: 4578 . section - The PetscSection object 4579 4580 Level: intermediate 4581 4582 .keywords: mesh, coordinates 4583 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4584 @*/ 4585 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4586 { 4587 DM cdm; 4588 PetscErrorCode ierr; 4589 4590 PetscFunctionBegin; 4591 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4592 PetscValidPointer(section, 2); 4593 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4594 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4595 PetscFunctionReturn(0); 4596 } 4597 4598 /*@ 4599 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4600 4601 Not Collective 4602 4603 Input Parameters: 4604 + dm - The DM object 4605 . dim - The embedding dimension, or PETSC_DETERMINE 4606 - section - The PetscSection object 4607 4608 Level: intermediate 4609 4610 .keywords: mesh, coordinates 4611 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4612 @*/ 4613 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4614 { 4615 DM cdm; 4616 PetscErrorCode ierr; 4617 4618 PetscFunctionBegin; 4619 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4620 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4621 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4622 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4623 if (dim == PETSC_DETERMINE) { 4624 PetscInt d = PETSC_DEFAULT; 4625 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4626 4627 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4628 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4629 pStart = PetscMax(vStart, pStart); 4630 pEnd = PetscMin(vEnd, pEnd); 4631 for (v = pStart; v < pEnd; ++v) { 4632 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4633 if (dd) {d = dd; break;} 4634 } 4635 if (d < 0) d = PETSC_DEFAULT; 4636 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4637 } 4638 PetscFunctionReturn(0); 4639 } 4640 4641 /*@C 4642 DMGetPeriodicity - Get the description of mesh periodicity 4643 4644 Input Parameters: 4645 . dm - The DM object 4646 4647 Output Parameters: 4648 + per - Whether the DM is periodic or not 4649 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4650 . L - If we assume the mesh is a torus, this is the length of each coordinate 4651 - bd - This describes the type of periodicity in each topological dimension 4652 4653 Level: developer 4654 4655 .seealso: DMGetPeriodicity() 4656 @*/ 4657 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4658 { 4659 PetscFunctionBegin; 4660 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4661 if (per) *per = dm->periodic; 4662 if (L) *L = dm->L; 4663 if (maxCell) *maxCell = dm->maxCell; 4664 if (bd) *bd = dm->bdtype; 4665 PetscFunctionReturn(0); 4666 } 4667 4668 /*@C 4669 DMSetPeriodicity - Set the description of mesh periodicity 4670 4671 Input Parameters: 4672 + dm - The DM object 4673 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 4674 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4675 . L - If we assume the mesh is a torus, this is the length of each coordinate 4676 - bd - This describes the type of periodicity in each topological dimension 4677 4678 Level: developer 4679 4680 .seealso: DMGetPeriodicity() 4681 @*/ 4682 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4683 { 4684 PetscInt dim, d; 4685 PetscErrorCode ierr; 4686 4687 PetscFunctionBegin; 4688 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4689 PetscValidLogicalCollectiveBool(dm,per,2); 4690 if (maxCell) { 4691 PetscValidPointer(maxCell,3); 4692 PetscValidPointer(L,4); 4693 PetscValidPointer(bd,5); 4694 } 4695 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4696 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4697 if (maxCell) { 4698 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4699 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4700 dm->periodic = PETSC_TRUE; 4701 } else { 4702 dm->periodic = per; 4703 } 4704 PetscFunctionReturn(0); 4705 } 4706 4707 /*@ 4708 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. 4709 4710 Input Parameters: 4711 + dm - The DM 4712 . in - The input coordinate point (dim numbers) 4713 - endpoint - Include the endpoint L_i 4714 4715 Output Parameter: 4716 . out - The localized coordinate point 4717 4718 Level: developer 4719 4720 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4721 @*/ 4722 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 4723 { 4724 PetscInt dim, d; 4725 PetscErrorCode ierr; 4726 4727 PetscFunctionBegin; 4728 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 4729 if (!dm->maxCell) { 4730 for (d = 0; d < dim; ++d) out[d] = in[d]; 4731 } else { 4732 if (endpoint) { 4733 for (d = 0; d < dim; ++d) { 4734 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)) { 4735 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 4736 } else { 4737 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 4738 } 4739 } 4740 } else { 4741 for (d = 0; d < dim; ++d) { 4742 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 4743 } 4744 } 4745 } 4746 PetscFunctionReturn(0); 4747 } 4748 4749 /* 4750 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. 4751 4752 Input Parameters: 4753 + dm - The DM 4754 . dim - The spatial dimension 4755 . anchor - The anchor point, the input point can be no more than maxCell away from it 4756 - in - The input coordinate point (dim numbers) 4757 4758 Output Parameter: 4759 . out - The localized coordinate point 4760 4761 Level: developer 4762 4763 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 4764 4765 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4766 */ 4767 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4768 { 4769 PetscInt d; 4770 4771 PetscFunctionBegin; 4772 if (!dm->maxCell) { 4773 for (d = 0; d < dim; ++d) out[d] = in[d]; 4774 } else { 4775 for (d = 0; d < dim; ++d) { 4776 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 4777 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4778 } else { 4779 out[d] = in[d]; 4780 } 4781 } 4782 } 4783 PetscFunctionReturn(0); 4784 } 4785 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 4786 { 4787 PetscInt d; 4788 4789 PetscFunctionBegin; 4790 if (!dm->maxCell) { 4791 for (d = 0; d < dim; ++d) out[d] = in[d]; 4792 } else { 4793 for (d = 0; d < dim; ++d) { 4794 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 4795 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4796 } else { 4797 out[d] = in[d]; 4798 } 4799 } 4800 } 4801 PetscFunctionReturn(0); 4802 } 4803 4804 /* 4805 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. 4806 4807 Input Parameters: 4808 + dm - The DM 4809 . dim - The spatial dimension 4810 . anchor - The anchor point, the input point can be no more than maxCell away from it 4811 . in - The input coordinate delta (dim numbers) 4812 - out - The input coordinate point (dim numbers) 4813 4814 Output Parameter: 4815 . out - The localized coordinate in + out 4816 4817 Level: developer 4818 4819 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 4820 4821 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 4822 */ 4823 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4824 { 4825 PetscInt d; 4826 4827 PetscFunctionBegin; 4828 if (!dm->maxCell) { 4829 for (d = 0; d < dim; ++d) out[d] += in[d]; 4830 } else { 4831 for (d = 0; d < dim; ++d) { 4832 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 4833 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4834 } else { 4835 out[d] += in[d]; 4836 } 4837 } 4838 } 4839 PetscFunctionReturn(0); 4840 } 4841 4842 /*@ 4843 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 4844 4845 Input Parameter: 4846 . dm - The DM 4847 4848 Output Parameter: 4849 areLocalized - True if localized 4850 4851 Level: developer 4852 4853 .seealso: DMLocalizeCoordinates() 4854 @*/ 4855 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 4856 { 4857 DM cdm; 4858 PetscSection coordSection; 4859 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 4860 PetscBool isPlex, alreadyLocalized; 4861 PetscErrorCode ierr; 4862 4863 PetscFunctionBegin; 4864 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4865 PetscValidPointer(areLocalized, 2); 4866 4867 *areLocalized = PETSC_FALSE; 4868 if (!dm->periodic) PetscFunctionReturn(0); /* This is a hideous optimization hack! */ 4869 4870 /* We need some generic way of refering to cells/vertices */ 4871 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4872 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4873 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 4874 if (!isPlex) SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4875 4876 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4877 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 4878 alreadyLocalized = PETSC_FALSE; 4879 for (c = cStart; c < cEnd; ++c) { 4880 if (c < sStart || c >= sEnd) continue; 4881 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 4882 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 4883 } 4884 ierr = MPIU_Allreduce(&alreadyLocalized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4885 PetscFunctionReturn(0); 4886 } 4887 4888 4889 /*@ 4890 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 4891 4892 Input Parameter: 4893 . dm - The DM 4894 4895 Level: developer 4896 4897 .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 4898 @*/ 4899 PetscErrorCode DMLocalizeCoordinates(DM dm) 4900 { 4901 DM cdm; 4902 PetscSection coordSection, cSection; 4903 Vec coordinates, cVec; 4904 PetscScalar *coords, *coords2, *anchor, *localized; 4905 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 4906 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4907 PetscInt maxHeight = 0, h; 4908 PetscInt *pStart = NULL, *pEnd = NULL; 4909 PetscErrorCode ierr; 4910 4911 PetscFunctionBegin; 4912 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4913 if (!dm->periodic) PetscFunctionReturn(0); 4914 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 4915 if (alreadyLocalized) PetscFunctionReturn(0); 4916 4917 /* We need some generic way of refering to cells/vertices */ 4918 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4919 { 4920 PetscBool isplex; 4921 4922 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4923 if (isplex) { 4924 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4925 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 4926 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4927 pEnd = &pStart[maxHeight + 1]; 4928 newStart = vStart; 4929 newEnd = vEnd; 4930 for (h = 0; h <= maxHeight; h++) { 4931 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 4932 newStart = PetscMin(newStart,pStart[h]); 4933 newEnd = PetscMax(newEnd,pEnd[h]); 4934 } 4935 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4936 } 4937 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4938 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 4939 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4940 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 4941 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4942 4943 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 4944 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 4945 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 4946 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 4947 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 4948 4949 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 4950 localized = &anchor[bs]; 4951 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 4952 for (h = 0; h <= maxHeight; h++) { 4953 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 4954 4955 for (c = cStart; c < cEnd; ++c) { 4956 PetscScalar *cellCoords = NULL; 4957 PetscInt b; 4958 4959 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 4960 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4961 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4962 for (d = 0; d < dof/bs; ++d) { 4963 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 4964 for (b = 0; b < bs; b++) { 4965 if (cellCoords[d*bs + b] != localized[b]) break; 4966 } 4967 if (b < bs) break; 4968 } 4969 if (d < dof/bs) { 4970 if (c >= sStart && c < sEnd) { 4971 PetscInt cdof; 4972 4973 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 4974 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 4975 } 4976 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 4977 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 4978 } 4979 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4980 } 4981 } 4982 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4983 if (alreadyLocalizedGlobal) { 4984 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 4985 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4986 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 4987 PetscFunctionReturn(0); 4988 } 4989 for (v = vStart; v < vEnd; ++v) { 4990 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4991 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 4992 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 4993 } 4994 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 4995 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 4996 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 4997 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 4998 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 4999 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 5000 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 5001 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 5002 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 5003 for (v = vStart; v < vEnd; ++v) { 5004 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 5005 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5006 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 5007 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 5008 } 5009 for (h = 0; h <= maxHeight; h++) { 5010 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 5011 5012 for (c = cStart; c < cEnd; ++c) { 5013 PetscScalar *cellCoords = NULL; 5014 PetscInt b, cdof; 5015 5016 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 5017 if (!cdof) continue; 5018 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5019 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 5020 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 5021 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 5022 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5023 } 5024 } 5025 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 5026 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 5027 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 5028 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 5029 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 5030 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 5031 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 5032 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 5033 PetscFunctionReturn(0); 5034 } 5035 5036 /*@ 5037 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 5038 5039 Collective on Vec v (see explanation below) 5040 5041 Input Parameters: 5042 + dm - The DM 5043 . v - The Vec of points 5044 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 5045 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 5046 5047 Output Parameter: 5048 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 5049 - cells - The PetscSF containing the ranks and local indices of the containing points. 5050 5051 5052 Level: developer 5053 5054 Notes: 5055 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 5056 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 5057 5058 If *cellSF is NULL on input, a PetscSF will be created. 5059 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 5060 5061 An array that maps each point to its containing cell can be obtained with 5062 5063 $ const PetscSFNode *cells; 5064 $ PetscInt nFound; 5065 $ const PetscInt *found; 5066 $ 5067 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 5068 5069 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 5070 the index of the cell in its rank's local numbering. 5071 5072 .keywords: point location, mesh 5073 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 5074 @*/ 5075 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 5076 { 5077 PetscErrorCode ierr; 5078 5079 PetscFunctionBegin; 5080 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5081 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 5082 PetscValidPointer(cellSF,4); 5083 if (*cellSF) { 5084 PetscMPIInt result; 5085 5086 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 5087 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 5088 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 5089 } else { 5090 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 5091 } 5092 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 5093 if (dm->ops->locatepoints) { 5094 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 5095 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 5096 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 5097 PetscFunctionReturn(0); 5098 } 5099 5100 /*@ 5101 DMGetOutputDM - Retrieve the DM associated with the layout for output 5102 5103 Input Parameter: 5104 . dm - The original DM 5105 5106 Output Parameter: 5107 . odm - The DM which provides the layout for output 5108 5109 Level: intermediate 5110 5111 .seealso: VecView(), DMGetDefaultGlobalSection() 5112 @*/ 5113 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 5114 { 5115 PetscSection section; 5116 PetscBool hasConstraints, ghasConstraints; 5117 PetscErrorCode ierr; 5118 5119 PetscFunctionBegin; 5120 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5121 PetscValidPointer(odm,2); 5122 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 5123 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 5124 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 5125 if (!ghasConstraints) { 5126 *odm = dm; 5127 PetscFunctionReturn(0); 5128 } 5129 if (!dm->dmBC) { 5130 PetscDS ds; 5131 PetscSection newSection, gsection; 5132 PetscSF sf; 5133 5134 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 5135 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5136 ierr = DMSetDS(dm->dmBC, ds);CHKERRQ(ierr); 5137 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 5138 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 5139 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 5140 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 5141 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 5142 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 5143 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 5144 } 5145 *odm = dm->dmBC; 5146 PetscFunctionReturn(0); 5147 } 5148 5149 /*@ 5150 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 5151 5152 Input Parameter: 5153 . dm - The original DM 5154 5155 Output Parameters: 5156 + num - The output sequence number 5157 - val - The output sequence value 5158 5159 Level: intermediate 5160 5161 Note: This is intended for output that should appear in sequence, for instance 5162 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5163 5164 .seealso: VecView() 5165 @*/ 5166 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 5167 { 5168 PetscFunctionBegin; 5169 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5170 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 5171 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 5172 PetscFunctionReturn(0); 5173 } 5174 5175 /*@ 5176 DMSetOutputSequenceNumber - Set the sequence number/value for output 5177 5178 Input Parameters: 5179 + dm - The original DM 5180 . num - The output sequence number 5181 - val - The output sequence value 5182 5183 Level: intermediate 5184 5185 Note: This is intended for output that should appear in sequence, for instance 5186 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5187 5188 .seealso: VecView() 5189 @*/ 5190 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 5191 { 5192 PetscFunctionBegin; 5193 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5194 dm->outputSequenceNum = num; 5195 dm->outputSequenceVal = val; 5196 PetscFunctionReturn(0); 5197 } 5198 5199 /*@C 5200 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 5201 5202 Input Parameters: 5203 + dm - The original DM 5204 . name - The sequence name 5205 - num - The output sequence number 5206 5207 Output Parameter: 5208 . val - The output sequence value 5209 5210 Level: intermediate 5211 5212 Note: This is intended for output that should appear in sequence, for instance 5213 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5214 5215 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 5216 @*/ 5217 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 5218 { 5219 PetscBool ishdf5; 5220 PetscErrorCode ierr; 5221 5222 PetscFunctionBegin; 5223 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5224 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 5225 PetscValidPointer(val,4); 5226 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 5227 if (ishdf5) { 5228 #if defined(PETSC_HAVE_HDF5) 5229 PetscScalar value; 5230 5231 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 5232 *val = PetscRealPart(value); 5233 #endif 5234 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 5235 PetscFunctionReturn(0); 5236 } 5237 5238 /*@ 5239 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 5240 5241 Not collective 5242 5243 Input Parameter: 5244 . dm - The DM 5245 5246 Output Parameter: 5247 . useNatural - The flag to build the mapping to a natural order during distribution 5248 5249 Level: beginner 5250 5251 .seealso: DMSetUseNatural(), DMCreate() 5252 @*/ 5253 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 5254 { 5255 PetscFunctionBegin; 5256 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5257 PetscValidPointer(useNatural, 2); 5258 *useNatural = dm->useNatural; 5259 PetscFunctionReturn(0); 5260 } 5261 5262 /*@ 5263 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 5264 5265 Collective on dm 5266 5267 Input Parameters: 5268 + dm - The DM 5269 - useNatural - The flag to build the mapping to a natural order during distribution 5270 5271 Level: beginner 5272 5273 .seealso: DMGetUseNatural(), DMCreate() 5274 @*/ 5275 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 5276 { 5277 PetscFunctionBegin; 5278 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5279 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 5280 dm->useNatural = useNatural; 5281 PetscFunctionReturn(0); 5282 } 5283 5284 5285 /*@C 5286 DMCreateLabel - Create a label of the given name if it does not already exist 5287 5288 Not Collective 5289 5290 Input Parameters: 5291 + dm - The DM object 5292 - name - The label name 5293 5294 Level: intermediate 5295 5296 .keywords: mesh 5297 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5298 @*/ 5299 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 5300 { 5301 DMLabelLink next = dm->labels->next; 5302 PetscBool flg = PETSC_FALSE; 5303 PetscErrorCode ierr; 5304 5305 PetscFunctionBegin; 5306 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5307 PetscValidCharPointer(name, 2); 5308 while (next) { 5309 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5310 if (flg) break; 5311 next = next->next; 5312 } 5313 if (!flg) { 5314 DMLabelLink tmpLabel; 5315 5316 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5317 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 5318 tmpLabel->output = PETSC_TRUE; 5319 tmpLabel->next = dm->labels->next; 5320 dm->labels->next = tmpLabel; 5321 } 5322 PetscFunctionReturn(0); 5323 } 5324 5325 /*@C 5326 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 5327 5328 Not Collective 5329 5330 Input Parameters: 5331 + dm - The DM object 5332 . name - The label name 5333 - point - The mesh point 5334 5335 Output Parameter: 5336 . value - The label value for this point, or -1 if the point is not in the label 5337 5338 Level: beginner 5339 5340 .keywords: mesh 5341 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 5342 @*/ 5343 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 5344 { 5345 DMLabel label; 5346 PetscErrorCode ierr; 5347 5348 PetscFunctionBegin; 5349 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5350 PetscValidCharPointer(name, 2); 5351 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5352 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 5353 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5354 PetscFunctionReturn(0); 5355 } 5356 5357 /*@C 5358 DMSetLabelValue - Add a point to a Sieve Label with given value 5359 5360 Not Collective 5361 5362 Input Parameters: 5363 + dm - The DM object 5364 . name - The label name 5365 . point - The mesh point 5366 - value - The label value for this point 5367 5368 Output Parameter: 5369 5370 Level: beginner 5371 5372 .keywords: mesh 5373 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5374 @*/ 5375 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5376 { 5377 DMLabel label; 5378 PetscErrorCode ierr; 5379 5380 PetscFunctionBegin; 5381 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5382 PetscValidCharPointer(name, 2); 5383 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5384 if (!label) { 5385 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5386 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5387 } 5388 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5389 PetscFunctionReturn(0); 5390 } 5391 5392 /*@C 5393 DMClearLabelValue - Remove a point from a Sieve Label with given value 5394 5395 Not Collective 5396 5397 Input Parameters: 5398 + dm - The DM object 5399 . name - The label name 5400 . point - The mesh point 5401 - value - The label value for this point 5402 5403 Output Parameter: 5404 5405 Level: beginner 5406 5407 .keywords: mesh 5408 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5409 @*/ 5410 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5411 { 5412 DMLabel label; 5413 PetscErrorCode ierr; 5414 5415 PetscFunctionBegin; 5416 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5417 PetscValidCharPointer(name, 2); 5418 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5419 if (!label) PetscFunctionReturn(0); 5420 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5421 PetscFunctionReturn(0); 5422 } 5423 5424 /*@C 5425 DMGetLabelSize - Get the number of different integer ids in a Label 5426 5427 Not Collective 5428 5429 Input Parameters: 5430 + dm - The DM object 5431 - name - The label name 5432 5433 Output Parameter: 5434 . size - The number of different integer ids, or 0 if the label does not exist 5435 5436 Level: beginner 5437 5438 .keywords: mesh 5439 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 5440 @*/ 5441 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5442 { 5443 DMLabel label; 5444 PetscErrorCode ierr; 5445 5446 PetscFunctionBegin; 5447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5448 PetscValidCharPointer(name, 2); 5449 PetscValidPointer(size, 3); 5450 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5451 *size = 0; 5452 if (!label) PetscFunctionReturn(0); 5453 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5454 PetscFunctionReturn(0); 5455 } 5456 5457 /*@C 5458 DMGetLabelIdIS - Get the integer ids in a label 5459 5460 Not Collective 5461 5462 Input Parameters: 5463 + mesh - The DM object 5464 - name - The label name 5465 5466 Output Parameter: 5467 . ids - The integer ids, or NULL if the label does not exist 5468 5469 Level: beginner 5470 5471 .keywords: mesh 5472 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5473 @*/ 5474 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5475 { 5476 DMLabel label; 5477 PetscErrorCode ierr; 5478 5479 PetscFunctionBegin; 5480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5481 PetscValidCharPointer(name, 2); 5482 PetscValidPointer(ids, 3); 5483 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5484 *ids = NULL; 5485 if (label) { 5486 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5487 } else { 5488 /* returning an empty IS */ 5489 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 5490 } 5491 PetscFunctionReturn(0); 5492 } 5493 5494 /*@C 5495 DMGetStratumSize - Get the number of points in a label stratum 5496 5497 Not Collective 5498 5499 Input Parameters: 5500 + dm - The DM object 5501 . name - The label name 5502 - value - The stratum value 5503 5504 Output Parameter: 5505 . size - The stratum size 5506 5507 Level: beginner 5508 5509 .keywords: mesh 5510 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5511 @*/ 5512 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5513 { 5514 DMLabel label; 5515 PetscErrorCode ierr; 5516 5517 PetscFunctionBegin; 5518 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5519 PetscValidCharPointer(name, 2); 5520 PetscValidPointer(size, 4); 5521 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5522 *size = 0; 5523 if (!label) PetscFunctionReturn(0); 5524 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5525 PetscFunctionReturn(0); 5526 } 5527 5528 /*@C 5529 DMGetStratumIS - Get the points in a label stratum 5530 5531 Not Collective 5532 5533 Input Parameters: 5534 + dm - The DM object 5535 . name - The label name 5536 - value - The stratum value 5537 5538 Output Parameter: 5539 . points - The stratum points, or NULL if the label does not exist or does not have that value 5540 5541 Level: beginner 5542 5543 .keywords: mesh 5544 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5545 @*/ 5546 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5547 { 5548 DMLabel label; 5549 PetscErrorCode ierr; 5550 5551 PetscFunctionBegin; 5552 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5553 PetscValidCharPointer(name, 2); 5554 PetscValidPointer(points, 4); 5555 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5556 *points = NULL; 5557 if (!label) PetscFunctionReturn(0); 5558 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5559 PetscFunctionReturn(0); 5560 } 5561 5562 /*@C 5563 DMSetStratumIS - Set the points in a label stratum 5564 5565 Not Collective 5566 5567 Input Parameters: 5568 + dm - The DM object 5569 . name - The label name 5570 . value - The stratum value 5571 - points - The stratum points 5572 5573 Level: beginner 5574 5575 .keywords: mesh 5576 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 5577 @*/ 5578 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 5579 { 5580 DMLabel label; 5581 PetscErrorCode ierr; 5582 5583 PetscFunctionBegin; 5584 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5585 PetscValidCharPointer(name, 2); 5586 PetscValidPointer(points, 4); 5587 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5588 if (!label) PetscFunctionReturn(0); 5589 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 5590 PetscFunctionReturn(0); 5591 } 5592 5593 /*@C 5594 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 5595 5596 Not Collective 5597 5598 Input Parameters: 5599 + dm - The DM object 5600 . name - The label name 5601 - value - The label value for this point 5602 5603 Output Parameter: 5604 5605 Level: beginner 5606 5607 .keywords: mesh 5608 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 5609 @*/ 5610 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 5611 { 5612 DMLabel label; 5613 PetscErrorCode ierr; 5614 5615 PetscFunctionBegin; 5616 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5617 PetscValidCharPointer(name, 2); 5618 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5619 if (!label) PetscFunctionReturn(0); 5620 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 5621 PetscFunctionReturn(0); 5622 } 5623 5624 /*@ 5625 DMGetNumLabels - Return the number of labels defined by the mesh 5626 5627 Not Collective 5628 5629 Input Parameter: 5630 . dm - The DM object 5631 5632 Output Parameter: 5633 . numLabels - the number of Labels 5634 5635 Level: intermediate 5636 5637 .keywords: mesh 5638 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5639 @*/ 5640 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 5641 { 5642 DMLabelLink next = dm->labels->next; 5643 PetscInt n = 0; 5644 5645 PetscFunctionBegin; 5646 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5647 PetscValidPointer(numLabels, 2); 5648 while (next) {++n; next = next->next;} 5649 *numLabels = n; 5650 PetscFunctionReturn(0); 5651 } 5652 5653 /*@C 5654 DMGetLabelName - Return the name of nth label 5655 5656 Not Collective 5657 5658 Input Parameters: 5659 + dm - The DM object 5660 - n - the label number 5661 5662 Output Parameter: 5663 . name - the label name 5664 5665 Level: intermediate 5666 5667 .keywords: mesh 5668 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5669 @*/ 5670 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 5671 { 5672 DMLabelLink next = dm->labels->next; 5673 PetscInt l = 0; 5674 5675 PetscFunctionBegin; 5676 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5677 PetscValidPointer(name, 3); 5678 while (next) { 5679 if (l == n) { 5680 *name = next->label->name; 5681 PetscFunctionReturn(0); 5682 } 5683 ++l; 5684 next = next->next; 5685 } 5686 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5687 } 5688 5689 /*@C 5690 DMHasLabel - Determine whether the mesh has a label of a given name 5691 5692 Not Collective 5693 5694 Input Parameters: 5695 + dm - The DM object 5696 - name - The label name 5697 5698 Output Parameter: 5699 . hasLabel - PETSC_TRUE if the label is present 5700 5701 Level: intermediate 5702 5703 .keywords: mesh 5704 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5705 @*/ 5706 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 5707 { 5708 DMLabelLink next = dm->labels->next; 5709 PetscErrorCode ierr; 5710 5711 PetscFunctionBegin; 5712 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5713 PetscValidCharPointer(name, 2); 5714 PetscValidPointer(hasLabel, 3); 5715 *hasLabel = PETSC_FALSE; 5716 while (next) { 5717 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 5718 if (*hasLabel) break; 5719 next = next->next; 5720 } 5721 PetscFunctionReturn(0); 5722 } 5723 5724 /*@C 5725 DMGetLabel - Return the label of a given name, or NULL 5726 5727 Not Collective 5728 5729 Input Parameters: 5730 + dm - The DM object 5731 - name - The label name 5732 5733 Output Parameter: 5734 . label - The DMLabel, or NULL if the label is absent 5735 5736 Level: intermediate 5737 5738 .keywords: mesh 5739 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5740 @*/ 5741 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 5742 { 5743 DMLabelLink next = dm->labels->next; 5744 PetscBool hasLabel; 5745 PetscErrorCode ierr; 5746 5747 PetscFunctionBegin; 5748 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5749 PetscValidCharPointer(name, 2); 5750 PetscValidPointer(label, 3); 5751 *label = NULL; 5752 while (next) { 5753 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5754 if (hasLabel) { 5755 *label = next->label; 5756 break; 5757 } 5758 next = next->next; 5759 } 5760 PetscFunctionReturn(0); 5761 } 5762 5763 /*@C 5764 DMGetLabelByNum - Return the nth label 5765 5766 Not Collective 5767 5768 Input Parameters: 5769 + dm - The DM object 5770 - n - the label number 5771 5772 Output Parameter: 5773 . label - the label 5774 5775 Level: intermediate 5776 5777 .keywords: mesh 5778 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5779 @*/ 5780 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5781 { 5782 DMLabelLink next = dm->labels->next; 5783 PetscInt l = 0; 5784 5785 PetscFunctionBegin; 5786 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5787 PetscValidPointer(label, 3); 5788 while (next) { 5789 if (l == n) { 5790 *label = next->label; 5791 PetscFunctionReturn(0); 5792 } 5793 ++l; 5794 next = next->next; 5795 } 5796 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5797 } 5798 5799 /*@C 5800 DMAddLabel - Add the label to this mesh 5801 5802 Not Collective 5803 5804 Input Parameters: 5805 + dm - The DM object 5806 - label - The DMLabel 5807 5808 Level: developer 5809 5810 .keywords: mesh 5811 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5812 @*/ 5813 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5814 { 5815 DMLabelLink tmpLabel; 5816 PetscBool hasLabel; 5817 PetscErrorCode ierr; 5818 5819 PetscFunctionBegin; 5820 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5821 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5822 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5823 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5824 tmpLabel->label = label; 5825 tmpLabel->output = PETSC_TRUE; 5826 tmpLabel->next = dm->labels->next; 5827 dm->labels->next = tmpLabel; 5828 PetscFunctionReturn(0); 5829 } 5830 5831 /*@C 5832 DMRemoveLabel - Remove the label from this mesh 5833 5834 Not Collective 5835 5836 Input Parameters: 5837 + dm - The DM object 5838 - name - The label name 5839 5840 Output Parameter: 5841 . label - The DMLabel, or NULL if the label is absent 5842 5843 Level: developer 5844 5845 .keywords: mesh 5846 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5847 @*/ 5848 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5849 { 5850 DMLabelLink next = dm->labels->next; 5851 DMLabelLink last = NULL; 5852 PetscBool hasLabel; 5853 PetscErrorCode ierr; 5854 5855 PetscFunctionBegin; 5856 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5857 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5858 *label = NULL; 5859 if (!hasLabel) PetscFunctionReturn(0); 5860 while (next) { 5861 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5862 if (hasLabel) { 5863 if (last) last->next = next->next; 5864 else dm->labels->next = next->next; 5865 next->next = NULL; 5866 *label = next->label; 5867 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5868 if (hasLabel) { 5869 dm->depthLabel = NULL; 5870 } 5871 ierr = PetscFree(next);CHKERRQ(ierr); 5872 break; 5873 } 5874 last = next; 5875 next = next->next; 5876 } 5877 PetscFunctionReturn(0); 5878 } 5879 5880 /*@C 5881 DMGetLabelOutput - Get the output flag for a given label 5882 5883 Not Collective 5884 5885 Input Parameters: 5886 + dm - The DM object 5887 - name - The label name 5888 5889 Output Parameter: 5890 . output - The flag for output 5891 5892 Level: developer 5893 5894 .keywords: mesh 5895 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5896 @*/ 5897 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5898 { 5899 DMLabelLink next = dm->labels->next; 5900 PetscErrorCode ierr; 5901 5902 PetscFunctionBegin; 5903 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5904 PetscValidPointer(name, 2); 5905 PetscValidPointer(output, 3); 5906 while (next) { 5907 PetscBool flg; 5908 5909 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5910 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5911 next = next->next; 5912 } 5913 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5914 } 5915 5916 /*@C 5917 DMSetLabelOutput - Set the output flag for a given label 5918 5919 Not Collective 5920 5921 Input Parameters: 5922 + dm - The DM object 5923 . name - The label name 5924 - output - The flag for output 5925 5926 Level: developer 5927 5928 .keywords: mesh 5929 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5930 @*/ 5931 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 5932 { 5933 DMLabelLink next = dm->labels->next; 5934 PetscErrorCode ierr; 5935 5936 PetscFunctionBegin; 5937 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5938 PetscValidPointer(name, 2); 5939 while (next) { 5940 PetscBool flg; 5941 5942 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5943 if (flg) {next->output = output; PetscFunctionReturn(0);} 5944 next = next->next; 5945 } 5946 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5947 } 5948 5949 5950 /*@ 5951 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 5952 5953 Collective on DM 5954 5955 Input Parameter: 5956 . dmA - The DM object with initial labels 5957 5958 Output Parameter: 5959 . dmB - The DM object with copied labels 5960 5961 Level: intermediate 5962 5963 Note: This is typically used when interpolating or otherwise adding to a mesh 5964 5965 .keywords: mesh 5966 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 5967 @*/ 5968 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 5969 { 5970 PetscInt numLabels, l; 5971 PetscErrorCode ierr; 5972 5973 PetscFunctionBegin; 5974 if (dmA == dmB) PetscFunctionReturn(0); 5975 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 5976 for (l = 0; l < numLabels; ++l) { 5977 DMLabel label, labelNew; 5978 const char *name; 5979 PetscBool flg; 5980 5981 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 5982 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 5983 if (flg) continue; 5984 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 5985 if (flg) continue; 5986 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 5987 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 5988 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 5989 } 5990 PetscFunctionReturn(0); 5991 } 5992 5993 /*@ 5994 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5995 5996 Input Parameter: 5997 . dm - The DM object 5998 5999 Output Parameter: 6000 . cdm - The coarse DM 6001 6002 Level: intermediate 6003 6004 .seealso: DMSetCoarseDM() 6005 @*/ 6006 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 6007 { 6008 PetscFunctionBegin; 6009 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6010 PetscValidPointer(cdm, 2); 6011 *cdm = dm->coarseMesh; 6012 PetscFunctionReturn(0); 6013 } 6014 6015 /*@ 6016 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 6017 6018 Input Parameters: 6019 + dm - The DM object 6020 - cdm - The coarse DM 6021 6022 Level: intermediate 6023 6024 .seealso: DMGetCoarseDM() 6025 @*/ 6026 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 6027 { 6028 PetscErrorCode ierr; 6029 6030 PetscFunctionBegin; 6031 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6032 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 6033 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 6034 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 6035 dm->coarseMesh = cdm; 6036 PetscFunctionReturn(0); 6037 } 6038 6039 /*@ 6040 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 6041 6042 Input Parameter: 6043 . dm - The DM object 6044 6045 Output Parameter: 6046 . fdm - The fine DM 6047 6048 Level: intermediate 6049 6050 .seealso: DMSetFineDM() 6051 @*/ 6052 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 6053 { 6054 PetscFunctionBegin; 6055 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6056 PetscValidPointer(fdm, 2); 6057 *fdm = dm->fineMesh; 6058 PetscFunctionReturn(0); 6059 } 6060 6061 /*@ 6062 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 6063 6064 Input Parameters: 6065 + dm - The DM object 6066 - fdm - The fine DM 6067 6068 Level: intermediate 6069 6070 .seealso: DMGetFineDM() 6071 @*/ 6072 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 6073 { 6074 PetscErrorCode ierr; 6075 6076 PetscFunctionBegin; 6077 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6078 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 6079 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 6080 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 6081 dm->fineMesh = fdm; 6082 PetscFunctionReturn(0); 6083 } 6084 6085 /*=== DMBoundary code ===*/ 6086 6087 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 6088 { 6089 PetscErrorCode ierr; 6090 6091 PetscFunctionBegin; 6092 ierr = PetscDSCopyBoundary(dm->prob,dmNew->prob);CHKERRQ(ierr); 6093 PetscFunctionReturn(0); 6094 } 6095 6096 /*@C 6097 DMAddBoundary - Add a boundary condition to the model 6098 6099 Input Parameters: 6100 + dm - The DM, with a PetscDS that matches the problem being constrained 6101 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6102 . name - The BC name 6103 . labelname - The label defining constrained points 6104 . field - The field to constrain 6105 . numcomps - The number of constrained field components 6106 . comps - An array of constrained component numbers 6107 . bcFunc - A pointwise function giving boundary values 6108 . numids - The number of DMLabel ids for constrained points 6109 . ids - An array of ids for constrained points 6110 - ctx - An optional user context for bcFunc 6111 6112 Options Database Keys: 6113 + -bc_<boundary name> <num> - Overrides the boundary ids 6114 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6115 6116 Level: developer 6117 6118 .seealso: DMGetBoundary() 6119 @*/ 6120 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) 6121 { 6122 PetscErrorCode ierr; 6123 6124 PetscFunctionBegin; 6125 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6126 ierr = PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);CHKERRQ(ierr); 6127 PetscFunctionReturn(0); 6128 } 6129 6130 /*@ 6131 DMGetNumBoundary - Get the number of registered BC 6132 6133 Input Parameters: 6134 . dm - The mesh object 6135 6136 Output Parameters: 6137 . numBd - The number of BC 6138 6139 Level: intermediate 6140 6141 .seealso: DMAddBoundary(), DMGetBoundary() 6142 @*/ 6143 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 6144 { 6145 PetscErrorCode ierr; 6146 6147 PetscFunctionBegin; 6148 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6149 ierr = PetscDSGetNumBoundary(dm->prob,numBd);CHKERRQ(ierr); 6150 PetscFunctionReturn(0); 6151 } 6152 6153 /*@C 6154 DMGetBoundary - Get a model boundary condition 6155 6156 Input Parameters: 6157 + dm - The mesh object 6158 - bd - The BC number 6159 6160 Output Parameters: 6161 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6162 . name - The BC name 6163 . labelname - The label defining constrained points 6164 . field - The field to constrain 6165 . numcomps - The number of constrained field components 6166 . comps - An array of constrained component numbers 6167 . bcFunc - A pointwise function giving boundary values 6168 . numids - The number of DMLabel ids for constrained points 6169 . ids - An array of ids for constrained points 6170 - ctx - An optional user context for bcFunc 6171 6172 Options Database Keys: 6173 + -bc_<boundary name> <num> - Overrides the boundary ids 6174 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6175 6176 Level: developer 6177 6178 .seealso: DMAddBoundary() 6179 @*/ 6180 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) 6181 { 6182 PetscErrorCode ierr; 6183 6184 PetscFunctionBegin; 6185 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6186 ierr = PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);CHKERRQ(ierr); 6187 PetscFunctionReturn(0); 6188 } 6189 6190 static PetscErrorCode DMPopulateBoundary(DM dm) 6191 { 6192 DMBoundary *lastnext; 6193 DSBoundary dsbound; 6194 PetscErrorCode ierr; 6195 6196 PetscFunctionBegin; 6197 dsbound = dm->prob->boundary; 6198 if (dm->boundary) { 6199 DMBoundary next = dm->boundary; 6200 6201 /* quick check to see if the PetscDS has changed */ 6202 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 6203 /* the PetscDS has changed: tear down and rebuild */ 6204 while (next) { 6205 DMBoundary b = next; 6206 6207 next = b->next; 6208 ierr = PetscFree(b);CHKERRQ(ierr); 6209 } 6210 dm->boundary = NULL; 6211 } 6212 6213 lastnext = &(dm->boundary); 6214 while (dsbound) { 6215 DMBoundary dmbound; 6216 6217 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 6218 dmbound->dsboundary = dsbound; 6219 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 6220 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 6221 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 6222 *lastnext = dmbound; 6223 lastnext = &(dmbound->next); 6224 dsbound = dsbound->next; 6225 } 6226 PetscFunctionReturn(0); 6227 } 6228 6229 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 6230 { 6231 DMBoundary b; 6232 PetscErrorCode ierr; 6233 6234 PetscFunctionBegin; 6235 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6236 PetscValidPointer(isBd, 3); 6237 *isBd = PETSC_FALSE; 6238 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 6239 b = dm->boundary; 6240 while (b && !(*isBd)) { 6241 DMLabel label = b->label; 6242 DSBoundary dsb = b->dsboundary; 6243 6244 if (label) { 6245 PetscInt i; 6246 6247 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 6248 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 6249 } 6250 } 6251 b = b->next; 6252 } 6253 PetscFunctionReturn(0); 6254 } 6255 6256 /*@C 6257 DMProjectFunction - This projects the given function into the function space provided. 6258 6259 Input Parameters: 6260 + dm - The DM 6261 . time - The time 6262 . funcs - The coordinate functions to evaluate, one per field 6263 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6264 - mode - The insertion mode for values 6265 6266 Output Parameter: 6267 . X - vector 6268 6269 Calling sequence of func: 6270 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6271 6272 + dim - The spatial dimension 6273 . x - The coordinates 6274 . Nf - The number of fields 6275 . u - The output field values 6276 - ctx - optional user-defined function context 6277 6278 Level: developer 6279 6280 .seealso: DMComputeL2Diff() 6281 @*/ 6282 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6283 { 6284 Vec localX; 6285 PetscErrorCode ierr; 6286 6287 PetscFunctionBegin; 6288 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6289 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6290 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6291 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6292 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6293 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6294 PetscFunctionReturn(0); 6295 } 6296 6297 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6298 { 6299 PetscErrorCode ierr; 6300 6301 PetscFunctionBegin; 6302 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6303 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6304 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6305 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6306 PetscFunctionReturn(0); 6307 } 6308 6309 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) 6310 { 6311 Vec localX; 6312 PetscErrorCode ierr; 6313 6314 PetscFunctionBegin; 6315 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6316 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6317 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6318 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6319 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6320 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6321 PetscFunctionReturn(0); 6322 } 6323 6324 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) 6325 { 6326 PetscErrorCode ierr; 6327 6328 PetscFunctionBegin; 6329 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6330 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6331 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6332 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6333 PetscFunctionReturn(0); 6334 } 6335 6336 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 6337 void (**funcs)(PetscInt, PetscInt, PetscInt, 6338 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6339 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6340 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6341 InsertMode mode, Vec localX) 6342 { 6343 PetscErrorCode ierr; 6344 6345 PetscFunctionBegin; 6346 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6347 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 6348 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 6349 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6350 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 6351 PetscFunctionReturn(0); 6352 } 6353 6354 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 6355 void (**funcs)(PetscInt, PetscInt, PetscInt, 6356 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6357 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6358 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6359 InsertMode mode, Vec localX) 6360 { 6361 PetscErrorCode ierr; 6362 6363 PetscFunctionBegin; 6364 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6365 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 6366 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 6367 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6368 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 6369 PetscFunctionReturn(0); 6370 } 6371 6372 /*@C 6373 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6374 6375 Input Parameters: 6376 + dm - The DM 6377 . time - The time 6378 . funcs - The functions to evaluate for each field component 6379 . ctxs - Optional array of contexts to pass to each function, or NULL. 6380 - X - The coefficient vector u_h, a global vector 6381 6382 Output Parameter: 6383 . diff - The diff ||u - u_h||_2 6384 6385 Level: developer 6386 6387 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6388 @*/ 6389 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6390 { 6391 PetscErrorCode ierr; 6392 6393 PetscFunctionBegin; 6394 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6395 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6396 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 6397 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6398 PetscFunctionReturn(0); 6399 } 6400 6401 /*@C 6402 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6403 6404 Input Parameters: 6405 + dm - The DM 6406 , time - The time 6407 . funcs - The gradient functions to evaluate for each field component 6408 . ctxs - Optional array of contexts to pass to each function, or NULL. 6409 . X - The coefficient vector u_h, a global vector 6410 - n - The vector to project along 6411 6412 Output Parameter: 6413 . diff - The diff ||(grad u - grad u_h) . n||_2 6414 6415 Level: developer 6416 6417 .seealso: DMProjectFunction(), DMComputeL2Diff() 6418 @*/ 6419 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) 6420 { 6421 PetscErrorCode ierr; 6422 6423 PetscFunctionBegin; 6424 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6425 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6426 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6427 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6428 PetscFunctionReturn(0); 6429 } 6430 6431 /*@C 6432 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 6433 6434 Input Parameters: 6435 + dm - The DM 6436 . time - The time 6437 . funcs - The functions to evaluate for each field component 6438 . ctxs - Optional array of contexts to pass to each function, or NULL. 6439 - X - The coefficient vector u_h, a global vector 6440 6441 Output Parameter: 6442 . diff - The array of differences, ||u^f - u^f_h||_2 6443 6444 Level: developer 6445 6446 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6447 @*/ 6448 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 6449 { 6450 PetscErrorCode ierr; 6451 6452 PetscFunctionBegin; 6453 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6454 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6455 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6456 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6457 PetscFunctionReturn(0); 6458 } 6459 6460 /*@C 6461 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 6462 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 6463 6464 Collective on dm 6465 6466 Input parameters: 6467 + dm - the pre-adaptation DM object 6468 - label - label with the flags 6469 6470 Output parameters: 6471 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 6472 6473 Level: intermediate 6474 6475 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 6476 @*/ 6477 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 6478 { 6479 PetscErrorCode ierr; 6480 6481 PetscFunctionBegin; 6482 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6483 PetscValidPointer(label,2); 6484 PetscValidPointer(dmAdapt,3); 6485 *dmAdapt = NULL; 6486 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 6487 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 6488 PetscFunctionReturn(0); 6489 } 6490 6491 /*@C 6492 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 6493 6494 Input Parameters: 6495 + dm - The DM object 6496 . metric - The metric to which the mesh is adapted, defined vertex-wise. 6497 - 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_". 6498 6499 Output Parameter: 6500 . dmAdapt - Pointer to the DM object containing the adapted mesh 6501 6502 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 6503 6504 Level: advanced 6505 6506 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 6507 @*/ 6508 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 6509 { 6510 PetscErrorCode ierr; 6511 6512 PetscFunctionBegin; 6513 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6514 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 6515 if (bdLabel) PetscValidPointer(bdLabel, 3); 6516 PetscValidPointer(dmAdapt, 4); 6517 *dmAdapt = NULL; 6518 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 6519 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 6520 PetscFunctionReturn(0); 6521 } 6522 6523 /*@C 6524 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 6525 6526 Not Collective 6527 6528 Input Parameter: 6529 . dm - The DM 6530 6531 Output Parameter: 6532 . nranks - the number of neighbours 6533 . ranks - the neighbors ranks 6534 6535 Notes: 6536 Do not free the array, it is freed when the DM is destroyed. 6537 6538 Level: beginner 6539 6540 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 6541 @*/ 6542 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 6543 { 6544 PetscErrorCode ierr; 6545 6546 PetscFunctionBegin; 6547 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6548 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 6549 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 6550 PetscFunctionReturn(0); 6551 } 6552 6553 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 6554 6555 /* 6556 Converts the input vector to a ghosted vector and then calls the standard coloring code. 6557 This has be a different function because it requires DM which is not defined in the Mat library 6558 */ 6559 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 6560 { 6561 PetscErrorCode ierr; 6562 6563 PetscFunctionBegin; 6564 if (coloring->ctype == IS_COLORING_LOCAL) { 6565 Vec x1local; 6566 DM dm; 6567 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6568 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 6569 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 6570 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6571 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6572 x1 = x1local; 6573 } 6574 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 6575 if (coloring->ctype == IS_COLORING_LOCAL) { 6576 DM dm; 6577 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6578 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 6579 } 6580 PetscFunctionReturn(0); 6581 } 6582 6583 /*@ 6584 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 6585 6586 Input Parameter: 6587 . coloring - the MatFDColoring object 6588 6589 Developer Notes: 6590 this routine exists because the PETSc Mat library does not know about the DM objects 6591 6592 Level: advanced 6593 6594 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 6595 @*/ 6596 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 6597 { 6598 PetscFunctionBegin; 6599 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 6600 PetscFunctionReturn(0); 6601 } 6602