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