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 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 4195 { 4196 PetscErrorCode ierr; 4197 4198 PetscFunctionBegin; 4199 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4200 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 4201 PetscFunctionReturn(0); 4202 } 4203 4204 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 4205 { 4206 PetscInt Nf, f; 4207 PetscErrorCode ierr; 4208 4209 PetscFunctionBegin; 4210 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4211 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 4212 for (f = Nf; f < numFields; ++f) { 4213 PetscContainer obj; 4214 4215 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 4216 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 4217 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 4218 } 4219 PetscFunctionReturn(0); 4220 } 4221 4222 /*@ 4223 DMGetField - Return the discretization object for a given DM field 4224 4225 Not collective 4226 4227 Input Parameters: 4228 + dm - The DM 4229 - f - The field number 4230 4231 Output Parameter: 4232 . field - The discretization object 4233 4234 Level: developer 4235 4236 .seealso: DMSetField() 4237 @*/ 4238 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 4239 { 4240 PetscErrorCode ierr; 4241 4242 PetscFunctionBegin; 4243 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4244 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 4245 PetscFunctionReturn(0); 4246 } 4247 4248 /*@ 4249 DMSetField - Set the discretization object for a given DM field 4250 4251 Logically collective on DM 4252 4253 Input Parameters: 4254 + dm - The DM 4255 . f - The field number 4256 - field - The discretization object 4257 4258 Level: developer 4259 4260 .seealso: DMGetField() 4261 @*/ 4262 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 4263 { 4264 PetscErrorCode ierr; 4265 4266 PetscFunctionBegin; 4267 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4268 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 4269 PetscFunctionReturn(0); 4270 } 4271 4272 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 4273 { 4274 DM dm_coord,dmc_coord; 4275 PetscErrorCode ierr; 4276 Vec coords,ccoords; 4277 Mat inject; 4278 PetscFunctionBegin; 4279 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4280 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 4281 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4282 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 4283 if (coords && !ccoords) { 4284 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 4285 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4286 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 4287 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 4288 ierr = MatDestroy(&inject);CHKERRQ(ierr); 4289 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 4290 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4291 } 4292 PetscFunctionReturn(0); 4293 } 4294 4295 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 4296 { 4297 DM dm_coord,subdm_coord; 4298 PetscErrorCode ierr; 4299 Vec coords,ccoords,clcoords; 4300 VecScatter *scat_i,*scat_g; 4301 PetscFunctionBegin; 4302 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4303 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 4304 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4305 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 4306 if (coords && !ccoords) { 4307 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 4308 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4309 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 4310 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 4311 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 4312 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4313 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4314 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4315 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4316 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 4317 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 4318 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 4319 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 4320 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4321 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 4322 ierr = PetscFree(scat_i);CHKERRQ(ierr); 4323 ierr = PetscFree(scat_g);CHKERRQ(ierr); 4324 } 4325 PetscFunctionReturn(0); 4326 } 4327 4328 /*@ 4329 DMGetDimension - Return the topological dimension of the DM 4330 4331 Not collective 4332 4333 Input Parameter: 4334 . dm - The DM 4335 4336 Output Parameter: 4337 . dim - The topological dimension 4338 4339 Level: beginner 4340 4341 .seealso: DMSetDimension(), DMCreate() 4342 @*/ 4343 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 4344 { 4345 PetscFunctionBegin; 4346 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4347 PetscValidPointer(dim, 2); 4348 *dim = dm->dim; 4349 PetscFunctionReturn(0); 4350 } 4351 4352 /*@ 4353 DMSetDimension - Set the topological dimension of the DM 4354 4355 Collective on dm 4356 4357 Input Parameters: 4358 + dm - The DM 4359 - dim - The topological dimension 4360 4361 Level: beginner 4362 4363 .seealso: DMGetDimension(), DMCreate() 4364 @*/ 4365 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 4366 { 4367 PetscErrorCode ierr; 4368 4369 PetscFunctionBegin; 4370 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4371 PetscValidLogicalCollectiveInt(dm, dim, 2); 4372 dm->dim = dim; 4373 if (dm->prob->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dim);CHKERRQ(ierr);} 4374 PetscFunctionReturn(0); 4375 } 4376 4377 /*@ 4378 DMGetDimPoints - Get the half-open interval for all points of a given dimension 4379 4380 Collective on DM 4381 4382 Input Parameters: 4383 + dm - the DM 4384 - dim - the dimension 4385 4386 Output Parameters: 4387 + pStart - The first point of the given dimension 4388 . pEnd - The first point following points of the given dimension 4389 4390 Note: 4391 The points are vertices in the Hasse diagram encoding the topology. This is explained in 4392 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 4393 then the interval is empty. 4394 4395 Level: intermediate 4396 4397 .keywords: point, Hasse Diagram, dimension 4398 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 4399 @*/ 4400 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4401 { 4402 PetscInt d; 4403 PetscErrorCode ierr; 4404 4405 PetscFunctionBegin; 4406 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4407 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 4408 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 4409 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 4410 PetscFunctionReturn(0); 4411 } 4412 4413 /*@ 4414 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 4415 4416 Collective on DM 4417 4418 Input Parameters: 4419 + dm - the DM 4420 - c - coordinate vector 4421 4422 Notes: 4423 The coordinates do include those for ghost points, which are in the local vector. 4424 4425 The vector c should be destroyed by the caller. 4426 4427 Level: intermediate 4428 4429 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4430 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4431 @*/ 4432 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 4433 { 4434 PetscErrorCode ierr; 4435 4436 PetscFunctionBegin; 4437 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4438 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4439 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4440 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4441 dm->coordinates = c; 4442 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4443 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4444 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4445 PetscFunctionReturn(0); 4446 } 4447 4448 /*@ 4449 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 4450 4451 Not collective 4452 4453 Input Parameters: 4454 + dm - the DM 4455 - c - coordinate vector 4456 4457 Notes: 4458 The coordinates of ghost points can be set using DMSetCoordinates() 4459 followed by DMGetCoordinatesLocal(). This is intended to enable the 4460 setting of ghost coordinates outside of the domain. 4461 4462 The vector c should be destroyed by the caller. 4463 4464 Level: intermediate 4465 4466 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4467 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 4468 @*/ 4469 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 4470 { 4471 PetscErrorCode ierr; 4472 4473 PetscFunctionBegin; 4474 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4475 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4476 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4477 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4478 4479 dm->coordinatesLocal = c; 4480 4481 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4482 PetscFunctionReturn(0); 4483 } 4484 4485 /*@ 4486 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 4487 4488 Collective on DM 4489 4490 Input Parameter: 4491 . dm - the DM 4492 4493 Output Parameter: 4494 . c - global coordinate vector 4495 4496 Note: 4497 This is a borrowed reference, so the user should NOT destroy this vector 4498 4499 Each process has only the local coordinates (does NOT have the ghost coordinates). 4500 4501 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4502 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4503 4504 Level: intermediate 4505 4506 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4507 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4508 @*/ 4509 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4510 { 4511 PetscErrorCode ierr; 4512 4513 PetscFunctionBegin; 4514 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4515 PetscValidPointer(c,2); 4516 if (!dm->coordinates && dm->coordinatesLocal) { 4517 DM cdm = NULL; 4518 4519 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4520 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4521 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4522 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4523 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4524 } 4525 *c = dm->coordinates; 4526 PetscFunctionReturn(0); 4527 } 4528 4529 /*@ 4530 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 4531 4532 Collective on DM 4533 4534 Input Parameter: 4535 . dm - the DM 4536 4537 Level: advanced 4538 4539 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4540 .seealso: DMGetCoordinatesLocalNoncollective() 4541 @*/ 4542 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 4543 { 4544 DM cdm = NULL; 4545 PetscErrorCode ierr; 4546 4547 PetscFunctionBegin; 4548 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4549 if (!dm->coordinatesLocal && dm->coordinates) { 4550 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4551 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4552 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4553 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4554 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4555 } 4556 PetscFunctionReturn(0); 4557 } 4558 4559 /*@ 4560 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4561 4562 Collective on DM 4563 4564 Input Parameter: 4565 . dm - the DM 4566 4567 Output Parameter: 4568 . c - coordinate vector 4569 4570 Note: 4571 This is a borrowed reference, so the user should NOT destroy this vector 4572 4573 Each process has the local and ghost coordinates 4574 4575 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4576 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4577 4578 Level: intermediate 4579 4580 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4581 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 4582 @*/ 4583 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4584 { 4585 PetscErrorCode ierr; 4586 4587 PetscFunctionBegin; 4588 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4589 PetscValidPointer(c,2); 4590 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 4591 *c = dm->coordinatesLocal; 4592 PetscFunctionReturn(0); 4593 } 4594 4595 /*@ 4596 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 4597 4598 Not collective 4599 4600 Input Parameter: 4601 . dm - the DM 4602 4603 Output Parameter: 4604 . c - coordinate vector 4605 4606 Level: advanced 4607 4608 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4609 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4610 @*/ 4611 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 4612 { 4613 PetscFunctionBegin; 4614 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4615 PetscValidPointer(c,2); 4616 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 4617 *c = dm->coordinatesLocal; 4618 PetscFunctionReturn(0); 4619 } 4620 4621 /*@ 4622 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 4623 4624 Not collective 4625 4626 Input Parameter: 4627 + dm - the DM 4628 - p - the IS of points whose coordinates will be returned 4629 4630 Output Parameter: 4631 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 4632 - pCoord - the Vec with coordinates of points in p 4633 4634 Note: 4635 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 4636 4637 This creates a new vector, so the user SHOULD destroy this vector 4638 4639 Each process has the local and ghost coordinates 4640 4641 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4642 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4643 4644 Level: advanced 4645 4646 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4647 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4648 @*/ 4649 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 4650 { 4651 PetscSection cs, newcs; 4652 Vec coords; 4653 const PetscScalar *arr; 4654 PetscScalar *newarr=NULL; 4655 PetscInt n; 4656 PetscErrorCode ierr; 4657 4658 PetscFunctionBegin; 4659 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4660 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 4661 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 4662 if (pCoord) PetscValidPointer(pCoord, 4); 4663 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 4664 if (!dm->coordinateDM || !dm->coordinateDM->defaultSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 4665 cs = dm->coordinateDM->defaultSection; 4666 coords = dm->coordinatesLocal; 4667 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 4668 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 4669 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 4670 if (pCoord) { 4671 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 4672 /* set array in two steps to mimic PETSC_OWN_POINTER */ 4673 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 4674 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 4675 } else { 4676 ierr = PetscFree(newarr);CHKERRQ(ierr); 4677 } 4678 if (pCoordSection) {*pCoordSection = newcs;} 4679 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 4680 PetscFunctionReturn(0); 4681 } 4682 4683 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 4684 { 4685 PetscErrorCode ierr; 4686 4687 PetscFunctionBegin; 4688 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4689 PetscValidPointer(field,2); 4690 if (!dm->coordinateField) { 4691 if (dm->ops->createcoordinatefield) { 4692 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 4693 } 4694 } 4695 *field = dm->coordinateField; 4696 PetscFunctionReturn(0); 4697 } 4698 4699 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 4700 { 4701 PetscErrorCode ierr; 4702 4703 PetscFunctionBegin; 4704 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4705 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 4706 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 4707 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 4708 dm->coordinateField = field; 4709 PetscFunctionReturn(0); 4710 } 4711 4712 /*@ 4713 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4714 4715 Collective on DM 4716 4717 Input Parameter: 4718 . dm - the DM 4719 4720 Output Parameter: 4721 . cdm - coordinate DM 4722 4723 Level: intermediate 4724 4725 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4726 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4727 @*/ 4728 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4729 { 4730 PetscErrorCode ierr; 4731 4732 PetscFunctionBegin; 4733 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4734 PetscValidPointer(cdm,2); 4735 if (!dm->coordinateDM) { 4736 DM cdm; 4737 4738 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4739 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 4740 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 4741 * until the call to CreateCoordinateDM) */ 4742 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4743 dm->coordinateDM = cdm; 4744 } 4745 *cdm = dm->coordinateDM; 4746 PetscFunctionReturn(0); 4747 } 4748 4749 /*@ 4750 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4751 4752 Logically Collective on DM 4753 4754 Input Parameters: 4755 + dm - the DM 4756 - cdm - coordinate DM 4757 4758 Level: intermediate 4759 4760 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4761 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4762 @*/ 4763 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4764 { 4765 PetscErrorCode ierr; 4766 4767 PetscFunctionBegin; 4768 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4769 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4770 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 4771 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4772 dm->coordinateDM = cdm; 4773 PetscFunctionReturn(0); 4774 } 4775 4776 /*@ 4777 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4778 4779 Not Collective 4780 4781 Input Parameter: 4782 . dm - The DM object 4783 4784 Output Parameter: 4785 . dim - The embedding dimension 4786 4787 Level: intermediate 4788 4789 .keywords: mesh, coordinates 4790 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetSection(), DMSetSection() 4791 @*/ 4792 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4793 { 4794 PetscFunctionBegin; 4795 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4796 PetscValidPointer(dim, 2); 4797 if (dm->dimEmbed == PETSC_DEFAULT) { 4798 dm->dimEmbed = dm->dim; 4799 } 4800 *dim = dm->dimEmbed; 4801 PetscFunctionReturn(0); 4802 } 4803 4804 /*@ 4805 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4806 4807 Not Collective 4808 4809 Input Parameters: 4810 + dm - The DM object 4811 - dim - The embedding dimension 4812 4813 Level: intermediate 4814 4815 .keywords: mesh, coordinates 4816 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetSection(), DMSetSection() 4817 @*/ 4818 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4819 { 4820 PetscErrorCode ierr; 4821 4822 PetscFunctionBegin; 4823 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4824 dm->dimEmbed = dim; 4825 ierr = PetscDSSetCoordinateDimension(dm->prob, dm->dimEmbed);CHKERRQ(ierr); 4826 PetscFunctionReturn(0); 4827 } 4828 4829 /*@ 4830 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4831 4832 Collective on DM 4833 4834 Input Parameter: 4835 . dm - The DM object 4836 4837 Output Parameter: 4838 . section - The PetscSection object 4839 4840 Level: intermediate 4841 4842 .keywords: mesh, coordinates 4843 .seealso: DMGetCoordinateDM(), DMGetSection(), DMSetSection() 4844 @*/ 4845 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4846 { 4847 DM cdm; 4848 PetscErrorCode ierr; 4849 4850 PetscFunctionBegin; 4851 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4852 PetscValidPointer(section, 2); 4853 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4854 ierr = DMGetSection(cdm, section);CHKERRQ(ierr); 4855 PetscFunctionReturn(0); 4856 } 4857 4858 /*@ 4859 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4860 4861 Not Collective 4862 4863 Input Parameters: 4864 + dm - The DM object 4865 . dim - The embedding dimension, or PETSC_DETERMINE 4866 - section - The PetscSection object 4867 4868 Level: intermediate 4869 4870 .keywords: mesh, coordinates 4871 .seealso: DMGetCoordinateSection(), DMGetSection(), DMSetSection() 4872 @*/ 4873 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4874 { 4875 DM cdm; 4876 PetscErrorCode ierr; 4877 4878 PetscFunctionBegin; 4879 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4880 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4881 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4882 ierr = DMSetSection(cdm, section);CHKERRQ(ierr); 4883 if (dim == PETSC_DETERMINE) { 4884 PetscInt d = PETSC_DEFAULT; 4885 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4886 4887 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4888 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4889 pStart = PetscMax(vStart, pStart); 4890 pEnd = PetscMin(vEnd, pEnd); 4891 for (v = pStart; v < pEnd; ++v) { 4892 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4893 if (dd) {d = dd; break;} 4894 } 4895 if (d < 0) d = PETSC_DEFAULT; 4896 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4897 } 4898 PetscFunctionReturn(0); 4899 } 4900 4901 /*@C 4902 DMGetPeriodicity - Get the description of mesh periodicity 4903 4904 Input Parameters: 4905 . dm - The DM object 4906 4907 Output Parameters: 4908 + per - Whether the DM is periodic or not 4909 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4910 . L - If we assume the mesh is a torus, this is the length of each coordinate 4911 - bd - This describes the type of periodicity in each topological dimension 4912 4913 Level: developer 4914 4915 .seealso: DMGetPeriodicity() 4916 @*/ 4917 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4918 { 4919 PetscFunctionBegin; 4920 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4921 if (per) *per = dm->periodic; 4922 if (L) *L = dm->L; 4923 if (maxCell) *maxCell = dm->maxCell; 4924 if (bd) *bd = dm->bdtype; 4925 PetscFunctionReturn(0); 4926 } 4927 4928 /*@C 4929 DMSetPeriodicity - Set the description of mesh periodicity 4930 4931 Input Parameters: 4932 + dm - The DM object 4933 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 4934 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4935 . L - If we assume the mesh is a torus, this is the length of each coordinate 4936 - bd - This describes the type of periodicity in each topological dimension 4937 4938 Level: developer 4939 4940 .seealso: DMGetPeriodicity() 4941 @*/ 4942 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4943 { 4944 PetscInt dim, d; 4945 PetscErrorCode ierr; 4946 4947 PetscFunctionBegin; 4948 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4949 PetscValidLogicalCollectiveBool(dm,per,2); 4950 if (maxCell) { 4951 PetscValidPointer(maxCell,3); 4952 PetscValidPointer(L,4); 4953 PetscValidPointer(bd,5); 4954 } 4955 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4956 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4957 if (maxCell) { 4958 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4959 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4960 } 4961 dm->periodic = per; 4962 PetscFunctionReturn(0); 4963 } 4964 4965 /*@ 4966 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. 4967 4968 Input Parameters: 4969 + dm - The DM 4970 . in - The input coordinate point (dim numbers) 4971 - endpoint - Include the endpoint L_i 4972 4973 Output Parameter: 4974 . out - The localized coordinate point 4975 4976 Level: developer 4977 4978 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4979 @*/ 4980 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 4981 { 4982 PetscInt dim, d; 4983 PetscErrorCode ierr; 4984 4985 PetscFunctionBegin; 4986 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 4987 if (!dm->maxCell) { 4988 for (d = 0; d < dim; ++d) out[d] = in[d]; 4989 } else { 4990 if (endpoint) { 4991 for (d = 0; d < dim; ++d) { 4992 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)) { 4993 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 4994 } else { 4995 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 4996 } 4997 } 4998 } else { 4999 for (d = 0; d < dim; ++d) { 5000 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 5001 } 5002 } 5003 } 5004 PetscFunctionReturn(0); 5005 } 5006 5007 /* 5008 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. 5009 5010 Input Parameters: 5011 + dm - The DM 5012 . dim - The spatial dimension 5013 . anchor - The anchor point, the input point can be no more than maxCell away from it 5014 - in - The input coordinate point (dim numbers) 5015 5016 Output Parameter: 5017 . out - The localized coordinate point 5018 5019 Level: developer 5020 5021 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 5022 5023 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 5024 */ 5025 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 5026 { 5027 PetscInt d; 5028 5029 PetscFunctionBegin; 5030 if (!dm->maxCell) { 5031 for (d = 0; d < dim; ++d) out[d] = in[d]; 5032 } else { 5033 for (d = 0; d < dim; ++d) { 5034 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 5035 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5036 } else { 5037 out[d] = in[d]; 5038 } 5039 } 5040 } 5041 PetscFunctionReturn(0); 5042 } 5043 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 5044 { 5045 PetscInt d; 5046 5047 PetscFunctionBegin; 5048 if (!dm->maxCell) { 5049 for (d = 0; d < dim; ++d) out[d] = in[d]; 5050 } else { 5051 for (d = 0; d < dim; ++d) { 5052 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 5053 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5054 } else { 5055 out[d] = in[d]; 5056 } 5057 } 5058 } 5059 PetscFunctionReturn(0); 5060 } 5061 5062 /* 5063 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. 5064 5065 Input Parameters: 5066 + dm - The DM 5067 . dim - The spatial dimension 5068 . anchor - The anchor point, the input point can be no more than maxCell away from it 5069 . in - The input coordinate delta (dim numbers) 5070 - out - The input coordinate point (dim numbers) 5071 5072 Output Parameter: 5073 . out - The localized coordinate in + out 5074 5075 Level: developer 5076 5077 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 5078 5079 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 5080 */ 5081 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 5082 { 5083 PetscInt d; 5084 5085 PetscFunctionBegin; 5086 if (!dm->maxCell) { 5087 for (d = 0; d < dim; ++d) out[d] += in[d]; 5088 } else { 5089 for (d = 0; d < dim; ++d) { 5090 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 5091 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5092 } else { 5093 out[d] += in[d]; 5094 } 5095 } 5096 } 5097 PetscFunctionReturn(0); 5098 } 5099 5100 /*@ 5101 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 5102 5103 Not collective 5104 5105 Input Parameter: 5106 . dm - The DM 5107 5108 Output Parameter: 5109 areLocalized - True if localized 5110 5111 Level: developer 5112 5113 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 5114 @*/ 5115 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 5116 { 5117 DM cdm; 5118 PetscSection coordSection; 5119 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 5120 PetscBool isPlex, alreadyLocalized; 5121 PetscErrorCode ierr; 5122 5123 PetscFunctionBegin; 5124 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5125 PetscValidPointer(areLocalized, 2); 5126 *areLocalized = PETSC_FALSE; 5127 5128 /* We need some generic way of refering to cells/vertices */ 5129 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5130 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5131 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 5132 if (!isPlex) SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 5133 5134 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5135 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 5136 alreadyLocalized = PETSC_FALSE; 5137 for (c = cStart; c < cEnd; ++c) { 5138 if (c < sStart || c >= sEnd) continue; 5139 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 5140 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 5141 } 5142 *areLocalized = alreadyLocalized; 5143 PetscFunctionReturn(0); 5144 } 5145 5146 /*@ 5147 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 5148 5149 Collective on dm 5150 5151 Input Parameter: 5152 . dm - The DM 5153 5154 Output Parameter: 5155 areLocalized - True if localized 5156 5157 Level: developer 5158 5159 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 5160 @*/ 5161 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 5162 { 5163 PetscBool localized; 5164 PetscErrorCode ierr; 5165 5166 PetscFunctionBegin; 5167 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5168 PetscValidPointer(areLocalized, 2); 5169 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 5170 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 5171 PetscFunctionReturn(0); 5172 } 5173 5174 /*@ 5175 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 5176 5177 Collective on dm 5178 5179 Input Parameter: 5180 . dm - The DM 5181 5182 Level: developer 5183 5184 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 5185 @*/ 5186 PetscErrorCode DMLocalizeCoordinates(DM dm) 5187 { 5188 DM cdm; 5189 PetscSection coordSection, cSection; 5190 Vec coordinates, cVec; 5191 PetscScalar *coords, *coords2, *anchor, *localized; 5192 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 5193 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 5194 PetscInt maxHeight = 0, h; 5195 PetscInt *pStart = NULL, *pEnd = NULL; 5196 PetscErrorCode ierr; 5197 5198 PetscFunctionBegin; 5199 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5200 if (!dm->periodic) PetscFunctionReturn(0); 5201 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 5202 if (alreadyLocalized) PetscFunctionReturn(0); 5203 5204 /* We need some generic way of refering to cells/vertices */ 5205 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5206 { 5207 PetscBool isplex; 5208 5209 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 5210 if (isplex) { 5211 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5212 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 5213 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 5214 pEnd = &pStart[maxHeight + 1]; 5215 newStart = vStart; 5216 newEnd = vEnd; 5217 for (h = 0; h <= maxHeight; h++) { 5218 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 5219 newStart = PetscMin(newStart,pStart[h]); 5220 newEnd = PetscMax(newEnd,pEnd[h]); 5221 } 5222 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 5223 } 5224 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5225 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 5226 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5227 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 5228 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 5229 5230 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 5231 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 5232 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 5233 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 5234 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 5235 5236 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 5237 localized = &anchor[bs]; 5238 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 5239 for (h = 0; h <= maxHeight; h++) { 5240 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 5241 5242 for (c = cStart; c < cEnd; ++c) { 5243 PetscScalar *cellCoords = NULL; 5244 PetscInt b; 5245 5246 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 5247 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5248 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 5249 for (d = 0; d < dof/bs; ++d) { 5250 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 5251 for (b = 0; b < bs; b++) { 5252 if (cellCoords[d*bs + b] != localized[b]) break; 5253 } 5254 if (b < bs) break; 5255 } 5256 if (d < dof/bs) { 5257 if (c >= sStart && c < sEnd) { 5258 PetscInt cdof; 5259 5260 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 5261 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 5262 } 5263 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 5264 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 5265 } 5266 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5267 } 5268 } 5269 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 5270 if (alreadyLocalizedGlobal) { 5271 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 5272 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 5273 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 5274 PetscFunctionReturn(0); 5275 } 5276 for (v = vStart; v < vEnd; ++v) { 5277 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 5278 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 5279 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 5280 } 5281 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 5282 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 5283 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 5284 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 5285 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 5286 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 5287 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 5288 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 5289 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 5290 for (v = vStart; v < vEnd; ++v) { 5291 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 5292 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5293 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 5294 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 5295 } 5296 for (h = 0; h <= maxHeight; h++) { 5297 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 5298 5299 for (c = cStart; c < cEnd; ++c) { 5300 PetscScalar *cellCoords = NULL; 5301 PetscInt b, cdof; 5302 5303 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 5304 if (!cdof) continue; 5305 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5306 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 5307 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 5308 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 5309 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 5310 } 5311 } 5312 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 5313 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 5314 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 5315 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 5316 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 5317 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 5318 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 5319 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 5320 PetscFunctionReturn(0); 5321 } 5322 5323 /*@ 5324 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 5325 5326 Collective on Vec v (see explanation below) 5327 5328 Input Parameters: 5329 + dm - The DM 5330 . v - The Vec of points 5331 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 5332 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 5333 5334 Output Parameter: 5335 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 5336 - cells - The PetscSF containing the ranks and local indices of the containing points. 5337 5338 5339 Level: developer 5340 5341 Notes: 5342 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 5343 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 5344 5345 If *cellSF is NULL on input, a PetscSF will be created. 5346 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 5347 5348 An array that maps each point to its containing cell can be obtained with 5349 5350 $ const PetscSFNode *cells; 5351 $ PetscInt nFound; 5352 $ const PetscInt *found; 5353 $ 5354 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 5355 5356 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 5357 the index of the cell in its rank's local numbering. 5358 5359 .keywords: point location, mesh 5360 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 5361 @*/ 5362 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 5363 { 5364 PetscErrorCode ierr; 5365 5366 PetscFunctionBegin; 5367 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5368 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 5369 PetscValidPointer(cellSF,4); 5370 if (*cellSF) { 5371 PetscMPIInt result; 5372 5373 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 5374 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 5375 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 5376 } else { 5377 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 5378 } 5379 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 5380 if (dm->ops->locatepoints) { 5381 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 5382 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 5383 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 5384 PetscFunctionReturn(0); 5385 } 5386 5387 /*@ 5388 DMGetOutputDM - Retrieve the DM associated with the layout for output 5389 5390 Collective on dm 5391 5392 Input Parameter: 5393 . dm - The original DM 5394 5395 Output Parameter: 5396 . odm - The DM which provides the layout for output 5397 5398 Level: intermediate 5399 5400 .seealso: VecView(), DMGetGlobalSection() 5401 @*/ 5402 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 5403 { 5404 PetscSection section; 5405 PetscBool hasConstraints, ghasConstraints; 5406 PetscErrorCode ierr; 5407 5408 PetscFunctionBegin; 5409 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5410 PetscValidPointer(odm,2); 5411 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 5412 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 5413 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 5414 if (!ghasConstraints) { 5415 *odm = dm; 5416 PetscFunctionReturn(0); 5417 } 5418 if (!dm->dmBC) { 5419 PetscDS ds; 5420 PetscSection newSection, gsection; 5421 PetscSF sf; 5422 5423 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 5424 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5425 ierr = DMSetDS(dm->dmBC, ds);CHKERRQ(ierr); 5426 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 5427 ierr = DMSetSection(dm->dmBC, newSection);CHKERRQ(ierr); 5428 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 5429 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 5430 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 5431 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 5432 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 5433 } 5434 *odm = dm->dmBC; 5435 PetscFunctionReturn(0); 5436 } 5437 5438 /*@ 5439 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 5440 5441 Input Parameter: 5442 . dm - The original DM 5443 5444 Output Parameters: 5445 + num - The output sequence number 5446 - val - The output sequence value 5447 5448 Level: intermediate 5449 5450 Note: This is intended for output that should appear in sequence, for instance 5451 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5452 5453 .seealso: VecView() 5454 @*/ 5455 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 5456 { 5457 PetscFunctionBegin; 5458 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5459 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 5460 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 5461 PetscFunctionReturn(0); 5462 } 5463 5464 /*@ 5465 DMSetOutputSequenceNumber - Set the sequence number/value for output 5466 5467 Input Parameters: 5468 + dm - The original DM 5469 . num - The output sequence number 5470 - val - The output sequence value 5471 5472 Level: intermediate 5473 5474 Note: This is intended for output that should appear in sequence, for instance 5475 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5476 5477 .seealso: VecView() 5478 @*/ 5479 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 5480 { 5481 PetscFunctionBegin; 5482 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5483 dm->outputSequenceNum = num; 5484 dm->outputSequenceVal = val; 5485 PetscFunctionReturn(0); 5486 } 5487 5488 /*@C 5489 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 5490 5491 Input Parameters: 5492 + dm - The original DM 5493 . name - The sequence name 5494 - num - The output sequence number 5495 5496 Output Parameter: 5497 . val - The output sequence value 5498 5499 Level: intermediate 5500 5501 Note: This is intended for output that should appear in sequence, for instance 5502 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5503 5504 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 5505 @*/ 5506 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 5507 { 5508 PetscBool ishdf5; 5509 PetscErrorCode ierr; 5510 5511 PetscFunctionBegin; 5512 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5513 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 5514 PetscValidPointer(val,4); 5515 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 5516 if (ishdf5) { 5517 #if defined(PETSC_HAVE_HDF5) 5518 PetscScalar value; 5519 5520 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 5521 *val = PetscRealPart(value); 5522 #endif 5523 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 5524 PetscFunctionReturn(0); 5525 } 5526 5527 /*@ 5528 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 5529 5530 Not collective 5531 5532 Input Parameter: 5533 . dm - The DM 5534 5535 Output Parameter: 5536 . useNatural - The flag to build the mapping to a natural order during distribution 5537 5538 Level: beginner 5539 5540 .seealso: DMSetUseNatural(), DMCreate() 5541 @*/ 5542 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 5543 { 5544 PetscFunctionBegin; 5545 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5546 PetscValidPointer(useNatural, 2); 5547 *useNatural = dm->useNatural; 5548 PetscFunctionReturn(0); 5549 } 5550 5551 /*@ 5552 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 5553 5554 Collective on dm 5555 5556 Input Parameters: 5557 + dm - The DM 5558 - useNatural - The flag to build the mapping to a natural order during distribution 5559 5560 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 5561 5562 Level: beginner 5563 5564 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 5565 @*/ 5566 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 5567 { 5568 PetscFunctionBegin; 5569 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5570 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 5571 dm->useNatural = useNatural; 5572 PetscFunctionReturn(0); 5573 } 5574 5575 5576 /*@C 5577 DMCreateLabel - Create a label of the given name if it does not already exist 5578 5579 Not Collective 5580 5581 Input Parameters: 5582 + dm - The DM object 5583 - name - The label name 5584 5585 Level: intermediate 5586 5587 .keywords: mesh 5588 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5589 @*/ 5590 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 5591 { 5592 DMLabelLink next = dm->labels->next; 5593 PetscBool flg = PETSC_FALSE; 5594 const char *lname; 5595 PetscErrorCode ierr; 5596 5597 PetscFunctionBegin; 5598 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5599 PetscValidCharPointer(name, 2); 5600 while (next) { 5601 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 5602 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 5603 if (flg) break; 5604 next = next->next; 5605 } 5606 if (!flg) { 5607 DMLabelLink tmpLabel; 5608 5609 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5610 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &tmpLabel->label);CHKERRQ(ierr); 5611 tmpLabel->output = PETSC_TRUE; 5612 tmpLabel->next = dm->labels->next; 5613 dm->labels->next = tmpLabel; 5614 } 5615 PetscFunctionReturn(0); 5616 } 5617 5618 /*@C 5619 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 5620 5621 Not Collective 5622 5623 Input Parameters: 5624 + dm - The DM object 5625 . name - The label name 5626 - point - The mesh point 5627 5628 Output Parameter: 5629 . value - The label value for this point, or -1 if the point is not in the label 5630 5631 Level: beginner 5632 5633 .keywords: mesh 5634 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 5635 @*/ 5636 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 5637 { 5638 DMLabel label; 5639 PetscErrorCode ierr; 5640 5641 PetscFunctionBegin; 5642 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5643 PetscValidCharPointer(name, 2); 5644 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5645 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 5646 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5647 PetscFunctionReturn(0); 5648 } 5649 5650 /*@C 5651 DMSetLabelValue - Add a point to a Sieve Label with given value 5652 5653 Not Collective 5654 5655 Input Parameters: 5656 + dm - The DM object 5657 . name - The label name 5658 . point - The mesh point 5659 - value - The label value for this point 5660 5661 Output Parameter: 5662 5663 Level: beginner 5664 5665 .keywords: mesh 5666 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5667 @*/ 5668 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5669 { 5670 DMLabel label; 5671 PetscErrorCode ierr; 5672 5673 PetscFunctionBegin; 5674 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5675 PetscValidCharPointer(name, 2); 5676 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5677 if (!label) { 5678 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5679 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5680 } 5681 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5682 PetscFunctionReturn(0); 5683 } 5684 5685 /*@C 5686 DMClearLabelValue - Remove a point from a Sieve Label with given value 5687 5688 Not Collective 5689 5690 Input Parameters: 5691 + dm - The DM object 5692 . name - The label name 5693 . point - The mesh point 5694 - value - The label value for this point 5695 5696 Output Parameter: 5697 5698 Level: beginner 5699 5700 .keywords: mesh 5701 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5702 @*/ 5703 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5704 { 5705 DMLabel label; 5706 PetscErrorCode ierr; 5707 5708 PetscFunctionBegin; 5709 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5710 PetscValidCharPointer(name, 2); 5711 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5712 if (!label) PetscFunctionReturn(0); 5713 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5714 PetscFunctionReturn(0); 5715 } 5716 5717 /*@C 5718 DMGetLabelSize - Get the number of different integer ids in a Label 5719 5720 Not Collective 5721 5722 Input Parameters: 5723 + dm - The DM object 5724 - name - The label name 5725 5726 Output Parameter: 5727 . size - The number of different integer ids, or 0 if the label does not exist 5728 5729 Level: beginner 5730 5731 .keywords: mesh 5732 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 5733 @*/ 5734 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5735 { 5736 DMLabel label; 5737 PetscErrorCode ierr; 5738 5739 PetscFunctionBegin; 5740 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5741 PetscValidCharPointer(name, 2); 5742 PetscValidPointer(size, 3); 5743 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5744 *size = 0; 5745 if (!label) PetscFunctionReturn(0); 5746 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5747 PetscFunctionReturn(0); 5748 } 5749 5750 /*@C 5751 DMGetLabelIdIS - Get the integer ids in a label 5752 5753 Not Collective 5754 5755 Input Parameters: 5756 + mesh - The DM object 5757 - name - The label name 5758 5759 Output Parameter: 5760 . ids - The integer ids, or NULL if the label does not exist 5761 5762 Level: beginner 5763 5764 .keywords: mesh 5765 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5766 @*/ 5767 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5768 { 5769 DMLabel label; 5770 PetscErrorCode ierr; 5771 5772 PetscFunctionBegin; 5773 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5774 PetscValidCharPointer(name, 2); 5775 PetscValidPointer(ids, 3); 5776 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5777 *ids = NULL; 5778 if (label) { 5779 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5780 } else { 5781 /* returning an empty IS */ 5782 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 5783 } 5784 PetscFunctionReturn(0); 5785 } 5786 5787 /*@C 5788 DMGetStratumSize - Get the number of points in a label stratum 5789 5790 Not Collective 5791 5792 Input Parameters: 5793 + dm - The DM object 5794 . name - The label name 5795 - value - The stratum value 5796 5797 Output Parameter: 5798 . size - The stratum size 5799 5800 Level: beginner 5801 5802 .keywords: mesh 5803 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5804 @*/ 5805 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5806 { 5807 DMLabel label; 5808 PetscErrorCode ierr; 5809 5810 PetscFunctionBegin; 5811 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5812 PetscValidCharPointer(name, 2); 5813 PetscValidPointer(size, 4); 5814 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5815 *size = 0; 5816 if (!label) PetscFunctionReturn(0); 5817 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5818 PetscFunctionReturn(0); 5819 } 5820 5821 /*@C 5822 DMGetStratumIS - Get the points in a label stratum 5823 5824 Not Collective 5825 5826 Input Parameters: 5827 + dm - The DM object 5828 . name - The label name 5829 - value - The stratum value 5830 5831 Output Parameter: 5832 . points - The stratum points, or NULL if the label does not exist or does not have that value 5833 5834 Level: beginner 5835 5836 .keywords: mesh 5837 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5838 @*/ 5839 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5840 { 5841 DMLabel label; 5842 PetscErrorCode ierr; 5843 5844 PetscFunctionBegin; 5845 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5846 PetscValidCharPointer(name, 2); 5847 PetscValidPointer(points, 4); 5848 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5849 *points = NULL; 5850 if (!label) PetscFunctionReturn(0); 5851 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5852 PetscFunctionReturn(0); 5853 } 5854 5855 /*@C 5856 DMSetStratumIS - Set the points in a label stratum 5857 5858 Not Collective 5859 5860 Input Parameters: 5861 + dm - The DM object 5862 . name - The label name 5863 . value - The stratum value 5864 - points - The stratum points 5865 5866 Level: beginner 5867 5868 .keywords: mesh 5869 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 5870 @*/ 5871 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 5872 { 5873 DMLabel label; 5874 PetscErrorCode ierr; 5875 5876 PetscFunctionBegin; 5877 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5878 PetscValidCharPointer(name, 2); 5879 PetscValidPointer(points, 4); 5880 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5881 if (!label) PetscFunctionReturn(0); 5882 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 5883 PetscFunctionReturn(0); 5884 } 5885 5886 /*@C 5887 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 5888 5889 Not Collective 5890 5891 Input Parameters: 5892 + dm - The DM object 5893 . name - The label name 5894 - value - The label value for this point 5895 5896 Output Parameter: 5897 5898 Level: beginner 5899 5900 .keywords: mesh 5901 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 5902 @*/ 5903 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 5904 { 5905 DMLabel label; 5906 PetscErrorCode ierr; 5907 5908 PetscFunctionBegin; 5909 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5910 PetscValidCharPointer(name, 2); 5911 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5912 if (!label) PetscFunctionReturn(0); 5913 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 5914 PetscFunctionReturn(0); 5915 } 5916 5917 /*@ 5918 DMGetNumLabels - Return the number of labels defined by the mesh 5919 5920 Not Collective 5921 5922 Input Parameter: 5923 . dm - The DM object 5924 5925 Output Parameter: 5926 . numLabels - the number of Labels 5927 5928 Level: intermediate 5929 5930 .keywords: mesh 5931 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5932 @*/ 5933 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 5934 { 5935 DMLabelLink next = dm->labels->next; 5936 PetscInt n = 0; 5937 5938 PetscFunctionBegin; 5939 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5940 PetscValidPointer(numLabels, 2); 5941 while (next) {++n; next = next->next;} 5942 *numLabels = n; 5943 PetscFunctionReturn(0); 5944 } 5945 5946 /*@C 5947 DMGetLabelName - Return the name of nth label 5948 5949 Not Collective 5950 5951 Input Parameters: 5952 + dm - The DM object 5953 - n - the label number 5954 5955 Output Parameter: 5956 . name - the label name 5957 5958 Level: intermediate 5959 5960 .keywords: mesh 5961 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5962 @*/ 5963 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 5964 { 5965 DMLabelLink next = dm->labels->next; 5966 PetscInt l = 0; 5967 PetscErrorCode ierr; 5968 5969 PetscFunctionBegin; 5970 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5971 PetscValidPointer(name, 3); 5972 while (next) { 5973 if (l == n) { 5974 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 5975 PetscFunctionReturn(0); 5976 } 5977 ++l; 5978 next = next->next; 5979 } 5980 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5981 } 5982 5983 /*@C 5984 DMHasLabel - Determine whether the mesh has a label of a given name 5985 5986 Not Collective 5987 5988 Input Parameters: 5989 + dm - The DM object 5990 - name - The label name 5991 5992 Output Parameter: 5993 . hasLabel - PETSC_TRUE if the label is present 5994 5995 Level: intermediate 5996 5997 .keywords: mesh 5998 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5999 @*/ 6000 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 6001 { 6002 DMLabelLink next = dm->labels->next; 6003 const char *lname; 6004 PetscErrorCode ierr; 6005 6006 PetscFunctionBegin; 6007 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6008 PetscValidCharPointer(name, 2); 6009 PetscValidPointer(hasLabel, 3); 6010 *hasLabel = PETSC_FALSE; 6011 while (next) { 6012 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6013 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 6014 if (*hasLabel) break; 6015 next = next->next; 6016 } 6017 PetscFunctionReturn(0); 6018 } 6019 6020 /*@C 6021 DMGetLabel - Return the label of a given name, or NULL 6022 6023 Not Collective 6024 6025 Input Parameters: 6026 + dm - The DM object 6027 - name - The label name 6028 6029 Output Parameter: 6030 . label - The DMLabel, or NULL if the label is absent 6031 6032 Level: intermediate 6033 6034 .keywords: mesh 6035 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6036 @*/ 6037 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 6038 { 6039 DMLabelLink next = dm->labels->next; 6040 PetscBool hasLabel; 6041 const char *lname; 6042 PetscErrorCode ierr; 6043 6044 PetscFunctionBegin; 6045 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6046 PetscValidCharPointer(name, 2); 6047 PetscValidPointer(label, 3); 6048 *label = NULL; 6049 while (next) { 6050 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6051 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 6052 if (hasLabel) { 6053 *label = next->label; 6054 break; 6055 } 6056 next = next->next; 6057 } 6058 PetscFunctionReturn(0); 6059 } 6060 6061 /*@C 6062 DMGetLabelByNum - Return the nth label 6063 6064 Not Collective 6065 6066 Input Parameters: 6067 + dm - The DM object 6068 - n - the label number 6069 6070 Output Parameter: 6071 . label - the label 6072 6073 Level: intermediate 6074 6075 .keywords: mesh 6076 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6077 @*/ 6078 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 6079 { 6080 DMLabelLink next = dm->labels->next; 6081 PetscInt l = 0; 6082 6083 PetscFunctionBegin; 6084 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6085 PetscValidPointer(label, 3); 6086 while (next) { 6087 if (l == n) { 6088 *label = next->label; 6089 PetscFunctionReturn(0); 6090 } 6091 ++l; 6092 next = next->next; 6093 } 6094 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 6095 } 6096 6097 /*@C 6098 DMAddLabel - Add the label to this mesh 6099 6100 Not Collective 6101 6102 Input Parameters: 6103 + dm - The DM object 6104 - label - The DMLabel 6105 6106 Level: developer 6107 6108 .keywords: mesh 6109 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6110 @*/ 6111 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 6112 { 6113 DMLabelLink tmpLabel; 6114 PetscBool hasLabel; 6115 const char *lname; 6116 PetscErrorCode ierr; 6117 6118 PetscFunctionBegin; 6119 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6120 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 6121 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 6122 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 6123 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 6124 tmpLabel->label = label; 6125 tmpLabel->output = PETSC_TRUE; 6126 tmpLabel->next = dm->labels->next; 6127 dm->labels->next = tmpLabel; 6128 PetscFunctionReturn(0); 6129 } 6130 6131 /*@C 6132 DMRemoveLabel - Remove the label from this mesh 6133 6134 Not Collective 6135 6136 Input Parameters: 6137 + dm - The DM object 6138 - name - The label name 6139 6140 Output Parameter: 6141 . label - The DMLabel, or NULL if the label is absent 6142 6143 Level: developer 6144 6145 .keywords: mesh 6146 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6147 @*/ 6148 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 6149 { 6150 DMLabelLink next = dm->labels->next; 6151 DMLabelLink last = NULL; 6152 PetscBool hasLabel; 6153 const char *lname; 6154 PetscErrorCode ierr; 6155 6156 PetscFunctionBegin; 6157 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6158 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 6159 *label = NULL; 6160 if (!hasLabel) PetscFunctionReturn(0); 6161 while (next) { 6162 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6163 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 6164 if (hasLabel) { 6165 if (last) last->next = next->next; 6166 else dm->labels->next = next->next; 6167 next->next = NULL; 6168 *label = next->label; 6169 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 6170 if (hasLabel) { 6171 dm->depthLabel = NULL; 6172 } 6173 ierr = PetscFree(next);CHKERRQ(ierr); 6174 break; 6175 } 6176 last = next; 6177 next = next->next; 6178 } 6179 PetscFunctionReturn(0); 6180 } 6181 6182 /*@C 6183 DMGetLabelOutput - Get the output flag for a given label 6184 6185 Not Collective 6186 6187 Input Parameters: 6188 + dm - The DM object 6189 - name - The label name 6190 6191 Output Parameter: 6192 . output - The flag for output 6193 6194 Level: developer 6195 6196 .keywords: mesh 6197 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6198 @*/ 6199 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 6200 { 6201 DMLabelLink next = dm->labels->next; 6202 const char *lname; 6203 PetscErrorCode ierr; 6204 6205 PetscFunctionBegin; 6206 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6207 PetscValidPointer(name, 2); 6208 PetscValidPointer(output, 3); 6209 while (next) { 6210 PetscBool flg; 6211 6212 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6213 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 6214 if (flg) {*output = next->output; PetscFunctionReturn(0);} 6215 next = next->next; 6216 } 6217 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 6218 } 6219 6220 /*@C 6221 DMSetLabelOutput - Set the output flag for a given label 6222 6223 Not Collective 6224 6225 Input Parameters: 6226 + dm - The DM object 6227 . name - The label name 6228 - output - The flag for output 6229 6230 Level: developer 6231 6232 .keywords: mesh 6233 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6234 @*/ 6235 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 6236 { 6237 DMLabelLink next = dm->labels->next; 6238 const char *lname; 6239 PetscErrorCode ierr; 6240 6241 PetscFunctionBegin; 6242 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6243 PetscValidPointer(name, 2); 6244 while (next) { 6245 PetscBool flg; 6246 6247 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6248 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 6249 if (flg) {next->output = output; PetscFunctionReturn(0);} 6250 next = next->next; 6251 } 6252 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 6253 } 6254 6255 6256 /*@ 6257 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 6258 6259 Collective on DM 6260 6261 Input Parameter: 6262 . dmA - The DM object with initial labels 6263 6264 Output Parameter: 6265 . dmB - The DM object with copied labels 6266 6267 Level: intermediate 6268 6269 Note: This is typically used when interpolating or otherwise adding to a mesh 6270 6271 .keywords: mesh 6272 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 6273 @*/ 6274 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 6275 { 6276 PetscInt numLabels, l; 6277 PetscErrorCode ierr; 6278 6279 PetscFunctionBegin; 6280 if (dmA == dmB) PetscFunctionReturn(0); 6281 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 6282 for (l = 0; l < numLabels; ++l) { 6283 DMLabel label, labelNew; 6284 const char *name; 6285 PetscBool flg; 6286 6287 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 6288 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 6289 if (flg) continue; 6290 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 6291 if (flg) continue; 6292 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 6293 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 6294 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 6295 } 6296 PetscFunctionReturn(0); 6297 } 6298 6299 /*@ 6300 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 6301 6302 Input Parameter: 6303 . dm - The DM object 6304 6305 Output Parameter: 6306 . cdm - The coarse DM 6307 6308 Level: intermediate 6309 6310 .seealso: DMSetCoarseDM() 6311 @*/ 6312 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 6313 { 6314 PetscFunctionBegin; 6315 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6316 PetscValidPointer(cdm, 2); 6317 *cdm = dm->coarseMesh; 6318 PetscFunctionReturn(0); 6319 } 6320 6321 /*@ 6322 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 6323 6324 Input Parameters: 6325 + dm - The DM object 6326 - cdm - The coarse DM 6327 6328 Level: intermediate 6329 6330 .seealso: DMGetCoarseDM() 6331 @*/ 6332 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 6333 { 6334 PetscErrorCode ierr; 6335 6336 PetscFunctionBegin; 6337 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6338 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 6339 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 6340 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 6341 dm->coarseMesh = cdm; 6342 PetscFunctionReturn(0); 6343 } 6344 6345 /*@ 6346 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 6347 6348 Input Parameter: 6349 . dm - The DM object 6350 6351 Output Parameter: 6352 . fdm - The fine DM 6353 6354 Level: intermediate 6355 6356 .seealso: DMSetFineDM() 6357 @*/ 6358 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 6359 { 6360 PetscFunctionBegin; 6361 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6362 PetscValidPointer(fdm, 2); 6363 *fdm = dm->fineMesh; 6364 PetscFunctionReturn(0); 6365 } 6366 6367 /*@ 6368 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 6369 6370 Input Parameters: 6371 + dm - The DM object 6372 - fdm - The fine DM 6373 6374 Level: intermediate 6375 6376 .seealso: DMGetFineDM() 6377 @*/ 6378 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 6379 { 6380 PetscErrorCode ierr; 6381 6382 PetscFunctionBegin; 6383 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6384 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 6385 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 6386 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 6387 dm->fineMesh = fdm; 6388 PetscFunctionReturn(0); 6389 } 6390 6391 /*=== DMBoundary code ===*/ 6392 6393 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 6394 { 6395 PetscErrorCode ierr; 6396 6397 PetscFunctionBegin; 6398 ierr = PetscDSCopyBoundary(dm->prob,dmNew->prob);CHKERRQ(ierr); 6399 PetscFunctionReturn(0); 6400 } 6401 6402 /*@C 6403 DMAddBoundary - Add a boundary condition to the model 6404 6405 Input Parameters: 6406 + dm - The DM, with a PetscDS that matches the problem being constrained 6407 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6408 . name - The BC name 6409 . labelname - The label defining constrained points 6410 . field - The field to constrain 6411 . numcomps - The number of constrained field components (0 will constrain all fields) 6412 . comps - An array of constrained component numbers 6413 . bcFunc - A pointwise function giving boundary values 6414 . numids - The number of DMLabel ids for constrained points 6415 . ids - An array of ids for constrained points 6416 - ctx - An optional user context for bcFunc 6417 6418 Options Database Keys: 6419 + -bc_<boundary name> <num> - Overrides the boundary ids 6420 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6421 6422 Level: developer 6423 6424 .seealso: DMGetBoundary() 6425 @*/ 6426 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) 6427 { 6428 PetscErrorCode ierr; 6429 6430 PetscFunctionBegin; 6431 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6432 ierr = PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);CHKERRQ(ierr); 6433 PetscFunctionReturn(0); 6434 } 6435 6436 /*@ 6437 DMGetNumBoundary - Get the number of registered BC 6438 6439 Input Parameters: 6440 . dm - The mesh object 6441 6442 Output Parameters: 6443 . numBd - The number of BC 6444 6445 Level: intermediate 6446 6447 .seealso: DMAddBoundary(), DMGetBoundary() 6448 @*/ 6449 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 6450 { 6451 PetscErrorCode ierr; 6452 6453 PetscFunctionBegin; 6454 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6455 ierr = PetscDSGetNumBoundary(dm->prob,numBd);CHKERRQ(ierr); 6456 PetscFunctionReturn(0); 6457 } 6458 6459 /*@C 6460 DMGetBoundary - Get a model boundary condition 6461 6462 Input Parameters: 6463 + dm - The mesh object 6464 - bd - The BC number 6465 6466 Output Parameters: 6467 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6468 . name - The BC name 6469 . labelname - The label defining constrained points 6470 . field - The field to constrain 6471 . numcomps - The number of constrained field components 6472 . comps - An array of constrained component numbers 6473 . bcFunc - A pointwise function giving boundary values 6474 . numids - The number of DMLabel ids for constrained points 6475 . ids - An array of ids for constrained points 6476 - ctx - An optional user context for bcFunc 6477 6478 Options Database Keys: 6479 + -bc_<boundary name> <num> - Overrides the boundary ids 6480 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6481 6482 Level: developer 6483 6484 .seealso: DMAddBoundary() 6485 @*/ 6486 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) 6487 { 6488 PetscErrorCode ierr; 6489 6490 PetscFunctionBegin; 6491 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6492 ierr = PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);CHKERRQ(ierr); 6493 PetscFunctionReturn(0); 6494 } 6495 6496 static PetscErrorCode DMPopulateBoundary(DM dm) 6497 { 6498 DMBoundary *lastnext; 6499 DSBoundary dsbound; 6500 PetscErrorCode ierr; 6501 6502 PetscFunctionBegin; 6503 dsbound = dm->prob->boundary; 6504 if (dm->boundary) { 6505 DMBoundary next = dm->boundary; 6506 6507 /* quick check to see if the PetscDS has changed */ 6508 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 6509 /* the PetscDS has changed: tear down and rebuild */ 6510 while (next) { 6511 DMBoundary b = next; 6512 6513 next = b->next; 6514 ierr = PetscFree(b);CHKERRQ(ierr); 6515 } 6516 dm->boundary = NULL; 6517 } 6518 6519 lastnext = &(dm->boundary); 6520 while (dsbound) { 6521 DMBoundary dmbound; 6522 6523 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 6524 dmbound->dsboundary = dsbound; 6525 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 6526 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 6527 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 6528 *lastnext = dmbound; 6529 lastnext = &(dmbound->next); 6530 dsbound = dsbound->next; 6531 } 6532 PetscFunctionReturn(0); 6533 } 6534 6535 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 6536 { 6537 DMBoundary b; 6538 PetscErrorCode ierr; 6539 6540 PetscFunctionBegin; 6541 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6542 PetscValidPointer(isBd, 3); 6543 *isBd = PETSC_FALSE; 6544 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 6545 b = dm->boundary; 6546 while (b && !(*isBd)) { 6547 DMLabel label = b->label; 6548 DSBoundary dsb = b->dsboundary; 6549 6550 if (label) { 6551 PetscInt i; 6552 6553 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 6554 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 6555 } 6556 } 6557 b = b->next; 6558 } 6559 PetscFunctionReturn(0); 6560 } 6561 6562 /*@C 6563 DMProjectFunction - This projects the given function into the function space provided. 6564 6565 Input Parameters: 6566 + dm - The DM 6567 . time - The time 6568 . funcs - The coordinate functions to evaluate, one per field 6569 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6570 - mode - The insertion mode for values 6571 6572 Output Parameter: 6573 . X - vector 6574 6575 Calling sequence of func: 6576 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6577 6578 + dim - The spatial dimension 6579 . x - The coordinates 6580 . Nf - The number of fields 6581 . u - The output field values 6582 - ctx - optional user-defined function context 6583 6584 Level: developer 6585 6586 .seealso: DMComputeL2Diff() 6587 @*/ 6588 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6589 { 6590 Vec localX; 6591 PetscErrorCode ierr; 6592 6593 PetscFunctionBegin; 6594 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6595 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6596 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6597 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6598 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6599 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6600 PetscFunctionReturn(0); 6601 } 6602 6603 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6604 { 6605 PetscErrorCode ierr; 6606 6607 PetscFunctionBegin; 6608 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6609 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6610 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6611 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6612 PetscFunctionReturn(0); 6613 } 6614 6615 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) 6616 { 6617 Vec localX; 6618 PetscErrorCode ierr; 6619 6620 PetscFunctionBegin; 6621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6622 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6623 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6624 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6625 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6626 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6627 PetscFunctionReturn(0); 6628 } 6629 6630 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) 6631 { 6632 PetscErrorCode ierr; 6633 6634 PetscFunctionBegin; 6635 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6636 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6637 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6638 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6639 PetscFunctionReturn(0); 6640 } 6641 6642 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 6643 void (**funcs)(PetscInt, PetscInt, PetscInt, 6644 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6645 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6646 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6647 InsertMode mode, Vec localX) 6648 { 6649 PetscErrorCode ierr; 6650 6651 PetscFunctionBegin; 6652 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6653 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 6654 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 6655 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6656 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 6657 PetscFunctionReturn(0); 6658 } 6659 6660 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 6661 void (**funcs)(PetscInt, PetscInt, PetscInt, 6662 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6663 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6664 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 6665 InsertMode mode, Vec localX) 6666 { 6667 PetscErrorCode ierr; 6668 6669 PetscFunctionBegin; 6670 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6671 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 6672 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 6673 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 6674 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 6675 PetscFunctionReturn(0); 6676 } 6677 6678 /*@C 6679 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6680 6681 Input Parameters: 6682 + dm - The DM 6683 . time - The time 6684 . funcs - The functions to evaluate for each field component 6685 . ctxs - Optional array of contexts to pass to each function, or NULL. 6686 - X - The coefficient vector u_h, a global vector 6687 6688 Output Parameter: 6689 . diff - The diff ||u - u_h||_2 6690 6691 Level: developer 6692 6693 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6694 @*/ 6695 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6696 { 6697 PetscErrorCode ierr; 6698 6699 PetscFunctionBegin; 6700 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6701 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6702 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 6703 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6704 PetscFunctionReturn(0); 6705 } 6706 6707 /*@C 6708 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6709 6710 Input Parameters: 6711 + dm - The DM 6712 , time - The time 6713 . funcs - The gradient functions to evaluate for each field component 6714 . ctxs - Optional array of contexts to pass to each function, or NULL. 6715 . X - The coefficient vector u_h, a global vector 6716 - n - The vector to project along 6717 6718 Output Parameter: 6719 . diff - The diff ||(grad u - grad u_h) . n||_2 6720 6721 Level: developer 6722 6723 .seealso: DMProjectFunction(), DMComputeL2Diff() 6724 @*/ 6725 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) 6726 { 6727 PetscErrorCode ierr; 6728 6729 PetscFunctionBegin; 6730 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6731 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6732 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6733 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6734 PetscFunctionReturn(0); 6735 } 6736 6737 /*@C 6738 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 6739 6740 Input Parameters: 6741 + dm - The DM 6742 . time - The time 6743 . funcs - The functions to evaluate for each field component 6744 . ctxs - Optional array of contexts to pass to each function, or NULL. 6745 - X - The coefficient vector u_h, a global vector 6746 6747 Output Parameter: 6748 . diff - The array of differences, ||u^f - u^f_h||_2 6749 6750 Level: developer 6751 6752 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6753 @*/ 6754 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 6755 { 6756 PetscErrorCode ierr; 6757 6758 PetscFunctionBegin; 6759 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6760 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6761 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6762 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6763 PetscFunctionReturn(0); 6764 } 6765 6766 /*@C 6767 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 6768 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 6769 6770 Collective on dm 6771 6772 Input parameters: 6773 + dm - the pre-adaptation DM object 6774 - label - label with the flags 6775 6776 Output parameters: 6777 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 6778 6779 Level: intermediate 6780 6781 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 6782 @*/ 6783 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 6784 { 6785 PetscErrorCode ierr; 6786 6787 PetscFunctionBegin; 6788 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6789 PetscValidPointer(label,2); 6790 PetscValidPointer(dmAdapt,3); 6791 *dmAdapt = NULL; 6792 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 6793 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 6794 PetscFunctionReturn(0); 6795 } 6796 6797 /*@C 6798 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 6799 6800 Input Parameters: 6801 + dm - The DM object 6802 . metric - The metric to which the mesh is adapted, defined vertex-wise. 6803 - 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_". 6804 6805 Output Parameter: 6806 . dmAdapt - Pointer to the DM object containing the adapted mesh 6807 6808 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 6809 6810 Level: advanced 6811 6812 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 6813 @*/ 6814 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 6815 { 6816 PetscErrorCode ierr; 6817 6818 PetscFunctionBegin; 6819 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6820 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 6821 if (bdLabel) PetscValidPointer(bdLabel, 3); 6822 PetscValidPointer(dmAdapt, 4); 6823 *dmAdapt = NULL; 6824 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 6825 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 6826 PetscFunctionReturn(0); 6827 } 6828 6829 /*@C 6830 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 6831 6832 Not Collective 6833 6834 Input Parameter: 6835 . dm - The DM 6836 6837 Output Parameter: 6838 . nranks - the number of neighbours 6839 . ranks - the neighbors ranks 6840 6841 Notes: 6842 Do not free the array, it is freed when the DM is destroyed. 6843 6844 Level: beginner 6845 6846 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 6847 @*/ 6848 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 6849 { 6850 PetscErrorCode ierr; 6851 6852 PetscFunctionBegin; 6853 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6854 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 6855 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 6856 PetscFunctionReturn(0); 6857 } 6858 6859 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 6860 6861 /* 6862 Converts the input vector to a ghosted vector and then calls the standard coloring code. 6863 This has be a different function because it requires DM which is not defined in the Mat library 6864 */ 6865 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 6866 { 6867 PetscErrorCode ierr; 6868 6869 PetscFunctionBegin; 6870 if (coloring->ctype == IS_COLORING_LOCAL) { 6871 Vec x1local; 6872 DM dm; 6873 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6874 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 6875 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 6876 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6877 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6878 x1 = x1local; 6879 } 6880 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 6881 if (coloring->ctype == IS_COLORING_LOCAL) { 6882 DM dm; 6883 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6884 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 6885 } 6886 PetscFunctionReturn(0); 6887 } 6888 6889 /*@ 6890 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 6891 6892 Input Parameter: 6893 . coloring - the MatFDColoring object 6894 6895 Developer Notes: 6896 this routine exists because the PETSc Mat library does not know about the DM objects 6897 6898 Level: advanced 6899 6900 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 6901 @*/ 6902 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 6903 { 6904 PetscFunctionBegin; 6905 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 6906 PetscFunctionReturn(0); 6907 } 6908 6909 /*@ 6910 DMGetCompatibility - determine if two DMs are compatible 6911 6912 Collective 6913 6914 Input Parameters: 6915 + dm - the first DM 6916 - dm2 - the second DM 6917 6918 Output Parameters: 6919 + compatible - whether or not the two DMs are compatible 6920 - set - whether or not the compatible value was set 6921 6922 Notes: 6923 Two DMs are deemed compatible if they represent the same parallel decomposition 6924 of the same topology. This implies that the the section (field data) on one 6925 "makes sense" with respect to the topology and parallel decomposition of the other. 6926 Loosely speaking, compatibile DMs represent the same domain, with the same parallel 6927 decomposition, with different data. 6928 6929 Typically, one would confirm compatibility if intending to simultaneously iterate 6930 over a pair of vectors obtained from different DMs. 6931 6932 For example, two DMDA objects are compatible if they have the same local 6933 and global sizes and the same stencil width. They can have different numbers 6934 of degrees of freedom per node. Thus, one could use the node numbering from 6935 either DM in bounds for a loop over vectors derived from either DM. 6936 6937 Consider the operation of summing data living on a 2-dof DMDA to data living 6938 on a 1-dof DMDA, which should be compatible, as in the following snippet. 6939 .vb 6940 ... 6941 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 6942 if (set && compatible) { 6943 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 6944 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 6945 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n);CHKERRQ(ierr); 6946 for (j=y; j<y+n; ++j) { 6947 for (i=x; i<x+m, ++i) { 6948 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 6949 } 6950 } 6951 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 6952 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 6953 } else { 6954 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 6955 } 6956 ... 6957 .ve 6958 6959 Checking compatibility might be expensive for a given implementation of DM, 6960 or might be impossible to unambiguously confirm or deny. For this reason, 6961 this function may decline to determine compatibility, and hence users should 6962 always check the "set" output parameter. 6963 6964 A DM is always compatible with itself. 6965 6966 In the current implementation, DMs which live on "unequal" communicators 6967 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 6968 incompatible. 6969 6970 This function is labeled "Collective," as information about all subdomains 6971 is required on each rank. However, in DM implementations which store all this 6972 information locally, this function may be merely "Logically Collective". 6973 6974 Developer Notes: 6975 Compatibility is assumed to be a symmetric concept; if DM A is compatible with DM B, 6976 the DM B is compatible with DM A. Thus, this function checks the implementations 6977 of both dm and dm2 (if they are of different types), attempting to determine 6978 compatibility. It is left to DM implementers to ensure that symmetry is 6979 preserved. The simplest way to do this is, when implementing type-specific 6980 logic for this function, to check for existing logic in the implementation 6981 of other DM types and let *set = PETSC_FALSE if found; the logic of this 6982 function will then call that logic. 6983 6984 Level: advanced 6985 6986 .seealso: DM, DMDACreateCompatibleDMDA() 6987 @*/ 6988 6989 PetscErrorCode DMGetCompatibility(DM dm,DM dm2,PetscBool *compatible,PetscBool *set) 6990 { 6991 PetscErrorCode ierr; 6992 PetscMPIInt compareResult; 6993 DMType type,type2; 6994 PetscBool sameType; 6995 6996 PetscFunctionBegin; 6997 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6998 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 6999 7000 /* Declare a DM compatible with itself */ 7001 if (dm == dm2) { 7002 *set = PETSC_TRUE; 7003 *compatible = PETSC_TRUE; 7004 PetscFunctionReturn(0); 7005 } 7006 7007 /* Declare a DM incompatible with a DM that lives on an "unequal" 7008 communicator. Note that this does not preclude compatibility with 7009 DMs living on "congruent" or "similar" communicators, but this must be 7010 determined by the implementation-specific logic */ 7011 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr); 7012 if (compareResult == MPI_UNEQUAL) { 7013 *set = PETSC_TRUE; 7014 *compatible = PETSC_FALSE; 7015 PetscFunctionReturn(0); 7016 } 7017 7018 /* Pass to the implementation-specific routine, if one exists. */ 7019 if (dm->ops->getcompatibility) { 7020 ierr = (*dm->ops->getcompatibility)(dm,dm2,compatible,set);CHKERRQ(ierr); 7021 if (*set) { 7022 PetscFunctionReturn(0); 7023 } 7024 } 7025 7026 /* If dm and dm2 are of different types, then attempt to check compatibility 7027 with an implementation of this function from dm2 */ 7028 ierr = DMGetType(dm,&type);CHKERRQ(ierr); 7029 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 7030 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 7031 if (!sameType && dm2->ops->getcompatibility) { 7032 ierr = (*dm2->ops->getcompatibility)(dm2,dm,compatible,set);CHKERRQ(ierr); /* Note argument order */ 7033 } else { 7034 *set = PETSC_FALSE; 7035 } 7036 PetscFunctionReturn(0); 7037 } 7038