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