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