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