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