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