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