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