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(), DMPlexCreateBasisRotation() 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 = VecGetArrayInPlace(l, &lArray);CHKERRQ(ierr); 2412 ierr = VecGetArrayReadInPlace(g, &gArray);CHKERRQ(ierr); 2413 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 2414 ierr = VecRestoreArrayInPlace(l, &lArray);CHKERRQ(ierr); 2415 ierr = VecRestoreArrayReadInPlace(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 = VecGetArrayInPlace(l, &lArray);CHKERRQ(ierr); 2456 ierr = VecGetArrayReadInPlace(g, &gArray);CHKERRQ(ierr); 2457 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 2458 ierr = VecRestoreArrayInPlace(l, &lArray);CHKERRQ(ierr); 2459 ierr = VecRestoreArrayReadInPlace(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, l_inplace = PETSC_FALSE, g_inplace = PETSC_FALSE; 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 if (isInsert) { 2655 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2656 } else { 2657 ierr = VecGetArrayReadInPlace(l, &lArray);CHKERRQ(ierr); 2658 l_inplace = PETSC_TRUE; 2659 } 2660 if (s && isInsert) { 2661 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2662 } else { 2663 ierr = VecGetArrayInPlace(g, &gArray);CHKERRQ(ierr); 2664 g_inplace = PETSC_TRUE; 2665 } 2666 if (sf && !isInsert) { 2667 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2668 } else if (s && isInsert) { 2669 PetscInt gStart, pStart, pEnd, p; 2670 2671 ierr = DMGetGlobalSection(dm, &gs);CHKERRQ(ierr); 2672 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 2673 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 2674 for (p = pStart; p < pEnd; ++p) { 2675 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 2676 2677 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 2678 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 2679 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 2680 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 2681 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 2682 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 2683 /* Ignore off-process data and points with no global data */ 2684 if (!gdof || goff < 0) continue; 2685 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); 2686 /* If no constraints are enforced in the global vector */ 2687 if (!gcdof) { 2688 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 2689 /* If constraints are enforced in the global vector */ 2690 } else if (cdof == gcdof) { 2691 const PetscInt *cdofs; 2692 PetscInt cind = 0; 2693 2694 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 2695 for (d = 0, e = 0; d < dof; ++d) { 2696 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 2697 gArray[goff-gStart+e++] = lArray[off+d]; 2698 } 2699 } 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); 2700 } 2701 } 2702 if (g_inplace) { 2703 ierr = VecRestoreArrayInPlace(g, &gArray);CHKERRQ(ierr); 2704 } else { 2705 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2706 } 2707 if (transform) { 2708 ierr = VecRestoreArrayRead(tmpl, &lArray);CHKERRQ(ierr); 2709 ierr = DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr); 2710 } else if (l_inplace) { 2711 ierr = VecRestoreArrayReadInPlace(l, &lArray);CHKERRQ(ierr); 2712 } else { 2713 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2714 } 2715 } else { 2716 if (!dm->ops->localtoglobalbegin) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMLocalToGlobalBegin() for type %s",((PetscObject)dm)->type_name); 2717 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2718 } 2719 PetscFunctionReturn(0); 2720 } 2721 2722 /*@ 2723 DMLocalToGlobalEnd - updates global vectors from local vectors 2724 2725 Neighbor-wise Collective on dm 2726 2727 Input Parameters: 2728 + dm - the DM object 2729 . l - the local vector 2730 . mode - INSERT_VALUES or ADD_VALUES 2731 - g - the global vector 2732 2733 Level: intermediate 2734 2735 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 2736 2737 @*/ 2738 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 2739 { 2740 PetscSF sf; 2741 PetscSection s; 2742 DMLocalToGlobalHookLink link; 2743 PetscBool isInsert, transform; 2744 PetscErrorCode ierr; 2745 2746 PetscFunctionBegin; 2747 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2748 ierr = DMGetSectionSF(dm, &sf);CHKERRQ(ierr); 2749 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 2750 switch (mode) { 2751 case INSERT_VALUES: 2752 case INSERT_ALL_VALUES: 2753 isInsert = PETSC_TRUE; break; 2754 case ADD_VALUES: 2755 case ADD_ALL_VALUES: 2756 isInsert = PETSC_FALSE; break; 2757 default: 2758 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2759 } 2760 if (sf && !isInsert) { 2761 const PetscScalar *lArray; 2762 PetscScalar *gArray; 2763 Vec tmpl; 2764 2765 ierr = DMHasBasisTransform(dm, &transform);CHKERRQ(ierr); 2766 if (transform) { 2767 ierr = DMGetNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr); 2768 ierr = VecGetArrayRead(tmpl, &lArray);CHKERRQ(ierr); 2769 } else { 2770 ierr = VecGetArrayReadInPlace(l, &lArray);CHKERRQ(ierr); 2771 } 2772 ierr = VecGetArrayInPlace(g, &gArray);CHKERRQ(ierr); 2773 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2774 if (transform) { 2775 ierr = VecRestoreArrayRead(tmpl, &lArray);CHKERRQ(ierr); 2776 ierr = DMRestoreNamedLocalVector(dm, "__petsc_dm_transform_local_copy", &tmpl);CHKERRQ(ierr); 2777 } else { 2778 ierr = VecRestoreArrayReadInPlace(l, &lArray);CHKERRQ(ierr); 2779 } 2780 ierr = VecRestoreArrayInPlace(g, &gArray);CHKERRQ(ierr); 2781 } else if (s && isInsert) { 2782 } else { 2783 if (!dm->ops->localtoglobalend) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Missing DMLocalToGlobalEnd() for type %s",((PetscObject)dm)->type_name); 2784 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2785 } 2786 for (link=dm->ltoghook; link; link=link->next) { 2787 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2788 } 2789 PetscFunctionReturn(0); 2790 } 2791 2792 /*@ 2793 DMLocalToLocalBegin - Maps from a local vector (including ghost points 2794 that contain irrelevant values) to another local vector where the ghost 2795 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 2796 2797 Neighbor-wise Collective on dm 2798 2799 Input Parameters: 2800 + dm - the DM object 2801 . g - the original local vector 2802 - mode - one of INSERT_VALUES or ADD_VALUES 2803 2804 Output Parameter: 2805 . l - the local vector with correct ghost values 2806 2807 Level: intermediate 2808 2809 Notes: 2810 The local vectors used here need not be the same as those 2811 obtained from DMCreateLocalVector(), BUT they 2812 must have the same parallel data layout; they could, for example, be 2813 obtained with VecDuplicate() from the DM originating vectors. 2814 2815 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2816 2817 @*/ 2818 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2819 { 2820 PetscErrorCode ierr; 2821 2822 PetscFunctionBegin; 2823 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2824 if (!dm->ops->localtolocalbegin) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 2825 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2826 PetscFunctionReturn(0); 2827 } 2828 2829 /*@ 2830 DMLocalToLocalEnd - Maps from a local vector (including ghost points 2831 that contain irrelevant values) to another local vector where the ghost 2832 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 2833 2834 Neighbor-wise Collective on dm 2835 2836 Input Parameters: 2837 + da - the DM object 2838 . g - the original local vector 2839 - mode - one of INSERT_VALUES or ADD_VALUES 2840 2841 Output Parameter: 2842 . l - the local vector with correct ghost values 2843 2844 Level: intermediate 2845 2846 Notes: 2847 The local vectors used here need not be the same as those 2848 obtained from DMCreateLocalVector(), BUT they 2849 must have the same parallel data layout; they could, for example, be 2850 obtained with VecDuplicate() from the DM originating vectors. 2851 2852 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2853 2854 @*/ 2855 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2856 { 2857 PetscErrorCode ierr; 2858 2859 PetscFunctionBegin; 2860 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2861 if (!dm->ops->localtolocalend) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM does not support local to local maps"); 2862 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2863 PetscFunctionReturn(0); 2864 } 2865 2866 2867 /*@ 2868 DMCoarsen - Coarsens a DM object 2869 2870 Collective on dm 2871 2872 Input Parameter: 2873 + dm - the DM object 2874 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2875 2876 Output Parameter: 2877 . dmc - the coarsened DM 2878 2879 Level: developer 2880 2881 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2882 2883 @*/ 2884 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 2885 { 2886 PetscErrorCode ierr; 2887 DMCoarsenHookLink link; 2888 2889 PetscFunctionBegin; 2890 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2891 if (!dm->ops->coarsen) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMCoarsen",((PetscObject)dm)->type_name); 2892 ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2893 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 2894 if (*dmc) { 2895 ierr = DMSetCoarseDM(dm,*dmc);CHKERRQ(ierr); 2896 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2897 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2898 (*dmc)->ctx = dm->ctx; 2899 (*dmc)->levelup = dm->levelup; 2900 (*dmc)->leveldown = dm->leveldown + 1; 2901 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2902 for (link=dm->coarsenhook; link; link=link->next) { 2903 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2904 } 2905 } 2906 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2907 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 2908 PetscFunctionReturn(0); 2909 } 2910 2911 /*@C 2912 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2913 2914 Logically Collective 2915 2916 Input Arguments: 2917 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2918 . coarsenhook - function to run when setting up a coarser level 2919 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2920 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2921 2922 Calling sequence of coarsenhook: 2923 $ coarsenhook(DM fine,DM coarse,void *ctx); 2924 2925 + fine - fine level DM 2926 . coarse - coarse level DM to restrict problem to 2927 - ctx - optional user-defined function context 2928 2929 Calling sequence for restricthook: 2930 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2931 2932 + fine - fine level DM 2933 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2934 . rscale - scaling vector for restriction 2935 . inject - matrix restricting by injection 2936 . coarse - coarse level DM to update 2937 - ctx - optional user-defined function context 2938 2939 Level: advanced 2940 2941 Notes: 2942 This function is only needed if auxiliary data needs to be set up on coarse grids. 2943 2944 If this function is called multiple times, the hooks will be run in the order they are added. 2945 2946 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2947 extract the finest level information from its context (instead of from the SNES). 2948 2949 This function is currently not available from Fortran. 2950 2951 .seealso: DMCoarsenHookRemove(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2952 @*/ 2953 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2954 { 2955 PetscErrorCode ierr; 2956 DMCoarsenHookLink link,*p; 2957 2958 PetscFunctionBegin; 2959 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2960 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 2961 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 2962 } 2963 ierr = PetscNew(&link);CHKERRQ(ierr); 2964 link->coarsenhook = coarsenhook; 2965 link->restricthook = restricthook; 2966 link->ctx = ctx; 2967 link->next = NULL; 2968 *p = link; 2969 PetscFunctionReturn(0); 2970 } 2971 2972 /*@C 2973 DMCoarsenHookRemove - remove a callback from the list of hooks to be run when restricting a nonlinear problem to the coarse grid 2974 2975 Logically Collective 2976 2977 Input Arguments: 2978 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2979 . coarsenhook - function to run when setting up a coarser level 2980 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2981 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2982 2983 Level: advanced 2984 2985 Notes: 2986 This function does nothing if the hook is not in the list. 2987 2988 This function is currently not available from Fortran. 2989 2990 .seealso: DMCoarsenHookAdd(), DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2991 @*/ 2992 PetscErrorCode DMCoarsenHookRemove(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2993 { 2994 PetscErrorCode ierr; 2995 DMCoarsenHookLink link,*p; 2996 2997 PetscFunctionBegin; 2998 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2999 for (p=&fine->coarsenhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 3000 if ((*p)->coarsenhook == coarsenhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 3001 link = *p; 3002 *p = link->next; 3003 ierr = PetscFree(link);CHKERRQ(ierr); 3004 break; 3005 } 3006 } 3007 PetscFunctionReturn(0); 3008 } 3009 3010 3011 /*@ 3012 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 3013 3014 Collective if any hooks are 3015 3016 Input Arguments: 3017 + fine - finer DM to use as a base 3018 . restrct - restriction matrix, apply using MatRestrict() 3019 . rscale - scaling vector for restriction 3020 . inject - injection matrix, also use MatRestrict() 3021 - coarse - coarser DM to update 3022 3023 Level: developer 3024 3025 .seealso: DMCoarsenHookAdd(), MatRestrict() 3026 @*/ 3027 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 3028 { 3029 PetscErrorCode ierr; 3030 DMCoarsenHookLink link; 3031 3032 PetscFunctionBegin; 3033 for (link=fine->coarsenhook; link; link=link->next) { 3034 if (link->restricthook) { 3035 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 3036 } 3037 } 3038 PetscFunctionReturn(0); 3039 } 3040 3041 /*@C 3042 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 3043 3044 Logically Collective on global 3045 3046 Input Arguments: 3047 + global - global DM 3048 . ddhook - function to run to pass data to the decomposition DM upon its creation 3049 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 3050 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 3051 3052 3053 Calling sequence for ddhook: 3054 $ ddhook(DM global,DM block,void *ctx) 3055 3056 + global - global DM 3057 . block - block DM 3058 - ctx - optional user-defined function context 3059 3060 Calling sequence for restricthook: 3061 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 3062 3063 + global - global DM 3064 . out - scatter to the outer (with ghost and overlap points) block vector 3065 . in - scatter to block vector values only owned locally 3066 . block - block DM 3067 - ctx - optional user-defined function context 3068 3069 Level: advanced 3070 3071 Notes: 3072 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 3073 3074 If this function is called multiple times, the hooks will be run in the order they are added. 3075 3076 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 3077 extract the global information from its context (instead of from the SNES). 3078 3079 This function is currently not available from Fortran. 3080 3081 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 3082 @*/ 3083 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 3084 { 3085 PetscErrorCode ierr; 3086 DMSubDomainHookLink link,*p; 3087 3088 PetscFunctionBegin; 3089 PetscValidHeaderSpecific(global,DM_CLASSID,1); 3090 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Scan to the end of the current list of hooks */ 3091 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) PetscFunctionReturn(0); 3092 } 3093 ierr = PetscNew(&link);CHKERRQ(ierr); 3094 link->restricthook = restricthook; 3095 link->ddhook = ddhook; 3096 link->ctx = ctx; 3097 link->next = NULL; 3098 *p = link; 3099 PetscFunctionReturn(0); 3100 } 3101 3102 /*@C 3103 DMSubDomainHookRemove - remove a callback from the list to be run when restricting a problem to the coarse grid 3104 3105 Logically Collective 3106 3107 Input Arguments: 3108 + global - global DM 3109 . ddhook - function to run to pass data to the decomposition DM upon its creation 3110 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 3111 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 3112 3113 Level: advanced 3114 3115 Notes: 3116 3117 This function is currently not available from Fortran. 3118 3119 .seealso: DMSubDomainHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 3120 @*/ 3121 PetscErrorCode DMSubDomainHookRemove(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 3122 { 3123 PetscErrorCode ierr; 3124 DMSubDomainHookLink link,*p; 3125 3126 PetscFunctionBegin; 3127 PetscValidHeaderSpecific(global,DM_CLASSID,1); 3128 for (p=&global->subdomainhook; *p; p=&(*p)->next) { /* Search the list of current hooks */ 3129 if ((*p)->ddhook == ddhook && (*p)->restricthook == restricthook && (*p)->ctx == ctx) { 3130 link = *p; 3131 *p = link->next; 3132 ierr = PetscFree(link);CHKERRQ(ierr); 3133 break; 3134 } 3135 } 3136 PetscFunctionReturn(0); 3137 } 3138 3139 /*@ 3140 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 3141 3142 Collective if any hooks are 3143 3144 Input Arguments: 3145 + fine - finer DM to use as a base 3146 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 3147 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 3148 - coarse - coarer DM to update 3149 3150 Level: developer 3151 3152 .seealso: DMCoarsenHookAdd(), MatRestrict() 3153 @*/ 3154 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 3155 { 3156 PetscErrorCode ierr; 3157 DMSubDomainHookLink link; 3158 3159 PetscFunctionBegin; 3160 for (link=global->subdomainhook; link; link=link->next) { 3161 if (link->restricthook) { 3162 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 3163 } 3164 } 3165 PetscFunctionReturn(0); 3166 } 3167 3168 /*@ 3169 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 3170 3171 Not Collective 3172 3173 Input Parameter: 3174 . dm - the DM object 3175 3176 Output Parameter: 3177 . level - number of coarsenings 3178 3179 Level: developer 3180 3181 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3182 3183 @*/ 3184 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 3185 { 3186 PetscFunctionBegin; 3187 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3188 PetscValidIntPointer(level,2); 3189 *level = dm->leveldown; 3190 PetscFunctionReturn(0); 3191 } 3192 3193 /*@ 3194 DMSetCoarsenLevel - Sets the number of coarsenings that have generated this DM. 3195 3196 Not Collective 3197 3198 Input Parameters: 3199 + dm - the DM object 3200 - level - number of coarsenings 3201 3202 Level: developer 3203 3204 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3205 @*/ 3206 PetscErrorCode DMSetCoarsenLevel(DM dm,PetscInt level) 3207 { 3208 PetscFunctionBegin; 3209 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3210 dm->leveldown = level; 3211 PetscFunctionReturn(0); 3212 } 3213 3214 3215 3216 /*@C 3217 DMRefineHierarchy - Refines a DM object, all levels at once 3218 3219 Collective on dm 3220 3221 Input Parameter: 3222 + dm - the DM object 3223 - nlevels - the number of levels of refinement 3224 3225 Output Parameter: 3226 . dmf - the refined DM hierarchy 3227 3228 Level: developer 3229 3230 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3231 3232 @*/ 3233 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 3234 { 3235 PetscErrorCode ierr; 3236 3237 PetscFunctionBegin; 3238 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3239 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 3240 if (nlevels == 0) PetscFunctionReturn(0); 3241 PetscValidPointer(dmf,3); 3242 if (dm->ops->refinehierarchy) { 3243 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 3244 } else if (dm->ops->refine) { 3245 PetscInt i; 3246 3247 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 3248 for (i=1; i<nlevels; i++) { 3249 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 3250 } 3251 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 3252 PetscFunctionReturn(0); 3253 } 3254 3255 /*@C 3256 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 3257 3258 Collective on dm 3259 3260 Input Parameter: 3261 + dm - the DM object 3262 - nlevels - the number of levels of coarsening 3263 3264 Output Parameter: 3265 . dmc - the coarsened DM hierarchy 3266 3267 Level: developer 3268 3269 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 3270 3271 @*/ 3272 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 3273 { 3274 PetscErrorCode ierr; 3275 3276 PetscFunctionBegin; 3277 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3278 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 3279 if (nlevels == 0) PetscFunctionReturn(0); 3280 PetscValidPointer(dmc,3); 3281 if (dm->ops->coarsenhierarchy) { 3282 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 3283 } else if (dm->ops->coarsen) { 3284 PetscInt i; 3285 3286 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 3287 for (i=1; i<nlevels; i++) { 3288 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 3289 } 3290 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 3291 PetscFunctionReturn(0); 3292 } 3293 3294 /*@C 3295 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 3296 3297 Not Collective 3298 3299 Input Parameters: 3300 + dm - the DM object 3301 - destroy - the destroy function 3302 3303 Level: intermediate 3304 3305 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3306 3307 @*/ 3308 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 3309 { 3310 PetscFunctionBegin; 3311 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3312 dm->ctxdestroy = destroy; 3313 PetscFunctionReturn(0); 3314 } 3315 3316 /*@ 3317 DMSetApplicationContext - Set a user context into a DM object 3318 3319 Not Collective 3320 3321 Input Parameters: 3322 + dm - the DM object 3323 - ctx - the user context 3324 3325 Level: intermediate 3326 3327 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3328 3329 @*/ 3330 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 3331 { 3332 PetscFunctionBegin; 3333 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3334 dm->ctx = ctx; 3335 PetscFunctionReturn(0); 3336 } 3337 3338 /*@ 3339 DMGetApplicationContext - Gets a user context from a DM object 3340 3341 Not Collective 3342 3343 Input Parameter: 3344 . dm - the DM object 3345 3346 Output Parameter: 3347 . ctx - the user context 3348 3349 Level: intermediate 3350 3351 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3352 3353 @*/ 3354 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 3355 { 3356 PetscFunctionBegin; 3357 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3358 *(void**)ctx = dm->ctx; 3359 PetscFunctionReturn(0); 3360 } 3361 3362 /*@C 3363 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 3364 3365 Logically Collective on dm 3366 3367 Input Parameter: 3368 + dm - the DM object 3369 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 3370 3371 Level: intermediate 3372 3373 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 3374 DMSetJacobian() 3375 3376 @*/ 3377 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 3378 { 3379 PetscFunctionBegin; 3380 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3381 dm->ops->computevariablebounds = f; 3382 PetscFunctionReturn(0); 3383 } 3384 3385 /*@ 3386 DMHasVariableBounds - does the DM object have a variable bounds function? 3387 3388 Not Collective 3389 3390 Input Parameter: 3391 . dm - the DM object to destroy 3392 3393 Output Parameter: 3394 . flg - PETSC_TRUE if the variable bounds function exists 3395 3396 Level: developer 3397 3398 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3399 3400 @*/ 3401 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 3402 { 3403 PetscFunctionBegin; 3404 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3405 PetscValidBoolPointer(flg,2); 3406 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 3407 PetscFunctionReturn(0); 3408 } 3409 3410 /*@C 3411 DMComputeVariableBounds - compute variable bounds used by SNESVI. 3412 3413 Logically Collective on dm 3414 3415 Input Parameters: 3416 . dm - the DM object 3417 3418 Output parameters: 3419 + xl - lower bound 3420 - xu - upper bound 3421 3422 Level: advanced 3423 3424 Notes: 3425 This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 3426 3427 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3428 3429 @*/ 3430 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 3431 { 3432 PetscErrorCode ierr; 3433 3434 PetscFunctionBegin; 3435 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3436 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 3437 PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 3438 if (!dm->ops->computevariablebounds) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeVariableBounds",((PetscObject)dm)->type_name); 3439 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 3440 PetscFunctionReturn(0); 3441 } 3442 3443 /*@ 3444 DMHasColoring - does the DM object have a method of providing a coloring? 3445 3446 Not Collective 3447 3448 Input Parameter: 3449 . dm - the DM object 3450 3451 Output Parameter: 3452 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 3453 3454 Level: developer 3455 3456 .seealso DMCreateColoring() 3457 3458 @*/ 3459 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 3460 { 3461 PetscFunctionBegin; 3462 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3463 PetscValidBoolPointer(flg,2); 3464 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 3465 PetscFunctionReturn(0); 3466 } 3467 3468 /*@ 3469 DMHasCreateRestriction - does the DM object have a method of providing a restriction? 3470 3471 Not Collective 3472 3473 Input Parameter: 3474 . dm - the DM object 3475 3476 Output Parameter: 3477 . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction(). 3478 3479 Level: developer 3480 3481 .seealso DMCreateRestriction() 3482 3483 @*/ 3484 PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg) 3485 { 3486 PetscFunctionBegin; 3487 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3488 PetscValidBoolPointer(flg,2); 3489 *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE; 3490 PetscFunctionReturn(0); 3491 } 3492 3493 3494 /*@ 3495 DMHasCreateInjection - does the DM object have a method of providing an injection? 3496 3497 Not Collective 3498 3499 Input Parameter: 3500 . dm - the DM object 3501 3502 Output Parameter: 3503 . flg - PETSC_TRUE if the DM has facilities for DMCreateInjection(). 3504 3505 Level: developer 3506 3507 .seealso DMCreateInjection() 3508 3509 @*/ 3510 PetscErrorCode DMHasCreateInjection(DM dm,PetscBool *flg) 3511 { 3512 PetscErrorCode ierr; 3513 3514 PetscFunctionBegin; 3515 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3516 PetscValidBoolPointer(flg,2); 3517 if (dm->ops->hascreateinjection) { 3518 ierr = (*dm->ops->hascreateinjection)(dm,flg);CHKERRQ(ierr); 3519 } else { 3520 *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE; 3521 } 3522 PetscFunctionReturn(0); 3523 } 3524 3525 PetscFunctionList DMList = NULL; 3526 PetscBool DMRegisterAllCalled = PETSC_FALSE; 3527 3528 /*@C 3529 DMSetType - Builds a DM, for a particular DM implementation. 3530 3531 Collective on dm 3532 3533 Input Parameters: 3534 + dm - The DM object 3535 - method - The name of the DM type 3536 3537 Options Database Key: 3538 . -dm_type <type> - Sets the DM type; use -help for a list of available types 3539 3540 Notes: 3541 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 3542 3543 Level: intermediate 3544 3545 .seealso: DMGetType(), DMCreate() 3546 @*/ 3547 PetscErrorCode DMSetType(DM dm, DMType method) 3548 { 3549 PetscErrorCode (*r)(DM); 3550 PetscBool match; 3551 PetscErrorCode ierr; 3552 3553 PetscFunctionBegin; 3554 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3555 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 3556 if (match) PetscFunctionReturn(0); 3557 3558 ierr = DMRegisterAll();CHKERRQ(ierr); 3559 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 3560 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 3561 3562 if (dm->ops->destroy) { 3563 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 3564 } 3565 ierr = PetscMemzero(dm->ops,sizeof(*dm->ops));CHKERRQ(ierr); 3566 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 3567 ierr = (*r)(dm);CHKERRQ(ierr); 3568 PetscFunctionReturn(0); 3569 } 3570 3571 /*@C 3572 DMGetType - Gets the DM type name (as a string) from the DM. 3573 3574 Not Collective 3575 3576 Input Parameter: 3577 . dm - The DM 3578 3579 Output Parameter: 3580 . type - The DM type name 3581 3582 Level: intermediate 3583 3584 .seealso: DMSetType(), DMCreate() 3585 @*/ 3586 PetscErrorCode DMGetType(DM dm, DMType *type) 3587 { 3588 PetscErrorCode ierr; 3589 3590 PetscFunctionBegin; 3591 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3592 PetscValidPointer(type,2); 3593 ierr = DMRegisterAll();CHKERRQ(ierr); 3594 *type = ((PetscObject)dm)->type_name; 3595 PetscFunctionReturn(0); 3596 } 3597 3598 /*@C 3599 DMConvert - Converts a DM to another DM, either of the same or different type. 3600 3601 Collective on dm 3602 3603 Input Parameters: 3604 + dm - the DM 3605 - newtype - new DM type (use "same" for the same type) 3606 3607 Output Parameter: 3608 . M - pointer to new DM 3609 3610 Notes: 3611 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 3612 the MPI communicator of the generated DM is always the same as the communicator 3613 of the input DM. 3614 3615 Level: intermediate 3616 3617 .seealso: DMCreate() 3618 @*/ 3619 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 3620 { 3621 DM B; 3622 char convname[256]; 3623 PetscBool sametype/*, issame */; 3624 PetscErrorCode ierr; 3625 3626 PetscFunctionBegin; 3627 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3628 PetscValidType(dm,1); 3629 PetscValidPointer(M,3); 3630 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 3631 /* ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); */ 3632 if (sametype) { 3633 *M = dm; 3634 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 3635 PetscFunctionReturn(0); 3636 } else { 3637 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 3638 3639 /* 3640 Order of precedence: 3641 1) See if a specialized converter is known to the current DM. 3642 2) See if a specialized converter is known to the desired DM class. 3643 3) See if a good general converter is registered for the desired class 3644 4) See if a good general converter is known for the current matrix. 3645 5) Use a really basic converter. 3646 */ 3647 3648 /* 1) See if a specialized converter is known to the current DM and the desired class */ 3649 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3650 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3651 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3652 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3653 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3654 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 3655 if (conv) goto foundconv; 3656 3657 /* 2) See if a specialized converter is known to the desired DM class. */ 3658 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 3659 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 3660 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3661 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3662 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3663 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3664 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3665 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 3666 if (conv) { 3667 ierr = DMDestroy(&B);CHKERRQ(ierr); 3668 goto foundconv; 3669 } 3670 3671 #if 0 3672 /* 3) See if a good general converter is registered for the desired class */ 3673 conv = B->ops->convertfrom; 3674 ierr = DMDestroy(&B);CHKERRQ(ierr); 3675 if (conv) goto foundconv; 3676 3677 /* 4) See if a good general converter is known for the current matrix */ 3678 if (dm->ops->convert) { 3679 conv = dm->ops->convert; 3680 } 3681 if (conv) goto foundconv; 3682 #endif 3683 3684 /* 5) Use a really basic converter. */ 3685 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 3686 3687 foundconv: 3688 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3689 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 3690 /* Things that are independent of DM type: We should consult DMClone() here */ 3691 { 3692 PetscBool isper; 3693 const PetscReal *maxCell, *L; 3694 const DMBoundaryType *bd; 3695 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 3696 ierr = DMSetPeriodicity(*M, isper, maxCell, L, bd);CHKERRQ(ierr); 3697 } 3698 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3699 } 3700 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 3701 PetscFunctionReturn(0); 3702 } 3703 3704 /*--------------------------------------------------------------------------------------------------------------------*/ 3705 3706 /*@C 3707 DMRegister - Adds a new DM component implementation 3708 3709 Not Collective 3710 3711 Input Parameters: 3712 + name - The name of a new user-defined creation routine 3713 - create_func - The creation routine itself 3714 3715 Notes: 3716 DMRegister() may be called multiple times to add several user-defined DMs 3717 3718 3719 Sample usage: 3720 .vb 3721 DMRegister("my_da", MyDMCreate); 3722 .ve 3723 3724 Then, your DM type can be chosen with the procedural interface via 3725 .vb 3726 DMCreate(MPI_Comm, DM *); 3727 DMSetType(DM,"my_da"); 3728 .ve 3729 or at runtime via the option 3730 .vb 3731 -da_type my_da 3732 .ve 3733 3734 Level: advanced 3735 3736 .seealso: DMRegisterAll(), DMRegisterDestroy() 3737 3738 @*/ 3739 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 3740 { 3741 PetscErrorCode ierr; 3742 3743 PetscFunctionBegin; 3744 ierr = DMInitializePackage();CHKERRQ(ierr); 3745 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 3746 PetscFunctionReturn(0); 3747 } 3748 3749 /*@C 3750 DMLoad - Loads a DM that has been stored in binary with DMView(). 3751 3752 Collective on viewer 3753 3754 Input Parameters: 3755 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 3756 some related function before a call to DMLoad(). 3757 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 3758 HDF5 file viewer, obtained from PetscViewerHDF5Open() 3759 3760 Level: intermediate 3761 3762 Notes: 3763 The type is determined by the data in the file, any type set into the DM before this call is ignored. 3764 3765 Notes for advanced users: 3766 Most users should not need to know the details of the binary storage 3767 format, since DMLoad() and DMView() completely hide these details. 3768 But for anyone who's interested, the standard binary matrix storage 3769 format is 3770 .vb 3771 has not yet been determined 3772 .ve 3773 3774 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 3775 @*/ 3776 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 3777 { 3778 PetscBool isbinary, ishdf5; 3779 PetscErrorCode ierr; 3780 3781 PetscFunctionBegin; 3782 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 3783 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3784 ierr = PetscViewerCheckReadable(viewer);CHKERRQ(ierr); 3785 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 3786 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 3787 ierr = PetscLogEventBegin(DM_Load,viewer,0,0,0);CHKERRQ(ierr); 3788 if (isbinary) { 3789 PetscInt classid; 3790 char type[256]; 3791 3792 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3793 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3794 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3795 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3796 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3797 } else if (ishdf5) { 3798 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3799 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3800 ierr = PetscLogEventEnd(DM_Load,viewer,0,0,0);CHKERRQ(ierr); 3801 PetscFunctionReturn(0); 3802 } 3803 3804 /*@ 3805 DMGetLocalBoundingBox - Returns the bounding box for the piece of the DM on this process. 3806 3807 Not collective 3808 3809 Input Parameter: 3810 . dm - the DM 3811 3812 Output Parameters: 3813 + lmin - local minimum coordinates (length coord dim, optional) 3814 - lmax - local maximim coordinates (length coord dim, optional) 3815 3816 Level: beginner 3817 3818 Note: If the DM is a DMDA and has no coordinates, the index bounds are returned instead. 3819 3820 3821 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetBoundingBox() 3822 @*/ 3823 PetscErrorCode DMGetLocalBoundingBox(DM dm, PetscReal lmin[], PetscReal lmax[]) 3824 { 3825 Vec coords = NULL; 3826 PetscReal min[3] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL}; 3827 PetscReal max[3] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 3828 const PetscScalar *local_coords; 3829 PetscInt N, Ni; 3830 PetscInt cdim, i, j; 3831 PetscErrorCode ierr; 3832 3833 PetscFunctionBegin; 3834 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3835 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 3836 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 3837 if (coords) { 3838 ierr = VecGetArrayRead(coords, &local_coords);CHKERRQ(ierr); 3839 ierr = VecGetLocalSize(coords, &N);CHKERRQ(ierr); 3840 Ni = N/cdim; 3841 for (i = 0; i < Ni; ++i) { 3842 for (j = 0; j < 3; ++j) { 3843 min[j] = j < cdim ? PetscMin(min[j], PetscRealPart(local_coords[i*cdim+j])) : 0; 3844 max[j] = j < cdim ? PetscMax(max[j], PetscRealPart(local_coords[i*cdim+j])) : 0; 3845 } 3846 } 3847 ierr = VecRestoreArrayRead(coords, &local_coords);CHKERRQ(ierr); 3848 } else { 3849 PetscBool isda; 3850 3851 ierr = PetscObjectTypeCompare((PetscObject) dm, DMDA, &isda);CHKERRQ(ierr); 3852 if (isda) {ierr = DMGetLocalBoundingIndices_DMDA(dm, min, max);CHKERRQ(ierr);} 3853 } 3854 if (lmin) {ierr = PetscArraycpy(lmin, min, cdim);CHKERRQ(ierr);} 3855 if (lmax) {ierr = PetscArraycpy(lmax, max, cdim);CHKERRQ(ierr);} 3856 PetscFunctionReturn(0); 3857 } 3858 3859 /*@ 3860 DMGetBoundingBox - Returns the global bounding box for the DM. 3861 3862 Collective 3863 3864 Input Parameter: 3865 . dm - the DM 3866 3867 Output Parameters: 3868 + gmin - global minimum coordinates (length coord dim, optional) 3869 - gmax - global maximim coordinates (length coord dim, optional) 3870 3871 Level: beginner 3872 3873 .seealso: DMGetLocalBoundingBox(), DMGetCoordinates(), DMGetCoordinatesLocal() 3874 @*/ 3875 PetscErrorCode DMGetBoundingBox(DM dm, PetscReal gmin[], PetscReal gmax[]) 3876 { 3877 PetscReal lmin[3], lmax[3]; 3878 PetscInt cdim; 3879 PetscMPIInt count; 3880 PetscErrorCode ierr; 3881 3882 PetscFunctionBegin; 3883 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3884 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 3885 ierr = PetscMPIIntCast(cdim, &count);CHKERRQ(ierr); 3886 ierr = DMGetLocalBoundingBox(dm, lmin, lmax);CHKERRQ(ierr); 3887 if (gmin) {ierr = MPIU_Allreduce(lmin, gmin, count, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr);} 3888 if (gmax) {ierr = MPIU_Allreduce(lmax, gmax, count, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr);} 3889 PetscFunctionReturn(0); 3890 } 3891 3892 /******************************** FEM Support **********************************/ 3893 3894 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3895 { 3896 PetscInt f; 3897 PetscErrorCode ierr; 3898 3899 PetscFunctionBegin; 3900 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3901 for (f = 0; f < len; ++f) { 3902 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3903 } 3904 PetscFunctionReturn(0); 3905 } 3906 3907 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3908 { 3909 PetscInt f, g; 3910 PetscErrorCode ierr; 3911 3912 PetscFunctionBegin; 3913 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3914 for (f = 0; f < rows; ++f) { 3915 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3916 for (g = 0; g < cols; ++g) { 3917 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3918 } 3919 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3920 } 3921 PetscFunctionReturn(0); 3922 } 3923 3924 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3925 { 3926 PetscInt localSize, bs; 3927 PetscMPIInt size; 3928 Vec x, xglob; 3929 const PetscScalar *xarray; 3930 PetscErrorCode ierr; 3931 3932 PetscFunctionBegin; 3933 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);CHKERRQ(ierr); 3934 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3935 ierr = VecCopy(X, x);CHKERRQ(ierr); 3936 ierr = VecChop(x, tol);CHKERRQ(ierr); 3937 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);CHKERRQ(ierr); 3938 if (size > 1) { 3939 ierr = VecGetLocalSize(x,&localSize);CHKERRQ(ierr); 3940 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr); 3941 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 3942 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);CHKERRQ(ierr); 3943 } else { 3944 xglob = x; 3945 } 3946 ierr = VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));CHKERRQ(ierr); 3947 if (size > 1) { 3948 ierr = VecDestroy(&xglob);CHKERRQ(ierr); 3949 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 3950 } 3951 ierr = VecDestroy(&x);CHKERRQ(ierr); 3952 PetscFunctionReturn(0); 3953 } 3954 3955 /*@ 3956 DMGetSection - Get the PetscSection encoding the local data layout for the DM. This is equivalent to DMGetLocalSection(). Deprecated in v3.12 3957 3958 Input Parameter: 3959 . dm - The DM 3960 3961 Output Parameter: 3962 . section - The PetscSection 3963 3964 Options Database Keys: 3965 . -dm_petscsection_view - View the Section created by the DM 3966 3967 Level: advanced 3968 3969 Notes: 3970 Use DMGetLocalSection() in new code. 3971 3972 This gets a borrowed reference, so the user should not destroy this PetscSection. 3973 3974 .seealso: DMGetLocalSection(), DMSetLocalSection(), DMGetGlobalSection() 3975 @*/ 3976 PetscErrorCode DMGetSection(DM dm, PetscSection *section) 3977 { 3978 PetscErrorCode ierr; 3979 3980 PetscFunctionBegin; 3981 ierr = DMGetLocalSection(dm,section);CHKERRQ(ierr); 3982 PetscFunctionReturn(0); 3983 } 3984 3985 /*@ 3986 DMGetLocalSection - Get the PetscSection encoding the local data layout for the DM. 3987 3988 Input Parameter: 3989 . dm - The DM 3990 3991 Output Parameter: 3992 . section - The PetscSection 3993 3994 Options Database Keys: 3995 . -dm_petscsection_view - View the Section created by the DM 3996 3997 Level: intermediate 3998 3999 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 4000 4001 .seealso: DMSetLocalSection(), DMGetGlobalSection() 4002 @*/ 4003 PetscErrorCode DMGetLocalSection(DM dm, PetscSection *section) 4004 { 4005 PetscErrorCode ierr; 4006 4007 PetscFunctionBegin; 4008 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4009 PetscValidPointer(section, 2); 4010 if (!dm->localSection && dm->ops->createlocalsection) { 4011 PetscInt d; 4012 4013 if (dm->setfromoptionscalled) for (d = 0; d < dm->Nds; ++d) {ierr = PetscDSSetFromOptions(dm->probs[d].ds);CHKERRQ(ierr);} 4014 ierr = (*dm->ops->createlocalsection)(dm);CHKERRQ(ierr); 4015 if (dm->localSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->localSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 4016 } 4017 *section = dm->localSection; 4018 PetscFunctionReturn(0); 4019 } 4020 4021 /*@ 4022 DMSetSection - Set the PetscSection encoding the local data layout for the DM. This is equivalent to DMSetLocalSection(). Deprecated in v3.12 4023 4024 Input Parameters: 4025 + dm - The DM 4026 - section - The PetscSection 4027 4028 Level: advanced 4029 4030 Notes: 4031 Use DMSetLocalSection() in new code. 4032 4033 Any existing Section will be destroyed 4034 4035 .seealso: DMSetLocalSection(), DMGetLocalSection(), DMSetGlobalSection() 4036 @*/ 4037 PetscErrorCode DMSetSection(DM dm, PetscSection section) 4038 { 4039 PetscErrorCode ierr; 4040 4041 PetscFunctionBegin; 4042 ierr = DMSetLocalSection(dm,section);CHKERRQ(ierr); 4043 PetscFunctionReturn(0); 4044 } 4045 4046 /*@ 4047 DMSetLocalSection - Set the PetscSection encoding the local data layout for the DM. 4048 4049 Input Parameters: 4050 + dm - The DM 4051 - section - The PetscSection 4052 4053 Level: intermediate 4054 4055 Note: Any existing Section will be destroyed 4056 4057 .seealso: DMGetLocalSection(), DMSetGlobalSection() 4058 @*/ 4059 PetscErrorCode DMSetLocalSection(DM dm, PetscSection section) 4060 { 4061 PetscInt numFields = 0; 4062 PetscInt f; 4063 PetscErrorCode ierr; 4064 4065 PetscFunctionBegin; 4066 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4067 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4068 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4069 ierr = PetscSectionDestroy(&dm->localSection);CHKERRQ(ierr); 4070 dm->localSection = section; 4071 if (section) {ierr = PetscSectionGetNumFields(dm->localSection, &numFields);CHKERRQ(ierr);} 4072 if (numFields) { 4073 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 4074 for (f = 0; f < numFields; ++f) { 4075 PetscObject disc; 4076 const char *name; 4077 4078 ierr = PetscSectionGetFieldName(dm->localSection, f, &name);CHKERRQ(ierr); 4079 ierr = DMGetField(dm, f, NULL, &disc);CHKERRQ(ierr); 4080 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 4081 } 4082 } 4083 /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */ 4084 ierr = PetscSectionDestroy(&dm->globalSection);CHKERRQ(ierr); 4085 PetscFunctionReturn(0); 4086 } 4087 4088 /*@ 4089 DMGetDefaultConstraints - Get the PetscSection and Mat that specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 4090 4091 not collective 4092 4093 Input Parameter: 4094 . dm - The DM 4095 4096 Output Parameter: 4097 + 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. 4098 - 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. 4099 4100 Level: advanced 4101 4102 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 4103 4104 .seealso: DMSetDefaultConstraints() 4105 @*/ 4106 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 4107 { 4108 PetscErrorCode ierr; 4109 4110 PetscFunctionBegin; 4111 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4112 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 4113 if (section) {*section = dm->defaultConstraintSection;} 4114 if (mat) {*mat = dm->defaultConstraintMat;} 4115 PetscFunctionReturn(0); 4116 } 4117 4118 /*@ 4119 DMSetDefaultConstraints - Set the PetscSection and Mat that specify the local constraint interpolation. 4120 4121 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(). 4122 4123 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. 4124 4125 collective on dm 4126 4127 Input Parameters: 4128 + dm - The DM 4129 + 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). 4130 - 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). 4131 4132 Level: advanced 4133 4134 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 4135 4136 .seealso: DMGetDefaultConstraints() 4137 @*/ 4138 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 4139 { 4140 PetscMPIInt result; 4141 PetscErrorCode ierr; 4142 4143 PetscFunctionBegin; 4144 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4145 if (section) { 4146 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4147 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 4148 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 4149 } 4150 if (mat) { 4151 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 4152 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 4153 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 4154 } 4155 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4156 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 4157 dm->defaultConstraintSection = section; 4158 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 4159 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 4160 dm->defaultConstraintMat = mat; 4161 PetscFunctionReturn(0); 4162 } 4163 4164 #if defined(PETSC_USE_DEBUG) 4165 /* 4166 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 4167 4168 Input Parameters: 4169 + dm - The DM 4170 . localSection - PetscSection describing the local data layout 4171 - globalSection - PetscSection describing the global data layout 4172 4173 Level: intermediate 4174 4175 .seealso: DMGetSectionSF(), DMSetSectionSF() 4176 */ 4177 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 4178 { 4179 MPI_Comm comm; 4180 PetscLayout layout; 4181 const PetscInt *ranges; 4182 PetscInt pStart, pEnd, p, nroots; 4183 PetscMPIInt size, rank; 4184 PetscBool valid = PETSC_TRUE, gvalid; 4185 PetscErrorCode ierr; 4186 4187 PetscFunctionBegin; 4188 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4189 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4190 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 4191 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4192 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 4193 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 4194 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 4195 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 4196 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 4197 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 4198 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 4199 for (p = pStart; p < pEnd; ++p) { 4200 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 4201 4202 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 4203 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 4204 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 4205 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4206 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4207 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 4208 if (!gdof) continue; /* Censored point */ 4209 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;} 4210 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;} 4211 if (gdof < 0) { 4212 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4213 for (d = 0; d < gsize; ++d) { 4214 PetscInt offset = -(goff+1) + d, r; 4215 4216 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 4217 if (r < 0) r = -(r+2); 4218 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;} 4219 } 4220 } 4221 } 4222 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 4223 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 4224 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 4225 if (!gvalid) { 4226 ierr = DMView(dm, NULL);CHKERRQ(ierr); 4227 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 4228 } 4229 PetscFunctionReturn(0); 4230 } 4231 #endif 4232 4233 /*@ 4234 DMGetGlobalSection - Get the PetscSection encoding the global data layout for the DM. 4235 4236 Collective on dm 4237 4238 Input Parameter: 4239 . dm - The DM 4240 4241 Output Parameter: 4242 . section - The PetscSection 4243 4244 Level: intermediate 4245 4246 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 4247 4248 .seealso: DMSetLocalSection(), DMGetLocalSection() 4249 @*/ 4250 PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section) 4251 { 4252 PetscErrorCode ierr; 4253 4254 PetscFunctionBegin; 4255 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4256 PetscValidPointer(section, 2); 4257 if (!dm->globalSection) { 4258 PetscSection s; 4259 4260 ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 4261 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 4262 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection"); 4263 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->globalSection);CHKERRQ(ierr); 4264 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 4265 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->globalSection, &dm->map);CHKERRQ(ierr); 4266 ierr = PetscSectionViewFromOptions(dm->globalSection, NULL, "-global_section_view");CHKERRQ(ierr); 4267 } 4268 *section = dm->globalSection; 4269 PetscFunctionReturn(0); 4270 } 4271 4272 /*@ 4273 DMSetGlobalSection - Set the PetscSection encoding the global data layout for the DM. 4274 4275 Input Parameters: 4276 + dm - The DM 4277 - section - The PetscSection, or NULL 4278 4279 Level: intermediate 4280 4281 Note: Any existing Section will be destroyed 4282 4283 .seealso: DMGetGlobalSection(), DMSetLocalSection() 4284 @*/ 4285 PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section) 4286 { 4287 PetscErrorCode ierr; 4288 4289 PetscFunctionBegin; 4290 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4291 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4292 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4293 ierr = PetscSectionDestroy(&dm->globalSection);CHKERRQ(ierr); 4294 dm->globalSection = section; 4295 #if defined(PETSC_USE_DEBUG) 4296 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->localSection, section);CHKERRQ(ierr);} 4297 #endif 4298 PetscFunctionReturn(0); 4299 } 4300 4301 /*@ 4302 DMGetSectionSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 4303 it is created from the default PetscSection layouts in the DM. 4304 4305 Input Parameter: 4306 . dm - The DM 4307 4308 Output Parameter: 4309 . sf - The PetscSF 4310 4311 Level: intermediate 4312 4313 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4314 4315 .seealso: DMSetSectionSF(), DMCreateSectionSF() 4316 @*/ 4317 PetscErrorCode DMGetSectionSF(DM dm, PetscSF *sf) 4318 { 4319 PetscInt nroots; 4320 PetscErrorCode ierr; 4321 4322 PetscFunctionBegin; 4323 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4324 PetscValidPointer(sf, 2); 4325 if (!dm->sectionSF) { 4326 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm),&dm->sectionSF);CHKERRQ(ierr); 4327 } 4328 ierr = PetscSFGetGraph(dm->sectionSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 4329 if (nroots < 0) { 4330 PetscSection section, gSection; 4331 4332 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 4333 if (section) { 4334 ierr = DMGetGlobalSection(dm, &gSection);CHKERRQ(ierr); 4335 ierr = DMCreateSectionSF(dm, section, gSection);CHKERRQ(ierr); 4336 } else { 4337 *sf = NULL; 4338 PetscFunctionReturn(0); 4339 } 4340 } 4341 *sf = dm->sectionSF; 4342 PetscFunctionReturn(0); 4343 } 4344 4345 /*@ 4346 DMSetSectionSF - Set the PetscSF encoding the parallel dof overlap for the DM 4347 4348 Input Parameters: 4349 + dm - The DM 4350 - sf - The PetscSF 4351 4352 Level: intermediate 4353 4354 Note: Any previous SF is destroyed 4355 4356 .seealso: DMGetSectionSF(), DMCreateSectionSF() 4357 @*/ 4358 PetscErrorCode DMSetSectionSF(DM dm, PetscSF sf) 4359 { 4360 PetscErrorCode ierr; 4361 4362 PetscFunctionBegin; 4363 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4364 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4365 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4366 ierr = PetscSFDestroy(&dm->sectionSF);CHKERRQ(ierr); 4367 dm->sectionSF = sf; 4368 PetscFunctionReturn(0); 4369 } 4370 4371 /*@C 4372 DMCreateSectionSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 4373 describing the data layout. 4374 4375 Input Parameters: 4376 + dm - The DM 4377 . localSection - PetscSection describing the local data layout 4378 - globalSection - PetscSection describing the global data layout 4379 4380 Notes: One usually uses DMGetSectionSF() to obtain the PetscSF 4381 4382 Level: developer 4383 4384 Developer Note: Since this routine has for arguments the two sections from the DM and puts the resulting PetscSF 4385 directly into the DM, perhaps this function should not take the local and global sections as 4386 input and should just obtain them from the DM? 4387 4388 .seealso: DMGetSectionSF(), DMSetSectionSF(), DMGetLocalSection(), DMGetGlobalSection() 4389 @*/ 4390 PetscErrorCode DMCreateSectionSF(DM dm, PetscSection localSection, PetscSection globalSection) 4391 { 4392 MPI_Comm comm; 4393 PetscLayout layout; 4394 const PetscInt *ranges; 4395 PetscInt *local; 4396 PetscSFNode *remote; 4397 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 4398 PetscMPIInt size, rank; 4399 PetscErrorCode ierr; 4400 4401 PetscFunctionBegin; 4402 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4403 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4404 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 4405 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4406 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 4407 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 4408 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 4409 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 4410 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 4411 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 4412 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 4413 for (p = pStart; p < pEnd; ++p) { 4414 PetscInt gdof, gcdof; 4415 4416 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4417 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4418 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)); 4419 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4420 } 4421 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 4422 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 4423 for (p = pStart, l = 0; p < pEnd; ++p) { 4424 const PetscInt *cind; 4425 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 4426 4427 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 4428 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 4429 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 4430 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 4431 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4432 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4433 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 4434 if (!gdof) continue; /* Censored point */ 4435 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4436 if (gsize != dof-cdof) { 4437 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); 4438 cdof = 0; /* Ignore constraints */ 4439 } 4440 for (d = 0, c = 0; d < dof; ++d) { 4441 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 4442 local[l+d-c] = off+d; 4443 } 4444 if (gdof < 0) { 4445 for (d = 0; d < gsize; ++d, ++l) { 4446 PetscInt offset = -(goff+1) + d, r; 4447 4448 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 4449 if (r < 0) r = -(r+2); 4450 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); 4451 remote[l].rank = r; 4452 remote[l].index = offset - ranges[r]; 4453 } 4454 } else { 4455 for (d = 0; d < gsize; ++d, ++l) { 4456 remote[l].rank = rank; 4457 remote[l].index = goff+d - ranges[rank]; 4458 } 4459 } 4460 } 4461 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 4462 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 4463 ierr = PetscSFSetGraph(dm->sectionSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 4464 PetscFunctionReturn(0); 4465 } 4466 4467 /*@ 4468 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 4469 4470 Input Parameter: 4471 . dm - The DM 4472 4473 Output Parameter: 4474 . sf - The PetscSF 4475 4476 Level: intermediate 4477 4478 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4479 4480 .seealso: DMSetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF() 4481 @*/ 4482 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 4483 { 4484 PetscFunctionBegin; 4485 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4486 PetscValidPointer(sf, 2); 4487 *sf = dm->sf; 4488 PetscFunctionReturn(0); 4489 } 4490 4491 /*@ 4492 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 4493 4494 Input Parameters: 4495 + dm - The DM 4496 - sf - The PetscSF 4497 4498 Level: intermediate 4499 4500 .seealso: DMGetPointSF(), DMGetSectionSF(), DMSetSectionSF(), DMCreateSectionSF() 4501 @*/ 4502 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 4503 { 4504 PetscErrorCode ierr; 4505 4506 PetscFunctionBegin; 4507 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4508 if (sf) PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4509 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4510 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 4511 dm->sf = sf; 4512 PetscFunctionReturn(0); 4513 } 4514 4515 static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc) 4516 { 4517 PetscClassId id; 4518 PetscErrorCode ierr; 4519 4520 PetscFunctionBegin; 4521 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 4522 if (id == PETSCFE_CLASSID) { 4523 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr); 4524 } else if (id == PETSCFV_CLASSID) { 4525 ierr = DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr); 4526 } else { 4527 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr); 4528 } 4529 PetscFunctionReturn(0); 4530 } 4531 4532 static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew) 4533 { 4534 RegionField *tmpr; 4535 PetscInt Nf = dm->Nf, f; 4536 PetscErrorCode ierr; 4537 4538 PetscFunctionBegin; 4539 if (Nf >= NfNew) PetscFunctionReturn(0); 4540 ierr = PetscMalloc1(NfNew, &tmpr);CHKERRQ(ierr); 4541 for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f]; 4542 for (f = Nf; f < NfNew; ++f) {tmpr[f].disc = NULL; tmpr[f].label = NULL;} 4543 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4544 dm->Nf = NfNew; 4545 dm->fields = tmpr; 4546 PetscFunctionReturn(0); 4547 } 4548 4549 /*@ 4550 DMClearFields - Remove all fields from the DM 4551 4552 Logically collective on dm 4553 4554 Input Parameter: 4555 . dm - The DM 4556 4557 Level: intermediate 4558 4559 .seealso: DMGetNumFields(), DMSetNumFields(), DMSetField() 4560 @*/ 4561 PetscErrorCode DMClearFields(DM dm) 4562 { 4563 PetscInt f; 4564 PetscErrorCode ierr; 4565 4566 PetscFunctionBegin; 4567 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4568 for (f = 0; f < dm->Nf; ++f) { 4569 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4570 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4571 } 4572 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4573 dm->fields = NULL; 4574 dm->Nf = 0; 4575 PetscFunctionReturn(0); 4576 } 4577 4578 /*@ 4579 DMGetNumFields - Get the number of fields in the DM 4580 4581 Not collective 4582 4583 Input Parameter: 4584 . dm - The DM 4585 4586 Output Parameter: 4587 . Nf - The number of fields 4588 4589 Level: intermediate 4590 4591 .seealso: DMSetNumFields(), DMSetField() 4592 @*/ 4593 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 4594 { 4595 PetscFunctionBegin; 4596 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4597 PetscValidIntPointer(numFields, 2); 4598 *numFields = dm->Nf; 4599 PetscFunctionReturn(0); 4600 } 4601 4602 /*@ 4603 DMSetNumFields - Set the number of fields in the DM 4604 4605 Logically collective on dm 4606 4607 Input Parameters: 4608 + dm - The DM 4609 - Nf - The number of fields 4610 4611 Level: intermediate 4612 4613 .seealso: DMGetNumFields(), DMSetField() 4614 @*/ 4615 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 4616 { 4617 PetscInt Nf, f; 4618 PetscErrorCode ierr; 4619 4620 PetscFunctionBegin; 4621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4622 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4623 for (f = Nf; f < numFields; ++f) { 4624 PetscContainer obj; 4625 4626 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 4627 ierr = DMAddField(dm, NULL, (PetscObject) obj);CHKERRQ(ierr); 4628 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 4629 } 4630 PetscFunctionReturn(0); 4631 } 4632 4633 /*@ 4634 DMGetField - Return the discretization object for a given DM field 4635 4636 Not collective 4637 4638 Input Parameters: 4639 + dm - The DM 4640 - f - The field number 4641 4642 Output Parameters: 4643 + label - The label indicating the support of the field, or NULL for the entire mesh 4644 - field - The discretization object 4645 4646 Level: intermediate 4647 4648 .seealso: DMAddField(), DMSetField() 4649 @*/ 4650 PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *field) 4651 { 4652 PetscFunctionBegin; 4653 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4654 PetscValidPointer(field, 3); 4655 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); 4656 if (label) *label = dm->fields[f].label; 4657 if (field) *field = dm->fields[f].disc; 4658 PetscFunctionReturn(0); 4659 } 4660 4661 /*@ 4662 DMSetField - Set the discretization object for a given DM field 4663 4664 Logically collective on dm 4665 4666 Input Parameters: 4667 + dm - The DM 4668 . f - The field number 4669 . label - The label indicating the support of the field, or NULL for the entire mesh 4670 - field - The discretization object 4671 4672 Level: intermediate 4673 4674 .seealso: DMAddField(), DMGetField() 4675 @*/ 4676 PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject field) 4677 { 4678 PetscErrorCode ierr; 4679 4680 PetscFunctionBegin; 4681 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4682 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3); 4683 PetscValidHeader(field, 4); 4684 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 4685 ierr = DMFieldEnlarge_Static(dm, f+1);CHKERRQ(ierr); 4686 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4687 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4688 dm->fields[f].label = label; 4689 dm->fields[f].disc = field; 4690 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4691 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 4692 ierr = DMSetDefaultAdjacency_Private(dm, f, field);CHKERRQ(ierr); 4693 ierr = DMClearDS(dm);CHKERRQ(ierr); 4694 PetscFunctionReturn(0); 4695 } 4696 4697 /*@ 4698 DMAddField - Add the discretization object for the given DM field 4699 4700 Logically collective on dm 4701 4702 Input Parameters: 4703 + dm - The DM 4704 . label - The label indicating the support of the field, or NULL for the entire mesh 4705 - field - The discretization object 4706 4707 Level: intermediate 4708 4709 .seealso: DMSetField(), DMGetField() 4710 @*/ 4711 PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject field) 4712 { 4713 PetscInt Nf = dm->Nf; 4714 PetscErrorCode ierr; 4715 4716 PetscFunctionBegin; 4717 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4718 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3); 4719 PetscValidHeader(field, 3); 4720 ierr = DMFieldEnlarge_Static(dm, Nf+1);CHKERRQ(ierr); 4721 dm->fields[Nf].label = label; 4722 dm->fields[Nf].disc = field; 4723 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4724 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 4725 ierr = DMSetDefaultAdjacency_Private(dm, Nf, field);CHKERRQ(ierr); 4726 ierr = DMClearDS(dm);CHKERRQ(ierr); 4727 PetscFunctionReturn(0); 4728 } 4729 4730 /*@ 4731 DMCopyFields - Copy the discretizations for the DM into another DM 4732 4733 Collective on dm 4734 4735 Input Parameter: 4736 . dm - The DM 4737 4738 Output Parameter: 4739 . newdm - The DM 4740 4741 Level: advanced 4742 4743 .seealso: DMGetField(), DMSetField(), DMAddField(), DMCopyDS(), DMGetDS(), DMGetCellDS() 4744 @*/ 4745 PetscErrorCode DMCopyFields(DM dm, DM newdm) 4746 { 4747 PetscInt Nf, f; 4748 PetscErrorCode ierr; 4749 4750 PetscFunctionBegin; 4751 if (dm == newdm) PetscFunctionReturn(0); 4752 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4753 ierr = DMClearFields(newdm);CHKERRQ(ierr); 4754 for (f = 0; f < Nf; ++f) { 4755 DMLabel label; 4756 PetscObject field; 4757 PetscBool useCone, useClosure; 4758 4759 ierr = DMGetField(dm, f, &label, &field);CHKERRQ(ierr); 4760 ierr = DMSetField(newdm, f, label, field);CHKERRQ(ierr); 4761 ierr = DMGetAdjacency(dm, f, &useCone, &useClosure);CHKERRQ(ierr); 4762 ierr = DMSetAdjacency(newdm, f, useCone, useClosure);CHKERRQ(ierr); 4763 } 4764 PetscFunctionReturn(0); 4765 } 4766 4767 /*@ 4768 DMGetAdjacency - Returns the flags for determining variable influence 4769 4770 Not collective 4771 4772 Input Parameters: 4773 + dm - The DM object 4774 - f - The field number, or PETSC_DEFAULT for the default adjacency 4775 4776 Output Parameter: 4777 + useCone - Flag for variable influence starting with the cone operation 4778 - useClosure - Flag for variable influence using transitive closure 4779 4780 Notes: 4781 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4782 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4783 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4784 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another. 4785 4786 Level: developer 4787 4788 .seealso: DMSetAdjacency(), DMGetField(), DMSetField() 4789 @*/ 4790 PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure) 4791 { 4792 PetscFunctionBegin; 4793 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4794 if (useCone) PetscValidBoolPointer(useCone, 3); 4795 if (useClosure) PetscValidBoolPointer(useClosure, 4); 4796 if (f < 0) { 4797 if (useCone) *useCone = dm->adjacency[0]; 4798 if (useClosure) *useClosure = dm->adjacency[1]; 4799 } else { 4800 PetscInt Nf; 4801 PetscErrorCode ierr; 4802 4803 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4804 if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf); 4805 if (useCone) *useCone = dm->fields[f].adjacency[0]; 4806 if (useClosure) *useClosure = dm->fields[f].adjacency[1]; 4807 } 4808 PetscFunctionReturn(0); 4809 } 4810 4811 /*@ 4812 DMSetAdjacency - Set the flags for determining variable influence 4813 4814 Not collective 4815 4816 Input Parameters: 4817 + dm - The DM object 4818 . f - The field number 4819 . useCone - Flag for variable influence starting with the cone operation 4820 - useClosure - Flag for variable influence using transitive closure 4821 4822 Notes: 4823 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4824 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4825 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4826 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another. 4827 4828 Level: developer 4829 4830 .seealso: DMGetAdjacency(), DMGetField(), DMSetField() 4831 @*/ 4832 PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure) 4833 { 4834 PetscFunctionBegin; 4835 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4836 if (f < 0) { 4837 dm->adjacency[0] = useCone; 4838 dm->adjacency[1] = useClosure; 4839 } else { 4840 PetscInt Nf; 4841 PetscErrorCode ierr; 4842 4843 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4844 if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf); 4845 dm->fields[f].adjacency[0] = useCone; 4846 dm->fields[f].adjacency[1] = useClosure; 4847 } 4848 PetscFunctionReturn(0); 4849 } 4850 4851 /*@ 4852 DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined 4853 4854 Not collective 4855 4856 Input Parameters: 4857 . dm - The DM object 4858 4859 Output Parameter: 4860 + useCone - Flag for variable influence starting with the cone operation 4861 - useClosure - Flag for variable influence using transitive closure 4862 4863 Notes: 4864 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4865 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4866 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4867 4868 Level: developer 4869 4870 .seealso: DMSetBasicAdjacency(), DMGetField(), DMSetField() 4871 @*/ 4872 PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure) 4873 { 4874 PetscInt Nf; 4875 PetscErrorCode ierr; 4876 4877 PetscFunctionBegin; 4878 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4879 if (useCone) PetscValidBoolPointer(useCone, 3); 4880 if (useClosure) PetscValidBoolPointer(useClosure, 4); 4881 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4882 if (!Nf) { 4883 ierr = DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 4884 } else { 4885 ierr = DMGetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr); 4886 } 4887 PetscFunctionReturn(0); 4888 } 4889 4890 /*@ 4891 DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined 4892 4893 Not collective 4894 4895 Input Parameters: 4896 + dm - The DM object 4897 . useCone - Flag for variable influence starting with the cone operation 4898 - useClosure - Flag for variable influence using transitive closure 4899 4900 Notes: 4901 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4902 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4903 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4904 4905 Level: developer 4906 4907 .seealso: DMGetBasicAdjacency(), DMGetField(), DMSetField() 4908 @*/ 4909 PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure) 4910 { 4911 PetscInt Nf; 4912 PetscErrorCode ierr; 4913 4914 PetscFunctionBegin; 4915 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4916 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4917 if (!Nf) { 4918 ierr = DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 4919 } else { 4920 ierr = DMSetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr); 4921 } 4922 PetscFunctionReturn(0); 4923 } 4924 4925 static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew) 4926 { 4927 DMSpace *tmpd; 4928 PetscInt Nds = dm->Nds, s; 4929 PetscErrorCode ierr; 4930 4931 PetscFunctionBegin; 4932 if (Nds >= NdsNew) PetscFunctionReturn(0); 4933 ierr = PetscMalloc1(NdsNew, &tmpd);CHKERRQ(ierr); 4934 for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s]; 4935 for (s = Nds; s < NdsNew; ++s) {tmpd[s].ds = NULL; tmpd[s].label = NULL; tmpd[s].fields = NULL;} 4936 ierr = PetscFree(dm->probs);CHKERRQ(ierr); 4937 dm->Nds = NdsNew; 4938 dm->probs = tmpd; 4939 PetscFunctionReturn(0); 4940 } 4941 4942 /*@ 4943 DMGetNumDS - Get the number of discrete systems in the DM 4944 4945 Not collective 4946 4947 Input Parameter: 4948 . dm - The DM 4949 4950 Output Parameter: 4951 . Nds - The number of PetscDS objects 4952 4953 Level: intermediate 4954 4955 .seealso: DMGetDS(), DMGetCellDS() 4956 @*/ 4957 PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds) 4958 { 4959 PetscFunctionBegin; 4960 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4961 PetscValidIntPointer(Nds, 2); 4962 *Nds = dm->Nds; 4963 PetscFunctionReturn(0); 4964 } 4965 4966 /*@ 4967 DMClearDS - Remove all discrete systems from the DM 4968 4969 Logically collective on dm 4970 4971 Input Parameter: 4972 . dm - The DM 4973 4974 Level: intermediate 4975 4976 .seealso: DMGetNumDS(), DMGetDS(), DMSetField() 4977 @*/ 4978 PetscErrorCode DMClearDS(DM dm) 4979 { 4980 PetscInt s; 4981 PetscErrorCode ierr; 4982 4983 PetscFunctionBegin; 4984 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4985 for (s = 0; s < dm->Nds; ++s) { 4986 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr); 4987 ierr = DMLabelDestroy(&dm->probs[s].label);CHKERRQ(ierr); 4988 ierr = ISDestroy(&dm->probs[s].fields);CHKERRQ(ierr); 4989 } 4990 ierr = PetscFree(dm->probs);CHKERRQ(ierr); 4991 dm->probs = NULL; 4992 dm->Nds = 0; 4993 PetscFunctionReturn(0); 4994 } 4995 4996 /*@ 4997 DMGetDS - Get the default PetscDS 4998 4999 Not collective 5000 5001 Input Parameter: 5002 . dm - The DM 5003 5004 Output Parameter: 5005 . prob - The default PetscDS 5006 5007 Level: intermediate 5008 5009 .seealso: DMGetCellDS(), DMGetRegionDS() 5010 @*/ 5011 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 5012 { 5013 PetscErrorCode ierr; 5014 5015 PetscFunctionBeginHot; 5016 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5017 PetscValidPointer(prob, 2); 5018 if (dm->Nds <= 0) { 5019 PetscDS ds; 5020 5021 ierr = PetscDSCreate(PetscObjectComm((PetscObject) dm), &ds);CHKERRQ(ierr); 5022 ierr = DMSetRegionDS(dm, NULL, NULL, ds);CHKERRQ(ierr); 5023 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr); 5024 } 5025 *prob = dm->probs[0].ds; 5026 PetscFunctionReturn(0); 5027 } 5028 5029 /*@ 5030 DMGetCellDS - Get the PetscDS defined on a given cell 5031 5032 Not collective 5033 5034 Input Parameters: 5035 + dm - The DM 5036 - point - Cell for the DS 5037 5038 Output Parameter: 5039 . prob - The PetscDS defined on the given cell 5040 5041 Level: developer 5042 5043 .seealso: DMGetDS(), DMSetRegionDS() 5044 @*/ 5045 PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *prob) 5046 { 5047 PetscDS probDef = NULL; 5048 PetscInt s; 5049 PetscErrorCode ierr; 5050 5051 PetscFunctionBeginHot; 5052 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5053 PetscValidPointer(prob, 3); 5054 *prob = NULL; 5055 for (s = 0; s < dm->Nds; ++s) { 5056 PetscInt val; 5057 5058 if (!dm->probs[s].label) {probDef = dm->probs[s].ds;} 5059 else { 5060 ierr = DMLabelGetValue(dm->probs[s].label, point, &val);CHKERRQ(ierr); 5061 if (val >= 0) {*prob = dm->probs[s].ds; break;} 5062 } 5063 } 5064 if (!*prob) *prob = probDef; 5065 PetscFunctionReturn(0); 5066 } 5067 5068 /*@ 5069 DMGetRegionDS - Get the PetscDS for a given mesh region, defined by a DMLabel 5070 5071 Not collective 5072 5073 Input Parameters: 5074 + dm - The DM 5075 - label - The DMLabel defining the mesh region, or NULL for the entire mesh 5076 5077 Output Parameters: 5078 + fields - The IS containing the DM field numbers for the fields in this DS, or NULL 5079 - prob - The PetscDS defined on the given region, or NULL 5080 5081 Note: If the label is missing, this function returns an error 5082 5083 Level: advanced 5084 5085 .seealso: DMGetRegionNumDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5086 @*/ 5087 PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds) 5088 { 5089 PetscInt Nds = dm->Nds, s; 5090 5091 PetscFunctionBegin; 5092 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5093 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 5094 if (fields) {PetscValidPointer(fields, 3); *fields = NULL;} 5095 if (ds) {PetscValidPointer(ds, 4); *ds = NULL;} 5096 for (s = 0; s < Nds; ++s) { 5097 if (dm->probs[s].label == label) { 5098 if (fields) *fields = dm->probs[s].fields; 5099 if (ds) *ds = dm->probs[s].ds; 5100 PetscFunctionReturn(0); 5101 } 5102 } 5103 PetscFunctionReturn(0); 5104 } 5105 5106 /*@ 5107 DMGetRegionNumDS - Get the PetscDS for a given mesh region, defined by the region number 5108 5109 Not collective 5110 5111 Input Parameters: 5112 + dm - The DM 5113 - num - The region number, in [0, Nds) 5114 5115 Output Parameters: 5116 + label - The region label, or NULL 5117 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL 5118 - prob - The PetscDS defined on the given region, or NULL 5119 5120 Level: advanced 5121 5122 .seealso: DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 5123 @*/ 5124 PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds) 5125 { 5126 PetscInt Nds; 5127 PetscErrorCode ierr; 5128 5129 PetscFunctionBegin; 5130 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5131 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5132 if ((num < 0) || (num >= Nds)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %D is not in [0, %D)", num, Nds); 5133 if (label) { 5134 PetscValidPointer(label, 3); 5135 *label = dm->probs[num].label; 5136 } 5137 if (fields) { 5138 PetscValidPointer(fields, 4); 5139 *fields = dm->probs[num].fields; 5140 } 5141 if (ds) { 5142 PetscValidPointer(ds, 5); 5143 *ds = dm->probs[num].ds; 5144 } 5145 PetscFunctionReturn(0); 5146 } 5147 5148 /*@ 5149 DMSetRegionDS - Set the PetscDS for a given mesh region, defined by a DMLabel 5150 5151 Collective on dm 5152 5153 Input Parameters: 5154 + dm - The DM 5155 . label - The DMLabel defining the mesh region, or NULL for the entire mesh 5156 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL for all fields 5157 - prob - The PetscDS defined on the given cell 5158 5159 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. If DS is replaced, 5160 the fields argument is ignored. 5161 5162 Level: advanced 5163 5164 .seealso: DMGetRegionDS(), DMGetDS(), DMGetCellDS() 5165 @*/ 5166 PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds) 5167 { 5168 PetscInt Nds = dm->Nds, s; 5169 PetscErrorCode ierr; 5170 5171 PetscFunctionBegin; 5172 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5173 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 5174 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 3); 5175 for (s = 0; s < Nds; ++s) { 5176 if (dm->probs[s].label == label) { 5177 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr); 5178 dm->probs[s].ds = ds; 5179 PetscFunctionReturn(0); 5180 } 5181 } 5182 ierr = DMDSEnlarge_Static(dm, Nds+1);CHKERRQ(ierr); 5183 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 5184 ierr = PetscObjectReference((PetscObject) fields);CHKERRQ(ierr); 5185 ierr = PetscObjectReference((PetscObject) ds);CHKERRQ(ierr); 5186 if (!label) { 5187 /* Put the NULL label at the front, so it is returned as the default */ 5188 for (s = Nds-1; s >=0; --s) dm->probs[s+1] = dm->probs[s]; 5189 Nds = 0; 5190 } 5191 dm->probs[Nds].label = label; 5192 dm->probs[Nds].fields = fields; 5193 dm->probs[Nds].ds = ds; 5194 PetscFunctionReturn(0); 5195 } 5196 5197 /*@ 5198 DMCreateDS - Create the discrete systems for the DM based upon the fields added to the DM 5199 5200 Collective on dm 5201 5202 Input Parameter: 5203 . dm - The DM 5204 5205 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. 5206 5207 Level: intermediate 5208 5209 .seealso: DMSetField, DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5210 @*/ 5211 PetscErrorCode DMCreateDS(DM dm) 5212 { 5213 MPI_Comm comm; 5214 PetscDS prob, probh = NULL; 5215 PetscInt dimEmbed, Nf = dm->Nf, f, s, field = 0, fieldh = 0; 5216 PetscBool doSetup = PETSC_TRUE; 5217 PetscErrorCode ierr; 5218 5219 PetscFunctionBegin; 5220 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5221 if (!dm->fields) PetscFunctionReturn(0); 5222 /* Can only handle two label cases right now: 5223 1) NULL 5224 2) Hybrid cells 5225 */ 5226 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 5227 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 5228 /* Create default DS */ 5229 ierr = DMGetRegionDS(dm, NULL, NULL, &prob);CHKERRQ(ierr); 5230 if (!prob) { 5231 IS fields; 5232 PetscInt *fld, nf; 5233 5234 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) ++nf; 5235 ierr = PetscMalloc1(nf, &fld);CHKERRQ(ierr); 5236 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) fld[nf++] = f; 5237 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr); 5238 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr); 5239 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr); 5240 ierr = ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);CHKERRQ(ierr); 5241 5242 ierr = PetscDSCreate(comm, &prob);CHKERRQ(ierr); 5243 ierr = DMSetRegionDS(dm, NULL, fields, prob);CHKERRQ(ierr); 5244 ierr = PetscDSDestroy(&prob);CHKERRQ(ierr); 5245 ierr = ISDestroy(&fields);CHKERRQ(ierr); 5246 ierr = DMGetRegionDS(dm, NULL, NULL, &prob);CHKERRQ(ierr); 5247 } 5248 ierr = PetscDSSetCoordinateDimension(prob, dimEmbed);CHKERRQ(ierr); 5249 /* Optionally create hybrid DS */ 5250 for (f = 0; f < Nf; ++f) { 5251 DMLabel label = dm->fields[f].label; 5252 PetscInt lStart, lEnd; 5253 5254 if (label) { 5255 DM plex; 5256 DMPolytopeType ct; 5257 IS fields; 5258 PetscInt *fld; 5259 PetscInt depth; 5260 5261 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 5262 ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 5263 ierr = DMDestroy(&plex);CHKERRQ(ierr); 5264 5265 ierr = DMLabelGetBounds(label, &lStart, &lEnd);CHKERRQ(ierr); 5266 ierr = DMPlexGetCellType(dm, lStart, &ct);CHKERRQ(ierr); 5267 switch (ct) { 5268 case DM_POLYTOPE_POINT_PRISM_TENSOR: 5269 case DM_POLYTOPE_SEG_PRISM_TENSOR: 5270 case DM_POLYTOPE_TRI_PRISM_TENSOR: 5271 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 5272 break; 5273 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only support labels over tensor prism cells right now"); 5274 } 5275 ierr = PetscDSCreate(comm, &probh);CHKERRQ(ierr); 5276 ierr = PetscMalloc1(1, &fld);CHKERRQ(ierr); 5277 fld[0] = f; 5278 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr); 5279 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr); 5280 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr); 5281 ierr = ISGeneralSetIndices(fields, 1, fld, PETSC_OWN_POINTER);CHKERRQ(ierr); 5282 ierr = DMSetRegionDS(dm, label, fields, probh);CHKERRQ(ierr); 5283 ierr = ISDestroy(&fields);CHKERRQ(ierr); 5284 ierr = PetscDSSetHybrid(probh, PETSC_TRUE);CHKERRQ(ierr); 5285 ierr = PetscDSSetCoordinateDimension(probh, dimEmbed);CHKERRQ(ierr); 5286 break; 5287 } 5288 } 5289 /* Set fields in DSes */ 5290 for (f = 0; f < Nf; ++f) { 5291 DMLabel label = dm->fields[f].label; 5292 PetscObject disc = dm->fields[f].disc; 5293 5294 if (!label) { 5295 ierr = PetscDSSetDiscretization(prob, field++, disc);CHKERRQ(ierr); 5296 if (probh) { 5297 PetscFE subfe; 5298 5299 ierr = PetscFEGetHeightSubspace((PetscFE) disc, 1, &subfe);CHKERRQ(ierr); 5300 ierr = PetscDSSetDiscretization(probh, fieldh++, (PetscObject) subfe);CHKERRQ(ierr); 5301 } 5302 } else { 5303 ierr = PetscDSSetDiscretization(probh, fieldh++, disc);CHKERRQ(ierr); 5304 } 5305 /* We allow people to have placeholder fields and construct the Section by hand */ 5306 { 5307 PetscClassId id; 5308 5309 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 5310 if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE; 5311 } 5312 } 5313 ierr = PetscDSDestroy(&probh);CHKERRQ(ierr); 5314 /* Setup DSes */ 5315 if (doSetup) { 5316 for (s = 0; s < dm->Nds; ++s) {ierr = PetscDSSetUp(dm->probs[s].ds);CHKERRQ(ierr);} 5317 } 5318 PetscFunctionReturn(0); 5319 } 5320 5321 /*@ 5322 DMCopyDS - Copy the discrete systems for the DM into another DM 5323 5324 Collective on dm 5325 5326 Input Parameter: 5327 . dm - The DM 5328 5329 Output Parameter: 5330 . newdm - The DM 5331 5332 Level: advanced 5333 5334 .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5335 @*/ 5336 PetscErrorCode DMCopyDS(DM dm, DM newdm) 5337 { 5338 PetscInt Nds, s; 5339 PetscErrorCode ierr; 5340 5341 PetscFunctionBegin; 5342 if (dm == newdm) PetscFunctionReturn(0); 5343 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5344 ierr = DMClearDS(newdm);CHKERRQ(ierr); 5345 for (s = 0; s < Nds; ++s) { 5346 DMLabel label; 5347 IS fields; 5348 PetscDS ds; 5349 5350 ierr = DMGetRegionNumDS(dm, s, &label, &fields, &ds);CHKERRQ(ierr); 5351 ierr = DMSetRegionDS(newdm, label, fields, ds);CHKERRQ(ierr); 5352 } 5353 PetscFunctionReturn(0); 5354 } 5355 5356 /*@ 5357 DMCopyDisc - Copy the fields and discrete systems for the DM into another DM 5358 5359 Collective on dm 5360 5361 Input Parameter: 5362 . dm - The DM 5363 5364 Output Parameter: 5365 . newdm - The DM 5366 5367 Level: advanced 5368 5369 .seealso: DMCopyFields(), DMCopyDS() 5370 @*/ 5371 PetscErrorCode DMCopyDisc(DM dm, DM newdm) 5372 { 5373 PetscErrorCode ierr; 5374 5375 PetscFunctionBegin; 5376 ierr = DMCopyFields(dm, newdm);CHKERRQ(ierr); 5377 ierr = DMCopyDS(dm, newdm);CHKERRQ(ierr); 5378 PetscFunctionReturn(0); 5379 } 5380 5381 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 5382 { 5383 DM dm_coord,dmc_coord; 5384 PetscErrorCode ierr; 5385 Vec coords,ccoords; 5386 Mat inject; 5387 PetscFunctionBegin; 5388 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5389 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 5390 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5391 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 5392 if (coords && !ccoords) { 5393 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 5394 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5395 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 5396 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 5397 ierr = MatDestroy(&inject);CHKERRQ(ierr); 5398 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 5399 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5400 } 5401 PetscFunctionReturn(0); 5402 } 5403 5404 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 5405 { 5406 DM dm_coord,subdm_coord; 5407 PetscErrorCode ierr; 5408 Vec coords,ccoords,clcoords; 5409 VecScatter *scat_i,*scat_g; 5410 PetscFunctionBegin; 5411 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5412 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 5413 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5414 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 5415 if (coords && !ccoords) { 5416 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 5417 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5418 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 5419 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 5420 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 5421 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5422 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5423 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5424 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5425 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 5426 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 5427 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 5428 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 5429 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5430 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 5431 ierr = PetscFree(scat_i);CHKERRQ(ierr); 5432 ierr = PetscFree(scat_g);CHKERRQ(ierr); 5433 } 5434 PetscFunctionReturn(0); 5435 } 5436 5437 /*@ 5438 DMGetDimension - Return the topological dimension of the DM 5439 5440 Not collective 5441 5442 Input Parameter: 5443 . dm - The DM 5444 5445 Output Parameter: 5446 . dim - The topological dimension 5447 5448 Level: beginner 5449 5450 .seealso: DMSetDimension(), DMCreate() 5451 @*/ 5452 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 5453 { 5454 PetscFunctionBegin; 5455 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5456 PetscValidIntPointer(dim, 2); 5457 *dim = dm->dim; 5458 PetscFunctionReturn(0); 5459 } 5460 5461 /*@ 5462 DMSetDimension - Set the topological dimension of the DM 5463 5464 Collective on dm 5465 5466 Input Parameters: 5467 + dm - The DM 5468 - dim - The topological dimension 5469 5470 Level: beginner 5471 5472 .seealso: DMGetDimension(), DMCreate() 5473 @*/ 5474 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 5475 { 5476 PetscDS ds; 5477 PetscErrorCode ierr; 5478 5479 PetscFunctionBegin; 5480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5481 PetscValidLogicalCollectiveInt(dm, dim, 2); 5482 dm->dim = dim; 5483 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5484 if (ds->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(ds, dm->dim);CHKERRQ(ierr);} 5485 PetscFunctionReturn(0); 5486 } 5487 5488 /*@ 5489 DMGetDimPoints - Get the half-open interval for all points of a given dimension 5490 5491 Collective on dm 5492 5493 Input Parameters: 5494 + dm - the DM 5495 - dim - the dimension 5496 5497 Output Parameters: 5498 + pStart - The first point of the given dimension 5499 - pEnd - The first point following points of the given dimension 5500 5501 Note: 5502 The points are vertices in the Hasse diagram encoding the topology. This is explained in 5503 https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme, 5504 then the interval is empty. 5505 5506 Level: intermediate 5507 5508 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 5509 @*/ 5510 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5511 { 5512 PetscInt d; 5513 PetscErrorCode ierr; 5514 5515 PetscFunctionBegin; 5516 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5517 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 5518 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 5519 if (!dm->ops->getdimpoints) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DM type %s does not implement DMGetDimPoints",((PetscObject)dm)->type_name); 5520 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 5521 PetscFunctionReturn(0); 5522 } 5523 5524 /*@ 5525 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 5526 5527 Collective on dm 5528 5529 Input Parameters: 5530 + dm - the DM 5531 - c - coordinate vector 5532 5533 Notes: 5534 The coordinates do include those for ghost points, which are in the local vector. 5535 5536 The vector c should be destroyed by the caller. 5537 5538 Level: intermediate 5539 5540 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5541 @*/ 5542 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 5543 { 5544 PetscErrorCode ierr; 5545 5546 PetscFunctionBegin; 5547 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5548 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5549 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5550 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5551 dm->coordinates = c; 5552 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5553 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5554 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5555 PetscFunctionReturn(0); 5556 } 5557 5558 /*@ 5559 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 5560 5561 Not collective 5562 5563 Input Parameters: 5564 + dm - the DM 5565 - c - coordinate vector 5566 5567 Notes: 5568 The coordinates of ghost points can be set using DMSetCoordinates() 5569 followed by DMGetCoordinatesLocal(). This is intended to enable the 5570 setting of ghost coordinates outside of the domain. 5571 5572 The vector c should be destroyed by the caller. 5573 5574 Level: intermediate 5575 5576 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 5577 @*/ 5578 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 5579 { 5580 PetscErrorCode ierr; 5581 5582 PetscFunctionBegin; 5583 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5584 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5585 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5586 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5587 5588 dm->coordinatesLocal = c; 5589 5590 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5591 PetscFunctionReturn(0); 5592 } 5593 5594 /*@ 5595 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 5596 5597 Collective on dm 5598 5599 Input Parameter: 5600 . dm - the DM 5601 5602 Output Parameter: 5603 . c - global coordinate vector 5604 5605 Note: 5606 This is a borrowed reference, so the user should NOT destroy this vector 5607 5608 Each process has only the local coordinates (does NOT have the ghost coordinates). 5609 5610 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5611 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5612 5613 Level: intermediate 5614 5615 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5616 @*/ 5617 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 5618 { 5619 PetscErrorCode ierr; 5620 5621 PetscFunctionBegin; 5622 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5623 PetscValidPointer(c,2); 5624 if (!dm->coordinates && dm->coordinatesLocal) { 5625 DM cdm = NULL; 5626 PetscBool localized; 5627 5628 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5629 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 5630 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5631 /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */ 5632 if (localized) { 5633 PetscInt cdim; 5634 5635 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5636 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5637 } 5638 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 5639 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5640 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5641 } 5642 *c = dm->coordinates; 5643 PetscFunctionReturn(0); 5644 } 5645 5646 /*@ 5647 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 5648 5649 Collective on dm 5650 5651 Input Parameter: 5652 . dm - the DM 5653 5654 Level: advanced 5655 5656 .seealso: DMGetCoordinatesLocalNoncollective() 5657 @*/ 5658 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 5659 { 5660 PetscErrorCode ierr; 5661 5662 PetscFunctionBegin; 5663 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5664 if (!dm->coordinatesLocal && dm->coordinates) { 5665 DM cdm = NULL; 5666 PetscBool localized; 5667 5668 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5669 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 5670 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5671 /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */ 5672 if (localized) { 5673 PetscInt cdim; 5674 5675 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5676 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5677 } 5678 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 5679 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5680 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5681 } 5682 PetscFunctionReturn(0); 5683 } 5684 5685 /*@ 5686 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 5687 5688 Collective on dm 5689 5690 Input Parameter: 5691 . dm - the DM 5692 5693 Output Parameter: 5694 . c - coordinate vector 5695 5696 Note: 5697 This is a borrowed reference, so the user should NOT destroy this vector 5698 5699 Each process has the local and ghost coordinates 5700 5701 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5702 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5703 5704 Level: intermediate 5705 5706 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 5707 @*/ 5708 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 5709 { 5710 PetscErrorCode ierr; 5711 5712 PetscFunctionBegin; 5713 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5714 PetscValidPointer(c,2); 5715 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 5716 *c = dm->coordinatesLocal; 5717 PetscFunctionReturn(0); 5718 } 5719 5720 /*@ 5721 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 5722 5723 Not collective 5724 5725 Input Parameter: 5726 . dm - the DM 5727 5728 Output Parameter: 5729 . c - coordinate vector 5730 5731 Level: advanced 5732 5733 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 5734 @*/ 5735 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 5736 { 5737 PetscFunctionBegin; 5738 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5739 PetscValidPointer(c,2); 5740 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 5741 *c = dm->coordinatesLocal; 5742 PetscFunctionReturn(0); 5743 } 5744 5745 /*@ 5746 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 5747 5748 Not collective 5749 5750 Input Parameter: 5751 + dm - the DM 5752 - p - the IS of points whose coordinates will be returned 5753 5754 Output Parameter: 5755 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 5756 - pCoord - the Vec with coordinates of points in p 5757 5758 Note: 5759 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 5760 5761 This creates a new vector, so the user SHOULD destroy this vector 5762 5763 Each process has the local and ghost coordinates 5764 5765 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5766 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5767 5768 Level: advanced 5769 5770 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 5771 @*/ 5772 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 5773 { 5774 PetscSection cs, newcs; 5775 Vec coords; 5776 const PetscScalar *arr; 5777 PetscScalar *newarr=NULL; 5778 PetscInt n; 5779 PetscErrorCode ierr; 5780 5781 PetscFunctionBegin; 5782 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5783 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 5784 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 5785 if (pCoord) PetscValidPointer(pCoord, 4); 5786 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 5787 if (!dm->coordinateDM || !dm->coordinateDM->localSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 5788 cs = dm->coordinateDM->localSection; 5789 coords = dm->coordinatesLocal; 5790 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 5791 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 5792 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 5793 if (pCoord) { 5794 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 5795 /* set array in two steps to mimic PETSC_OWN_POINTER */ 5796 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 5797 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 5798 } else { 5799 ierr = PetscFree(newarr);CHKERRQ(ierr); 5800 } 5801 if (pCoordSection) {*pCoordSection = newcs;} 5802 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 5803 PetscFunctionReturn(0); 5804 } 5805 5806 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 5807 { 5808 PetscErrorCode ierr; 5809 5810 PetscFunctionBegin; 5811 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5812 PetscValidPointer(field,2); 5813 if (!dm->coordinateField) { 5814 if (dm->ops->createcoordinatefield) { 5815 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 5816 } 5817 } 5818 *field = dm->coordinateField; 5819 PetscFunctionReturn(0); 5820 } 5821 5822 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 5823 { 5824 PetscErrorCode ierr; 5825 5826 PetscFunctionBegin; 5827 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5828 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 5829 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 5830 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 5831 dm->coordinateField = field; 5832 PetscFunctionReturn(0); 5833 } 5834 5835 /*@ 5836 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 5837 5838 Collective on dm 5839 5840 Input Parameter: 5841 . dm - the DM 5842 5843 Output Parameter: 5844 . cdm - coordinate DM 5845 5846 Level: intermediate 5847 5848 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 5849 @*/ 5850 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 5851 { 5852 PetscErrorCode ierr; 5853 5854 PetscFunctionBegin; 5855 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5856 PetscValidPointer(cdm,2); 5857 if (!dm->coordinateDM) { 5858 DM cdm; 5859 5860 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 5861 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 5862 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 5863 * until the call to CreateCoordinateDM) */ 5864 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 5865 dm->coordinateDM = cdm; 5866 } 5867 *cdm = dm->coordinateDM; 5868 PetscFunctionReturn(0); 5869 } 5870 5871 /*@ 5872 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 5873 5874 Logically Collective on dm 5875 5876 Input Parameters: 5877 + dm - the DM 5878 - cdm - coordinate DM 5879 5880 Level: intermediate 5881 5882 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 5883 @*/ 5884 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 5885 { 5886 PetscErrorCode ierr; 5887 5888 PetscFunctionBegin; 5889 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5890 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 5891 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5892 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 5893 dm->coordinateDM = cdm; 5894 PetscFunctionReturn(0); 5895 } 5896 5897 /*@ 5898 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 5899 5900 Not Collective 5901 5902 Input Parameter: 5903 . dm - The DM object 5904 5905 Output Parameter: 5906 . dim - The embedding dimension 5907 5908 Level: intermediate 5909 5910 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 5911 @*/ 5912 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 5913 { 5914 PetscFunctionBegin; 5915 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5916 PetscValidIntPointer(dim, 2); 5917 if (dm->dimEmbed == PETSC_DEFAULT) { 5918 dm->dimEmbed = dm->dim; 5919 } 5920 *dim = dm->dimEmbed; 5921 PetscFunctionReturn(0); 5922 } 5923 5924 /*@ 5925 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 5926 5927 Not Collective 5928 5929 Input Parameters: 5930 + dm - The DM object 5931 - dim - The embedding dimension 5932 5933 Level: intermediate 5934 5935 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 5936 @*/ 5937 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 5938 { 5939 PetscDS ds; 5940 PetscErrorCode ierr; 5941 5942 PetscFunctionBegin; 5943 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5944 dm->dimEmbed = dim; 5945 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5946 ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr); 5947 PetscFunctionReturn(0); 5948 } 5949 5950 /*@ 5951 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 5952 5953 Collective on dm 5954 5955 Input Parameter: 5956 . dm - The DM object 5957 5958 Output Parameter: 5959 . section - The PetscSection object 5960 5961 Level: intermediate 5962 5963 .seealso: DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 5964 @*/ 5965 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 5966 { 5967 DM cdm; 5968 PetscErrorCode ierr; 5969 5970 PetscFunctionBegin; 5971 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5972 PetscValidPointer(section, 2); 5973 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5974 ierr = DMGetLocalSection(cdm, section);CHKERRQ(ierr); 5975 PetscFunctionReturn(0); 5976 } 5977 5978 /*@ 5979 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 5980 5981 Not Collective 5982 5983 Input Parameters: 5984 + dm - The DM object 5985 . dim - The embedding dimension, or PETSC_DETERMINE 5986 - section - The PetscSection object 5987 5988 Level: intermediate 5989 5990 .seealso: DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 5991 @*/ 5992 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 5993 { 5994 DM cdm; 5995 PetscErrorCode ierr; 5996 5997 PetscFunctionBegin; 5998 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5999 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 6000 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6001 ierr = DMSetLocalSection(cdm, section);CHKERRQ(ierr); 6002 if (dim == PETSC_DETERMINE) { 6003 PetscInt d = PETSC_DEFAULT; 6004 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 6005 6006 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6007 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6008 pStart = PetscMax(vStart, pStart); 6009 pEnd = PetscMin(vEnd, pEnd); 6010 for (v = pStart; v < pEnd; ++v) { 6011 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 6012 if (dd) {d = dd; break;} 6013 } 6014 if (d >= 0) {ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);} 6015 } 6016 PetscFunctionReturn(0); 6017 } 6018 6019 /*@C 6020 DMGetPeriodicity - Get the description of mesh periodicity 6021 6022 Input Parameters: 6023 . dm - The DM object 6024 6025 Output Parameters: 6026 + per - Whether the DM is periodic or not 6027 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 6028 . L - If we assume the mesh is a torus, this is the length of each coordinate 6029 - bd - This describes the type of periodicity in each topological dimension 6030 6031 Level: developer 6032 6033 .seealso: DMGetPeriodicity() 6034 @*/ 6035 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 6036 { 6037 PetscFunctionBegin; 6038 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6039 if (per) *per = dm->periodic; 6040 if (L) *L = dm->L; 6041 if (maxCell) *maxCell = dm->maxCell; 6042 if (bd) *bd = dm->bdtype; 6043 PetscFunctionReturn(0); 6044 } 6045 6046 /*@C 6047 DMSetPeriodicity - Set the description of mesh periodicity 6048 6049 Input Parameters: 6050 + dm - The DM object 6051 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 6052 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 6053 . L - If we assume the mesh is a torus, this is the length of each coordinate 6054 - bd - This describes the type of periodicity in each topological dimension 6055 6056 Level: developer 6057 6058 .seealso: DMGetPeriodicity() 6059 @*/ 6060 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 6061 { 6062 PetscInt dim, d; 6063 PetscErrorCode ierr; 6064 6065 PetscFunctionBegin; 6066 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6067 PetscValidLogicalCollectiveBool(dm,per,2); 6068 if (maxCell) {PetscValidRealPointer(maxCell,3);} 6069 if (L) {PetscValidRealPointer(L,4);} 6070 if (bd) {PetscValidPointer(bd,5);} 6071 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6072 if (maxCell) { 6073 if (!dm->maxCell) {ierr = PetscMalloc1(dim, &dm->maxCell);CHKERRQ(ierr);} 6074 for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d]; 6075 } 6076 if (L) { 6077 if (!dm->L) {ierr = PetscMalloc1(dim, &dm->L);CHKERRQ(ierr);} 6078 for (d = 0; d < dim; ++d) dm->L[d] = L[d]; 6079 } 6080 if (bd) { 6081 if (!dm->bdtype) {ierr = PetscMalloc1(dim, &dm->bdtype);CHKERRQ(ierr);} 6082 for (d = 0; d < dim; ++d) dm->bdtype[d] = bd[d]; 6083 } 6084 dm->periodic = per; 6085 PetscFunctionReturn(0); 6086 } 6087 6088 /*@ 6089 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. 6090 6091 Input Parameters: 6092 + dm - The DM 6093 . in - The input coordinate point (dim numbers) 6094 - endpoint - Include the endpoint L_i 6095 6096 Output Parameter: 6097 . out - The localized coordinate point 6098 6099 Level: developer 6100 6101 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6102 @*/ 6103 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 6104 { 6105 PetscInt dim, d; 6106 PetscErrorCode ierr; 6107 6108 PetscFunctionBegin; 6109 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 6110 if (!dm->maxCell) { 6111 for (d = 0; d < dim; ++d) out[d] = in[d]; 6112 } else { 6113 if (endpoint) { 6114 for (d = 0; d < dim; ++d) { 6115 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)) { 6116 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 6117 } else { 6118 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6119 } 6120 } 6121 } else { 6122 for (d = 0; d < dim; ++d) { 6123 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6124 } 6125 } 6126 } 6127 PetscFunctionReturn(0); 6128 } 6129 6130 /* 6131 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. 6132 6133 Input Parameters: 6134 + dm - The DM 6135 . dim - The spatial dimension 6136 . anchor - The anchor point, the input point can be no more than maxCell away from it 6137 - in - The input coordinate point (dim numbers) 6138 6139 Output Parameter: 6140 . out - The localized coordinate point 6141 6142 Level: developer 6143 6144 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 6145 6146 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6147 */ 6148 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6149 { 6150 PetscInt d; 6151 6152 PetscFunctionBegin; 6153 if (!dm->maxCell) { 6154 for (d = 0; d < dim; ++d) out[d] = in[d]; 6155 } else { 6156 for (d = 0; d < dim; ++d) { 6157 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 6158 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6159 } else { 6160 out[d] = in[d]; 6161 } 6162 } 6163 } 6164 PetscFunctionReturn(0); 6165 } 6166 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 6167 { 6168 PetscInt d; 6169 6170 PetscFunctionBegin; 6171 if (!dm->maxCell) { 6172 for (d = 0; d < dim; ++d) out[d] = in[d]; 6173 } else { 6174 for (d = 0; d < dim; ++d) { 6175 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 6176 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6177 } else { 6178 out[d] = in[d]; 6179 } 6180 } 6181 } 6182 PetscFunctionReturn(0); 6183 } 6184 6185 /* 6186 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. 6187 6188 Input Parameters: 6189 + dm - The DM 6190 . dim - The spatial dimension 6191 . anchor - The anchor point, the input point can be no more than maxCell away from it 6192 . in - The input coordinate delta (dim numbers) 6193 - out - The input coordinate point (dim numbers) 6194 6195 Output Parameter: 6196 . out - The localized coordinate in + out 6197 6198 Level: developer 6199 6200 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 6201 6202 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 6203 */ 6204 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6205 { 6206 PetscInt d; 6207 6208 PetscFunctionBegin; 6209 if (!dm->maxCell) { 6210 for (d = 0; d < dim; ++d) out[d] += in[d]; 6211 } else { 6212 for (d = 0; d < dim; ++d) { 6213 const PetscReal maxC = dm->maxCell[d]; 6214 6215 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) { 6216 const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6217 6218 if (PetscAbsScalar(newCoord - anchor[d]) > maxC) 6219 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])); 6220 out[d] += newCoord; 6221 } else { 6222 out[d] += in[d]; 6223 } 6224 } 6225 } 6226 PetscFunctionReturn(0); 6227 } 6228 6229 /*@ 6230 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 6231 6232 Not collective 6233 6234 Input Parameter: 6235 . dm - The DM 6236 6237 Output Parameter: 6238 areLocalized - True if localized 6239 6240 Level: developer 6241 6242 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 6243 @*/ 6244 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 6245 { 6246 DM cdm; 6247 PetscSection coordSection; 6248 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 6249 PetscBool isPlex, alreadyLocalized; 6250 PetscErrorCode ierr; 6251 6252 PetscFunctionBegin; 6253 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6254 PetscValidBoolPointer(areLocalized, 2); 6255 *areLocalized = PETSC_FALSE; 6256 6257 /* We need some generic way of refering to cells/vertices */ 6258 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6259 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 6260 if (!isPlex) PetscFunctionReturn(0); 6261 6262 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6263 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6264 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 6265 alreadyLocalized = PETSC_FALSE; 6266 for (c = cStart; c < cEnd; ++c) { 6267 if (c < sStart || c >= sEnd) continue; 6268 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 6269 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 6270 } 6271 *areLocalized = alreadyLocalized; 6272 PetscFunctionReturn(0); 6273 } 6274 6275 /*@ 6276 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 6277 6278 Collective on dm 6279 6280 Input Parameter: 6281 . dm - The DM 6282 6283 Output Parameter: 6284 areLocalized - True if localized 6285 6286 Level: developer 6287 6288 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 6289 @*/ 6290 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 6291 { 6292 PetscBool localized; 6293 PetscErrorCode ierr; 6294 6295 PetscFunctionBegin; 6296 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6297 PetscValidBoolPointer(areLocalized, 2); 6298 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 6299 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6300 PetscFunctionReturn(0); 6301 } 6302 6303 /*@ 6304 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 6305 6306 Collective on dm 6307 6308 Input Parameter: 6309 . dm - The DM 6310 6311 Level: developer 6312 6313 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 6314 @*/ 6315 PetscErrorCode DMLocalizeCoordinates(DM dm) 6316 { 6317 DM cdm; 6318 PetscSection coordSection, cSection; 6319 Vec coordinates, cVec; 6320 PetscScalar *coords, *coords2, *anchor, *localized; 6321 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 6322 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 6323 PetscInt maxHeight = 0, h; 6324 PetscInt *pStart = NULL, *pEnd = NULL; 6325 PetscErrorCode ierr; 6326 6327 PetscFunctionBegin; 6328 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6329 if (!dm->periodic) PetscFunctionReturn(0); 6330 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 6331 if (alreadyLocalized) PetscFunctionReturn(0); 6332 6333 /* We need some generic way of refering to cells/vertices */ 6334 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6335 { 6336 PetscBool isplex; 6337 6338 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 6339 if (isplex) { 6340 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6341 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 6342 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6343 pEnd = &pStart[maxHeight + 1]; 6344 newStart = vStart; 6345 newEnd = vEnd; 6346 for (h = 0; h <= maxHeight; h++) { 6347 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 6348 newStart = PetscMin(newStart,pStart[h]); 6349 newEnd = PetscMax(newEnd,pEnd[h]); 6350 } 6351 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 6352 } 6353 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6354 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 6355 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6356 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 6357 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 6358 6359 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 6360 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 6361 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 6362 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 6363 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 6364 6365 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6366 localized = &anchor[bs]; 6367 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 6368 for (h = 0; h <= maxHeight; h++) { 6369 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6370 6371 for (c = cStart; c < cEnd; ++c) { 6372 PetscScalar *cellCoords = NULL; 6373 PetscInt b; 6374 6375 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 6376 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6377 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6378 for (d = 0; d < dof/bs; ++d) { 6379 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 6380 for (b = 0; b < bs; b++) { 6381 if (cellCoords[d*bs + b] != localized[b]) break; 6382 } 6383 if (b < bs) break; 6384 } 6385 if (d < dof/bs) { 6386 if (c >= sStart && c < sEnd) { 6387 PetscInt cdof; 6388 6389 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 6390 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 6391 } 6392 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 6393 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 6394 } 6395 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6396 } 6397 } 6398 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6399 if (alreadyLocalizedGlobal) { 6400 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6401 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6402 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6403 PetscFunctionReturn(0); 6404 } 6405 for (v = vStart; v < vEnd; ++v) { 6406 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6407 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 6408 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 6409 } 6410 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 6411 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 6412 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 6413 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 6414 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 6415 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 6416 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 6417 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6418 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 6419 for (v = vStart; v < vEnd; ++v) { 6420 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6421 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6422 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 6423 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 6424 } 6425 for (h = 0; h <= maxHeight; h++) { 6426 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6427 6428 for (c = cStart; c < cEnd; ++c) { 6429 PetscScalar *cellCoords = NULL; 6430 PetscInt b, cdof; 6431 6432 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 6433 if (!cdof) continue; 6434 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6435 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 6436 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6437 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 6438 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6439 } 6440 } 6441 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6442 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6443 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6444 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 6445 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 6446 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 6447 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 6448 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6449 PetscFunctionReturn(0); 6450 } 6451 6452 /*@ 6453 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 6454 6455 Collective on v (see explanation below) 6456 6457 Input Parameters: 6458 + dm - The DM 6459 . v - The Vec of points 6460 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 6461 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 6462 6463 Output Parameter: 6464 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 6465 - cells - The PetscSF containing the ranks and local indices of the containing points. 6466 6467 6468 Level: developer 6469 6470 Notes: 6471 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 6472 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 6473 6474 If *cellSF is NULL on input, a PetscSF will be created. 6475 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 6476 6477 An array that maps each point to its containing cell can be obtained with 6478 6479 $ const PetscSFNode *cells; 6480 $ PetscInt nFound; 6481 $ const PetscInt *found; 6482 $ 6483 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 6484 6485 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 6486 the index of the cell in its rank's local numbering. 6487 6488 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 6489 @*/ 6490 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 6491 { 6492 PetscErrorCode ierr; 6493 6494 PetscFunctionBegin; 6495 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6496 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 6497 PetscValidPointer(cellSF,4); 6498 if (*cellSF) { 6499 PetscMPIInt result; 6500 6501 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 6502 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 6503 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 6504 } else { 6505 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 6506 } 6507 if (!dm->ops->locatepoints) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 6508 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6509 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 6510 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6511 PetscFunctionReturn(0); 6512 } 6513 6514 /*@ 6515 DMGetOutputDM - Retrieve the DM associated with the layout for output 6516 6517 Collective on dm 6518 6519 Input Parameter: 6520 . dm - The original DM 6521 6522 Output Parameter: 6523 . odm - The DM which provides the layout for output 6524 6525 Level: intermediate 6526 6527 .seealso: VecView(), DMGetGlobalSection() 6528 @*/ 6529 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 6530 { 6531 PetscSection section; 6532 PetscBool hasConstraints, ghasConstraints; 6533 PetscErrorCode ierr; 6534 6535 PetscFunctionBegin; 6536 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6537 PetscValidPointer(odm,2); 6538 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 6539 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 6540 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 6541 if (!ghasConstraints) { 6542 *odm = dm; 6543 PetscFunctionReturn(0); 6544 } 6545 if (!dm->dmBC) { 6546 PetscSection newSection, gsection; 6547 PetscSF sf; 6548 6549 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 6550 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 6551 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 6552 ierr = DMSetLocalSection(dm->dmBC, newSection);CHKERRQ(ierr); 6553 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 6554 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 6555 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 6556 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 6557 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 6558 } 6559 *odm = dm->dmBC; 6560 PetscFunctionReturn(0); 6561 } 6562 6563 /*@ 6564 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 6565 6566 Input Parameter: 6567 . dm - The original DM 6568 6569 Output Parameters: 6570 + num - The output sequence number 6571 - val - The output sequence value 6572 6573 Level: intermediate 6574 6575 Note: This is intended for output that should appear in sequence, for instance 6576 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6577 6578 .seealso: VecView() 6579 @*/ 6580 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 6581 { 6582 PetscFunctionBegin; 6583 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6584 if (num) {PetscValidIntPointer(num,2); *num = dm->outputSequenceNum;} 6585 if (val) {PetscValidRealPointer(val,3);*val = dm->outputSequenceVal;} 6586 PetscFunctionReturn(0); 6587 } 6588 6589 /*@ 6590 DMSetOutputSequenceNumber - Set the sequence number/value for output 6591 6592 Input Parameters: 6593 + dm - The original DM 6594 . num - The output sequence number 6595 - val - The output sequence value 6596 6597 Level: intermediate 6598 6599 Note: This is intended for output that should appear in sequence, for instance 6600 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6601 6602 .seealso: VecView() 6603 @*/ 6604 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 6605 { 6606 PetscFunctionBegin; 6607 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6608 dm->outputSequenceNum = num; 6609 dm->outputSequenceVal = val; 6610 PetscFunctionReturn(0); 6611 } 6612 6613 /*@C 6614 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 6615 6616 Input Parameters: 6617 + dm - The original DM 6618 . name - The sequence name 6619 - num - The output sequence number 6620 6621 Output Parameter: 6622 . val - The output sequence value 6623 6624 Level: intermediate 6625 6626 Note: This is intended for output that should appear in sequence, for instance 6627 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6628 6629 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 6630 @*/ 6631 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 6632 { 6633 PetscBool ishdf5; 6634 PetscErrorCode ierr; 6635 6636 PetscFunctionBegin; 6637 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6638 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 6639 PetscValidRealPointer(val,4); 6640 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 6641 if (ishdf5) { 6642 #if defined(PETSC_HAVE_HDF5) 6643 PetscScalar value; 6644 6645 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 6646 *val = PetscRealPart(value); 6647 #endif 6648 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 6649 PetscFunctionReturn(0); 6650 } 6651 6652 /*@ 6653 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 6654 6655 Not collective 6656 6657 Input Parameter: 6658 . dm - The DM 6659 6660 Output Parameter: 6661 . useNatural - The flag to build the mapping to a natural order during distribution 6662 6663 Level: beginner 6664 6665 .seealso: DMSetUseNatural(), DMCreate() 6666 @*/ 6667 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 6668 { 6669 PetscFunctionBegin; 6670 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6671 PetscValidBoolPointer(useNatural, 2); 6672 *useNatural = dm->useNatural; 6673 PetscFunctionReturn(0); 6674 } 6675 6676 /*@ 6677 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 6678 6679 Collective on dm 6680 6681 Input Parameters: 6682 + dm - The DM 6683 - useNatural - The flag to build the mapping to a natural order during distribution 6684 6685 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 6686 6687 Level: beginner 6688 6689 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 6690 @*/ 6691 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 6692 { 6693 PetscFunctionBegin; 6694 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6695 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 6696 dm->useNatural = useNatural; 6697 PetscFunctionReturn(0); 6698 } 6699 6700 6701 /*@C 6702 DMCreateLabel - Create a label of the given name if it does not already exist 6703 6704 Not Collective 6705 6706 Input Parameters: 6707 + dm - The DM object 6708 - name - The label name 6709 6710 Level: intermediate 6711 6712 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6713 @*/ 6714 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 6715 { 6716 PetscBool flg; 6717 DMLabel label; 6718 PetscErrorCode ierr; 6719 6720 PetscFunctionBegin; 6721 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6722 PetscValidCharPointer(name, 2); 6723 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 6724 if (!flg) { 6725 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 6726 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 6727 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 6728 } 6729 PetscFunctionReturn(0); 6730 } 6731 6732 /*@C 6733 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 6734 6735 Not Collective 6736 6737 Input Parameters: 6738 + dm - The DM object 6739 . name - The label name 6740 - point - The mesh point 6741 6742 Output Parameter: 6743 . value - The label value for this point, or -1 if the point is not in the label 6744 6745 Level: beginner 6746 6747 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 6748 @*/ 6749 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 6750 { 6751 DMLabel label; 6752 PetscErrorCode ierr; 6753 6754 PetscFunctionBegin; 6755 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6756 PetscValidCharPointer(name, 2); 6757 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6758 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 6759 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 6760 PetscFunctionReturn(0); 6761 } 6762 6763 /*@C 6764 DMSetLabelValue - Add a point to a Sieve Label with given value 6765 6766 Not Collective 6767 6768 Input Parameters: 6769 + dm - The DM object 6770 . name - The label name 6771 . point - The mesh point 6772 - value - The label value for this point 6773 6774 Output Parameter: 6775 6776 Level: beginner 6777 6778 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 6779 @*/ 6780 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6781 { 6782 DMLabel label; 6783 PetscErrorCode ierr; 6784 6785 PetscFunctionBegin; 6786 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6787 PetscValidCharPointer(name, 2); 6788 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6789 if (!label) { 6790 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 6791 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6792 } 6793 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 6794 PetscFunctionReturn(0); 6795 } 6796 6797 /*@C 6798 DMClearLabelValue - Remove a point from a Sieve Label with given value 6799 6800 Not Collective 6801 6802 Input Parameters: 6803 + dm - The DM object 6804 . name - The label name 6805 . point - The mesh point 6806 - value - The label value for this point 6807 6808 Output Parameter: 6809 6810 Level: beginner 6811 6812 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 6813 @*/ 6814 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6815 { 6816 DMLabel label; 6817 PetscErrorCode ierr; 6818 6819 PetscFunctionBegin; 6820 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6821 PetscValidCharPointer(name, 2); 6822 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6823 if (!label) PetscFunctionReturn(0); 6824 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 6825 PetscFunctionReturn(0); 6826 } 6827 6828 /*@C 6829 DMGetLabelSize - Get the number of different integer ids in a Label 6830 6831 Not Collective 6832 6833 Input Parameters: 6834 + dm - The DM object 6835 - name - The label name 6836 6837 Output Parameter: 6838 . size - The number of different integer ids, or 0 if the label does not exist 6839 6840 Level: beginner 6841 6842 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 6843 @*/ 6844 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 6845 { 6846 DMLabel label; 6847 PetscErrorCode ierr; 6848 6849 PetscFunctionBegin; 6850 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6851 PetscValidCharPointer(name, 2); 6852 PetscValidIntPointer(size, 3); 6853 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6854 *size = 0; 6855 if (!label) PetscFunctionReturn(0); 6856 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 6857 PetscFunctionReturn(0); 6858 } 6859 6860 /*@C 6861 DMGetLabelIdIS - Get the integer ids in a label 6862 6863 Not Collective 6864 6865 Input Parameters: 6866 + mesh - The DM object 6867 - name - The label name 6868 6869 Output Parameter: 6870 . ids - The integer ids, or NULL if the label does not exist 6871 6872 Level: beginner 6873 6874 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 6875 @*/ 6876 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 6877 { 6878 DMLabel label; 6879 PetscErrorCode ierr; 6880 6881 PetscFunctionBegin; 6882 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6883 PetscValidCharPointer(name, 2); 6884 PetscValidPointer(ids, 3); 6885 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6886 *ids = NULL; 6887 if (label) { 6888 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 6889 } else { 6890 /* returning an empty IS */ 6891 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 6892 } 6893 PetscFunctionReturn(0); 6894 } 6895 6896 /*@C 6897 DMGetStratumSize - Get the number of points in a label stratum 6898 6899 Not Collective 6900 6901 Input Parameters: 6902 + dm - The DM object 6903 . name - The label name 6904 - value - The stratum value 6905 6906 Output Parameter: 6907 . size - The stratum size 6908 6909 Level: beginner 6910 6911 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 6912 @*/ 6913 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 6914 { 6915 DMLabel label; 6916 PetscErrorCode ierr; 6917 6918 PetscFunctionBegin; 6919 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6920 PetscValidCharPointer(name, 2); 6921 PetscValidIntPointer(size, 4); 6922 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6923 *size = 0; 6924 if (!label) PetscFunctionReturn(0); 6925 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 6926 PetscFunctionReturn(0); 6927 } 6928 6929 /*@C 6930 DMGetStratumIS - Get the points in a label stratum 6931 6932 Not Collective 6933 6934 Input Parameters: 6935 + dm - The DM object 6936 . name - The label name 6937 - value - The stratum value 6938 6939 Output Parameter: 6940 . points - The stratum points, or NULL if the label does not exist or does not have that value 6941 6942 Level: beginner 6943 6944 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 6945 @*/ 6946 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 6947 { 6948 DMLabel label; 6949 PetscErrorCode ierr; 6950 6951 PetscFunctionBegin; 6952 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6953 PetscValidCharPointer(name, 2); 6954 PetscValidPointer(points, 4); 6955 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6956 *points = NULL; 6957 if (!label) PetscFunctionReturn(0); 6958 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 6959 PetscFunctionReturn(0); 6960 } 6961 6962 /*@C 6963 DMSetStratumIS - Set the points in a label stratum 6964 6965 Not Collective 6966 6967 Input Parameters: 6968 + dm - The DM object 6969 . name - The label name 6970 . value - The stratum value 6971 - points - The stratum points 6972 6973 Level: beginner 6974 6975 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 6976 @*/ 6977 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 6978 { 6979 DMLabel label; 6980 PetscErrorCode ierr; 6981 6982 PetscFunctionBegin; 6983 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6984 PetscValidCharPointer(name, 2); 6985 PetscValidPointer(points, 4); 6986 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6987 if (!label) PetscFunctionReturn(0); 6988 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 6989 PetscFunctionReturn(0); 6990 } 6991 6992 /*@C 6993 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 6994 6995 Not Collective 6996 6997 Input Parameters: 6998 + dm - The DM object 6999 . name - The label name 7000 - value - The label value for this point 7001 7002 Output Parameter: 7003 7004 Level: beginner 7005 7006 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 7007 @*/ 7008 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 7009 { 7010 DMLabel label; 7011 PetscErrorCode ierr; 7012 7013 PetscFunctionBegin; 7014 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7015 PetscValidCharPointer(name, 2); 7016 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7017 if (!label) PetscFunctionReturn(0); 7018 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 7019 PetscFunctionReturn(0); 7020 } 7021 7022 /*@ 7023 DMGetNumLabels - Return the number of labels defined by the mesh 7024 7025 Not Collective 7026 7027 Input Parameter: 7028 . dm - The DM object 7029 7030 Output Parameter: 7031 . numLabels - the number of Labels 7032 7033 Level: intermediate 7034 7035 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7036 @*/ 7037 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 7038 { 7039 DMLabelLink next = dm->labels; 7040 PetscInt n = 0; 7041 7042 PetscFunctionBegin; 7043 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7044 PetscValidIntPointer(numLabels, 2); 7045 while (next) {++n; next = next->next;} 7046 *numLabels = n; 7047 PetscFunctionReturn(0); 7048 } 7049 7050 /*@C 7051 DMGetLabelName - Return the name of nth label 7052 7053 Not Collective 7054 7055 Input Parameters: 7056 + dm - The DM object 7057 - n - the label number 7058 7059 Output Parameter: 7060 . name - the label name 7061 7062 Level: intermediate 7063 7064 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7065 @*/ 7066 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 7067 { 7068 DMLabelLink next = dm->labels; 7069 PetscInt l = 0; 7070 PetscErrorCode ierr; 7071 7072 PetscFunctionBegin; 7073 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7074 PetscValidPointer(name, 3); 7075 while (next) { 7076 if (l == n) { 7077 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 7078 PetscFunctionReturn(0); 7079 } 7080 ++l; 7081 next = next->next; 7082 } 7083 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7084 } 7085 7086 /*@C 7087 DMHasLabel - Determine whether the mesh has a label of a given name 7088 7089 Not Collective 7090 7091 Input Parameters: 7092 + dm - The DM object 7093 - name - The label name 7094 7095 Output Parameter: 7096 . hasLabel - PETSC_TRUE if the label is present 7097 7098 Level: intermediate 7099 7100 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7101 @*/ 7102 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 7103 { 7104 DMLabelLink next = dm->labels; 7105 const char *lname; 7106 PetscErrorCode ierr; 7107 7108 PetscFunctionBegin; 7109 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7110 PetscValidCharPointer(name, 2); 7111 PetscValidBoolPointer(hasLabel, 3); 7112 *hasLabel = PETSC_FALSE; 7113 while (next) { 7114 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7115 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 7116 if (*hasLabel) break; 7117 next = next->next; 7118 } 7119 PetscFunctionReturn(0); 7120 } 7121 7122 /*@C 7123 DMGetLabel - Return the label of a given name, or NULL 7124 7125 Not Collective 7126 7127 Input Parameters: 7128 + dm - The DM object 7129 - name - The label name 7130 7131 Output Parameter: 7132 . label - The DMLabel, or NULL if the label is absent 7133 7134 Level: intermediate 7135 7136 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7137 @*/ 7138 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 7139 { 7140 DMLabelLink next = dm->labels; 7141 PetscBool hasLabel; 7142 const char *lname; 7143 PetscErrorCode ierr; 7144 7145 PetscFunctionBegin; 7146 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7147 PetscValidCharPointer(name, 2); 7148 PetscValidPointer(label, 3); 7149 *label = NULL; 7150 while (next) { 7151 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7152 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7153 if (hasLabel) { 7154 *label = next->label; 7155 break; 7156 } 7157 next = next->next; 7158 } 7159 PetscFunctionReturn(0); 7160 } 7161 7162 /*@C 7163 DMGetLabelByNum - Return the nth label 7164 7165 Not Collective 7166 7167 Input Parameters: 7168 + dm - The DM object 7169 - n - the label number 7170 7171 Output Parameter: 7172 . label - the label 7173 7174 Level: intermediate 7175 7176 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7177 @*/ 7178 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 7179 { 7180 DMLabelLink next = dm->labels; 7181 PetscInt l = 0; 7182 7183 PetscFunctionBegin; 7184 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7185 PetscValidPointer(label, 3); 7186 while (next) { 7187 if (l == n) { 7188 *label = next->label; 7189 PetscFunctionReturn(0); 7190 } 7191 ++l; 7192 next = next->next; 7193 } 7194 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7195 } 7196 7197 /*@C 7198 DMAddLabel - Add the label to this mesh 7199 7200 Not Collective 7201 7202 Input Parameters: 7203 + dm - The DM object 7204 - label - The DMLabel 7205 7206 Level: developer 7207 7208 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7209 @*/ 7210 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 7211 { 7212 DMLabelLink l, *p, tmpLabel; 7213 PetscBool hasLabel; 7214 const char *lname; 7215 PetscBool flg; 7216 PetscErrorCode ierr; 7217 7218 PetscFunctionBegin; 7219 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7220 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 7221 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 7222 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 7223 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 7224 tmpLabel->label = label; 7225 tmpLabel->output = PETSC_TRUE; 7226 for (p=&dm->labels; (l=*p); p=&l->next) {} 7227 *p = tmpLabel; 7228 ierr = PetscObjectReference((PetscObject)label);CHKERRQ(ierr); 7229 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 7230 if (flg) dm->depthLabel = label; 7231 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 7232 if (flg) dm->celltypeLabel = label; 7233 PetscFunctionReturn(0); 7234 } 7235 7236 /*@C 7237 DMRemoveLabel - Remove the label given by name from this mesh 7238 7239 Not Collective 7240 7241 Input Parameters: 7242 + dm - The DM object 7243 - name - The label name 7244 7245 Output Parameter: 7246 . label - The DMLabel, or NULL if the label is absent 7247 7248 Level: developer 7249 7250 Notes: 7251 DMRemoveLabel(dm,name,NULL) removes the label from dm and calls 7252 DMLabelDestroy() on the label. 7253 7254 DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT 7255 call DMLabelDestroy(). Instead, the label is returned and the user is 7256 responsible of calling DMLabelDestroy() at some point. 7257 7258 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf() 7259 @*/ 7260 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 7261 { 7262 DMLabelLink link, *pnext; 7263 PetscBool hasLabel; 7264 const char *lname; 7265 PetscErrorCode ierr; 7266 7267 PetscFunctionBegin; 7268 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7269 PetscValidCharPointer(name, 2); 7270 if (label) { 7271 PetscValidPointer(label, 3); 7272 *label = NULL; 7273 } 7274 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7275 ierr = PetscObjectGetName((PetscObject) link->label, &lname);CHKERRQ(ierr); 7276 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7277 if (hasLabel) { 7278 *pnext = link->next; /* Remove from list */ 7279 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 7280 if (hasLabel) dm->depthLabel = NULL; 7281 ierr = PetscStrcmp(name, "celltype", &hasLabel);CHKERRQ(ierr); 7282 if (hasLabel) dm->celltypeLabel = NULL; 7283 if (label) *label = link->label; 7284 else {ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);} 7285 ierr = PetscFree(link);CHKERRQ(ierr); 7286 break; 7287 } 7288 } 7289 PetscFunctionReturn(0); 7290 } 7291 7292 /*@ 7293 DMRemoveLabelBySelf - Remove the label from this mesh 7294 7295 Not Collective 7296 7297 Input Parameters: 7298 + dm - The DM object 7299 . label - (Optional) The DMLabel to be removed from the DM 7300 - failNotFound - Should it fail if the label is not found in the DM? 7301 7302 Level: developer 7303 7304 Notes: 7305 Only exactly the same instance is removed if found, name match is ignored. 7306 If the DM has an exclusive reference to the label, it gets destroyed and 7307 *label nullified. 7308 7309 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel() 7310 @*/ 7311 PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound) 7312 { 7313 DMLabelLink link, *pnext; 7314 PetscBool hasLabel = PETSC_FALSE; 7315 PetscErrorCode ierr; 7316 7317 PetscFunctionBegin; 7318 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7319 PetscValidPointer(label, 2); 7320 if (!*label && !failNotFound) PetscFunctionReturn(0); 7321 PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2); 7322 PetscValidLogicalCollectiveBool(dm,failNotFound,3); 7323 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7324 if (*label == link->label) { 7325 hasLabel = PETSC_TRUE; 7326 *pnext = link->next; /* Remove from list */ 7327 if (*label == dm->depthLabel) dm->depthLabel = NULL; 7328 if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL; 7329 if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */ 7330 ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr); 7331 ierr = PetscFree(link);CHKERRQ(ierr); 7332 break; 7333 } 7334 } 7335 if (!hasLabel && failNotFound) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM"); 7336 PetscFunctionReturn(0); 7337 } 7338 7339 /*@C 7340 DMGetLabelOutput - Get the output flag for a given label 7341 7342 Not Collective 7343 7344 Input Parameters: 7345 + dm - The DM object 7346 - name - The label name 7347 7348 Output Parameter: 7349 . output - The flag for output 7350 7351 Level: developer 7352 7353 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7354 @*/ 7355 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 7356 { 7357 DMLabelLink next = dm->labels; 7358 const char *lname; 7359 PetscErrorCode ierr; 7360 7361 PetscFunctionBegin; 7362 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7363 PetscValidPointer(name, 2); 7364 PetscValidPointer(output, 3); 7365 while (next) { 7366 PetscBool flg; 7367 7368 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7369 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7370 if (flg) {*output = next->output; PetscFunctionReturn(0);} 7371 next = next->next; 7372 } 7373 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7374 } 7375 7376 /*@C 7377 DMSetLabelOutput - Set the output flag for a given label 7378 7379 Not Collective 7380 7381 Input Parameters: 7382 + dm - The DM object 7383 . name - The label name 7384 - output - The flag for output 7385 7386 Level: developer 7387 7388 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7389 @*/ 7390 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 7391 { 7392 DMLabelLink next = dm->labels; 7393 const char *lname; 7394 PetscErrorCode ierr; 7395 7396 PetscFunctionBegin; 7397 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7398 PetscValidCharPointer(name, 2); 7399 while (next) { 7400 PetscBool flg; 7401 7402 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7403 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7404 if (flg) {next->output = output; PetscFunctionReturn(0);} 7405 next = next->next; 7406 } 7407 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7408 } 7409 7410 /*@ 7411 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 7412 7413 Collective on dmA 7414 7415 Input Parameter: 7416 + dmA - The DM object with initial labels 7417 . dmB - The DM object with copied labels 7418 . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES) 7419 - all - Copy all labels including "depth", "dim", and "celltype" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE) 7420 7421 Level: intermediate 7422 7423 Note: This is typically used when interpolating or otherwise adding to a mesh 7424 7425 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection(), DMShareLabels() 7426 @*/ 7427 PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all) 7428 { 7429 DMLabel label, labelNew; 7430 const char *name; 7431 PetscBool flg; 7432 DMLabelLink link; 7433 PetscErrorCode ierr; 7434 7435 PetscFunctionBegin; 7436 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 7437 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 7438 PetscValidLogicalCollectiveEnum(dmA, mode,3); 7439 PetscValidLogicalCollectiveBool(dmA, all, 4); 7440 if (mode==PETSC_USE_POINTER) SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects"); 7441 if (dmA == dmB) PetscFunctionReturn(0); 7442 for (link=dmA->labels; link; link=link->next) { 7443 label=link->label; 7444 ierr = PetscObjectGetName((PetscObject)label, &name);CHKERRQ(ierr); 7445 if (!all) { 7446 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 7447 if (flg) continue; 7448 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 7449 if (flg) continue; 7450 ierr = PetscStrcmp(name, "celltype", &flg);CHKERRQ(ierr); 7451 if (flg) continue; 7452 } 7453 if (mode==PETSC_COPY_VALUES) { 7454 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 7455 } else { 7456 labelNew = label; 7457 } 7458 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 7459 if (mode==PETSC_COPY_VALUES) {ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);} 7460 } 7461 PetscFunctionReturn(0); 7462 } 7463 7464 /*@ 7465 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 7466 7467 Input Parameter: 7468 . dm - The DM object 7469 7470 Output Parameter: 7471 . cdm - The coarse DM 7472 7473 Level: intermediate 7474 7475 .seealso: DMSetCoarseDM() 7476 @*/ 7477 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 7478 { 7479 PetscFunctionBegin; 7480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7481 PetscValidPointer(cdm, 2); 7482 *cdm = dm->coarseMesh; 7483 PetscFunctionReturn(0); 7484 } 7485 7486 /*@ 7487 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 7488 7489 Input Parameters: 7490 + dm - The DM object 7491 - cdm - The coarse DM 7492 7493 Level: intermediate 7494 7495 .seealso: DMGetCoarseDM() 7496 @*/ 7497 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 7498 { 7499 PetscErrorCode ierr; 7500 7501 PetscFunctionBegin; 7502 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7503 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 7504 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 7505 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 7506 dm->coarseMesh = cdm; 7507 PetscFunctionReturn(0); 7508 } 7509 7510 /*@ 7511 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 7512 7513 Input Parameter: 7514 . dm - The DM object 7515 7516 Output Parameter: 7517 . fdm - The fine DM 7518 7519 Level: intermediate 7520 7521 .seealso: DMSetFineDM() 7522 @*/ 7523 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 7524 { 7525 PetscFunctionBegin; 7526 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7527 PetscValidPointer(fdm, 2); 7528 *fdm = dm->fineMesh; 7529 PetscFunctionReturn(0); 7530 } 7531 7532 /*@ 7533 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 7534 7535 Input Parameters: 7536 + dm - The DM object 7537 - fdm - The fine DM 7538 7539 Level: intermediate 7540 7541 .seealso: DMGetFineDM() 7542 @*/ 7543 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 7544 { 7545 PetscErrorCode ierr; 7546 7547 PetscFunctionBegin; 7548 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7549 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 7550 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 7551 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 7552 dm->fineMesh = fdm; 7553 PetscFunctionReturn(0); 7554 } 7555 7556 /*=== DMBoundary code ===*/ 7557 7558 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 7559 { 7560 PetscInt d; 7561 PetscErrorCode ierr; 7562 7563 PetscFunctionBegin; 7564 for (d = 0; d < dm->Nds; ++d) { 7565 ierr = PetscDSCopyBoundary(dm->probs[d].ds, dmNew->probs[d].ds);CHKERRQ(ierr); 7566 } 7567 PetscFunctionReturn(0); 7568 } 7569 7570 /*@C 7571 DMAddBoundary - Add a boundary condition to the model 7572 7573 Input Parameters: 7574 + dm - The DM, with a PetscDS that matches the problem being constrained 7575 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7576 . name - The BC name 7577 . labelname - The label defining constrained points 7578 . field - The field to constrain 7579 . numcomps - The number of constrained field components (0 will constrain all fields) 7580 . comps - An array of constrained component numbers 7581 . bcFunc - A pointwise function giving boundary values 7582 . numids - The number of DMLabel ids for constrained points 7583 . ids - An array of ids for constrained points 7584 - ctx - An optional user context for bcFunc 7585 7586 Options Database Keys: 7587 + -bc_<boundary name> <num> - Overrides the boundary ids 7588 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7589 7590 Level: developer 7591 7592 .seealso: DMGetBoundary() 7593 @*/ 7594 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) 7595 { 7596 PetscDS ds; 7597 PetscErrorCode ierr; 7598 7599 PetscFunctionBegin; 7600 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7601 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7602 ierr = PetscDSAddBoundary(ds, type,name, labelname, field, numcomps, comps, bcFunc, numids, ids, ctx);CHKERRQ(ierr); 7603 PetscFunctionReturn(0); 7604 } 7605 7606 /*@ 7607 DMGetNumBoundary - Get the number of registered BC 7608 7609 Input Parameters: 7610 . dm - The mesh object 7611 7612 Output Parameters: 7613 . numBd - The number of BC 7614 7615 Level: intermediate 7616 7617 .seealso: DMAddBoundary(), DMGetBoundary() 7618 @*/ 7619 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 7620 { 7621 PetscDS ds; 7622 PetscErrorCode ierr; 7623 7624 PetscFunctionBegin; 7625 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7626 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7627 ierr = PetscDSGetNumBoundary(ds, numBd);CHKERRQ(ierr); 7628 PetscFunctionReturn(0); 7629 } 7630 7631 /*@C 7632 DMGetBoundary - Get a model boundary condition 7633 7634 Input Parameters: 7635 + dm - The mesh object 7636 - bd - The BC number 7637 7638 Output Parameters: 7639 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7640 . name - The BC name 7641 . labelname - The label defining constrained points 7642 . field - The field to constrain 7643 . numcomps - The number of constrained field components 7644 . comps - An array of constrained component numbers 7645 . bcFunc - A pointwise function giving boundary values 7646 . numids - The number of DMLabel ids for constrained points 7647 . ids - An array of ids for constrained points 7648 - ctx - An optional user context for bcFunc 7649 7650 Options Database Keys: 7651 + -bc_<boundary name> <num> - Overrides the boundary ids 7652 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7653 7654 Level: developer 7655 7656 .seealso: DMAddBoundary() 7657 @*/ 7658 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) 7659 { 7660 PetscDS ds; 7661 PetscErrorCode ierr; 7662 7663 PetscFunctionBegin; 7664 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7665 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7666 ierr = PetscDSGetBoundary(ds, bd, type, name, labelname, field, numcomps, comps, func, numids, ids, ctx);CHKERRQ(ierr); 7667 PetscFunctionReturn(0); 7668 } 7669 7670 static PetscErrorCode DMPopulateBoundary(DM dm) 7671 { 7672 PetscDS ds; 7673 DMBoundary *lastnext; 7674 DSBoundary dsbound; 7675 PetscErrorCode ierr; 7676 7677 PetscFunctionBegin; 7678 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7679 dsbound = ds->boundary; 7680 if (dm->boundary) { 7681 DMBoundary next = dm->boundary; 7682 7683 /* quick check to see if the PetscDS has changed */ 7684 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 7685 /* the PetscDS has changed: tear down and rebuild */ 7686 while (next) { 7687 DMBoundary b = next; 7688 7689 next = b->next; 7690 ierr = PetscFree(b);CHKERRQ(ierr); 7691 } 7692 dm->boundary = NULL; 7693 } 7694 7695 lastnext = &(dm->boundary); 7696 while (dsbound) { 7697 DMBoundary dmbound; 7698 7699 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 7700 dmbound->dsboundary = dsbound; 7701 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 7702 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 7703 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 7704 *lastnext = dmbound; 7705 lastnext = &(dmbound->next); 7706 dsbound = dsbound->next; 7707 } 7708 PetscFunctionReturn(0); 7709 } 7710 7711 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 7712 { 7713 DMBoundary b; 7714 PetscErrorCode ierr; 7715 7716 PetscFunctionBegin; 7717 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7718 PetscValidBoolPointer(isBd, 3); 7719 *isBd = PETSC_FALSE; 7720 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 7721 b = dm->boundary; 7722 while (b && !(*isBd)) { 7723 DMLabel label = b->label; 7724 DSBoundary dsb = b->dsboundary; 7725 7726 if (label) { 7727 PetscInt i; 7728 7729 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 7730 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 7731 } 7732 } 7733 b = b->next; 7734 } 7735 PetscFunctionReturn(0); 7736 } 7737 7738 /*@C 7739 DMProjectFunction - This projects the given function into the function space provided, putting the coefficients in a global vector. 7740 7741 Collective on DM 7742 7743 Input Parameters: 7744 + dm - The DM 7745 . time - The time 7746 . funcs - The coordinate functions to evaluate, one per field 7747 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7748 - mode - The insertion mode for values 7749 7750 Output Parameter: 7751 . X - vector 7752 7753 Calling sequence of func: 7754 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7755 7756 + dim - The spatial dimension 7757 . x - The coordinates 7758 . Nf - The number of fields 7759 . u - The output field values 7760 - ctx - optional user-defined function context 7761 7762 Level: developer 7763 7764 .seealso: DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 7765 @*/ 7766 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 7767 { 7768 Vec localX; 7769 PetscErrorCode ierr; 7770 7771 PetscFunctionBegin; 7772 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7773 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7774 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7775 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7776 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7777 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7778 PetscFunctionReturn(0); 7779 } 7780 7781 /*@C 7782 DMProjectFunctionLocal - This projects the given function into the function space provided, putting the coefficients in a local vector. 7783 7784 Not collective 7785 7786 Input Parameters: 7787 + dm - The DM 7788 . time - The time 7789 . funcs - The coordinate functions to evaluate, one per field 7790 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7791 - mode - The insertion mode for values 7792 7793 Output Parameter: 7794 . localX - vector 7795 7796 Calling sequence of func: 7797 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7798 7799 + dim - The spatial dimension 7800 . x - The coordinates 7801 . Nf - The number of fields 7802 . u - The output field values 7803 - ctx - optional user-defined function context 7804 7805 Level: developer 7806 7807 .seealso: DMProjectFunction(), DMProjectFunctionLabel(), DMComputeL2Diff() 7808 @*/ 7809 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 7810 { 7811 PetscErrorCode ierr; 7812 7813 PetscFunctionBegin; 7814 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7815 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7816 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 7817 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7818 PetscFunctionReturn(0); 7819 } 7820 7821 /*@C 7822 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. 7823 7824 Collective on DM 7825 7826 Input Parameters: 7827 + dm - The DM 7828 . time - The time 7829 . label - The DMLabel selecting the portion of the mesh for projection 7830 . funcs - The coordinate functions to evaluate, one per field 7831 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7832 - mode - The insertion mode for values 7833 7834 Output Parameter: 7835 . X - vector 7836 7837 Calling sequence of func: 7838 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7839 7840 + dim - The spatial dimension 7841 . x - The coordinates 7842 . Nf - The number of fields 7843 . u - The output field values 7844 - ctx - optional user-defined function context 7845 7846 Level: developer 7847 7848 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal(), DMComputeL2Diff() 7849 @*/ 7850 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) 7851 { 7852 Vec localX; 7853 PetscErrorCode ierr; 7854 7855 PetscFunctionBegin; 7856 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7857 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7858 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7859 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7860 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7861 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7862 PetscFunctionReturn(0); 7863 } 7864 7865 /*@C 7866 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. 7867 7868 Not collective 7869 7870 Input Parameters: 7871 + dm - The DM 7872 . time - The time 7873 . label - The DMLabel selecting the portion of the mesh for projection 7874 . funcs - The coordinate functions to evaluate, one per field 7875 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7876 - mode - The insertion mode for values 7877 7878 Output Parameter: 7879 . localX - vector 7880 7881 Calling sequence of func: 7882 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7883 7884 + dim - The spatial dimension 7885 . x - The coordinates 7886 . Nf - The number of fields 7887 . u - The output field values 7888 - ctx - optional user-defined function context 7889 7890 Level: developer 7891 7892 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 7893 @*/ 7894 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) 7895 { 7896 PetscErrorCode ierr; 7897 7898 PetscFunctionBegin; 7899 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7900 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7901 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 7902 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7903 PetscFunctionReturn(0); 7904 } 7905 7906 /*@C 7907 DMProjectFieldLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector. 7908 7909 Not collective 7910 7911 Input Parameters: 7912 + dm - The DM 7913 . time - The time 7914 . localU - The input field vector 7915 . funcs - The functions to evaluate, one per field 7916 - mode - The insertion mode for values 7917 7918 Output Parameter: 7919 . localX - The output vector 7920 7921 Calling sequence of func: 7922 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 7923 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 7924 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 7925 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 7926 7927 + dim - The spatial dimension 7928 . Nf - The number of input fields 7929 . NfAux - The number of input auxiliary fields 7930 . uOff - The offset of each field in u[] 7931 . uOff_x - The offset of each field in u_x[] 7932 . u - The field values at this point in space 7933 . u_t - The field time derivative at this point in space (or NULL) 7934 . u_x - The field derivatives at this point in space 7935 . aOff - The offset of each auxiliary field in u[] 7936 . aOff_x - The offset of each auxiliary field in u_x[] 7937 . a - The auxiliary field values at this point in space 7938 . a_t - The auxiliary field time derivative at this point in space (or NULL) 7939 . a_x - The auxiliary field derivatives at this point in space 7940 . t - The current time 7941 . x - The coordinates of this point 7942 . numConstants - The number of constants 7943 . constants - The value of each constant 7944 - f - The value of the function at this point in space 7945 7946 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. 7947 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 7948 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 7949 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 7950 7951 Level: intermediate 7952 7953 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 7954 @*/ 7955 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 7956 void (**funcs)(PetscInt, PetscInt, PetscInt, 7957 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7958 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7959 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 7960 InsertMode mode, Vec localX) 7961 { 7962 PetscErrorCode ierr; 7963 7964 PetscFunctionBegin; 7965 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7966 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 7967 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 7968 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 7969 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 7970 PetscFunctionReturn(0); 7971 } 7972 7973 /*@C 7974 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. 7975 7976 Not collective 7977 7978 Input Parameters: 7979 + dm - The DM 7980 . time - The time 7981 . label - The DMLabel marking the portion of the domain to output 7982 . numIds - The number of label ids to use 7983 . ids - The label ids to use for marking 7984 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 7985 . comps - The components to set in the output, or NULL for all components 7986 . localU - The input field vector 7987 . funcs - The functions to evaluate, one per field 7988 - mode - The insertion mode for values 7989 7990 Output Parameter: 7991 . localX - The output vector 7992 7993 Calling sequence of func: 7994 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 7995 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 7996 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 7997 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 7998 7999 + dim - The spatial dimension 8000 . Nf - The number of input fields 8001 . NfAux - The number of input auxiliary fields 8002 . uOff - The offset of each field in u[] 8003 . uOff_x - The offset of each field in u_x[] 8004 . u - The field values at this point in space 8005 . u_t - The field time derivative at this point in space (or NULL) 8006 . u_x - The field derivatives at this point in space 8007 . aOff - The offset of each auxiliary field in u[] 8008 . aOff_x - The offset of each auxiliary field in u_x[] 8009 . a - The auxiliary field values at this point in space 8010 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8011 . a_x - The auxiliary field derivatives at this point in space 8012 . t - The current time 8013 . x - The coordinates of this point 8014 . numConstants - The number of constants 8015 . constants - The value of each constant 8016 - f - The value of the function at this point in space 8017 8018 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. 8019 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 8020 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8021 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8022 8023 Level: intermediate 8024 8025 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8026 @*/ 8027 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 8028 void (**funcs)(PetscInt, PetscInt, PetscInt, 8029 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8030 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8031 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8032 InsertMode mode, Vec localX) 8033 { 8034 PetscErrorCode ierr; 8035 8036 PetscFunctionBegin; 8037 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8038 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 8039 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 8040 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 8041 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 8042 PetscFunctionReturn(0); 8043 } 8044 8045 /*@C 8046 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 8047 8048 Input Parameters: 8049 + dm - The DM 8050 . time - The time 8051 . funcs - The functions to evaluate for each field component 8052 . ctxs - Optional array of contexts to pass to each function, or NULL. 8053 - X - The coefficient vector u_h, a global vector 8054 8055 Output Parameter: 8056 . diff - The diff ||u - u_h||_2 8057 8058 Level: developer 8059 8060 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 8061 @*/ 8062 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 8063 { 8064 PetscErrorCode ierr; 8065 8066 PetscFunctionBegin; 8067 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8068 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8069 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 8070 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 8071 PetscFunctionReturn(0); 8072 } 8073 8074 /*@C 8075 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 8076 8077 Collective on dm 8078 8079 Input Parameters: 8080 + dm - The DM 8081 , time - The time 8082 . funcs - The gradient functions to evaluate for each field component 8083 . ctxs - Optional array of contexts to pass to each function, or NULL. 8084 . X - The coefficient vector u_h, a global vector 8085 - n - The vector to project along 8086 8087 Output Parameter: 8088 . diff - The diff ||(grad u - grad u_h) . n||_2 8089 8090 Level: developer 8091 8092 .seealso: DMProjectFunction(), DMComputeL2Diff() 8093 @*/ 8094 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) 8095 { 8096 PetscErrorCode ierr; 8097 8098 PetscFunctionBegin; 8099 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8100 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8101 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 8102 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 8103 PetscFunctionReturn(0); 8104 } 8105 8106 /*@C 8107 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 8108 8109 Collective on dm 8110 8111 Input Parameters: 8112 + dm - The DM 8113 . time - The time 8114 . funcs - The functions to evaluate for each field component 8115 . ctxs - Optional array of contexts to pass to each function, or NULL. 8116 - X - The coefficient vector u_h, a global vector 8117 8118 Output Parameter: 8119 . diff - The array of differences, ||u^f - u^f_h||_2 8120 8121 Level: developer 8122 8123 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 8124 @*/ 8125 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 8126 { 8127 PetscErrorCode ierr; 8128 8129 PetscFunctionBegin; 8130 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8131 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8132 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 8133 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 8134 PetscFunctionReturn(0); 8135 } 8136 8137 /*@C 8138 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 8139 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 8140 8141 Collective on dm 8142 8143 Input parameters: 8144 + dm - the pre-adaptation DM object 8145 - label - label with the flags 8146 8147 Output parameters: 8148 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 8149 8150 Level: intermediate 8151 8152 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 8153 @*/ 8154 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 8155 { 8156 PetscErrorCode ierr; 8157 8158 PetscFunctionBegin; 8159 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8160 PetscValidPointer(label,2); 8161 PetscValidPointer(dmAdapt,3); 8162 *dmAdapt = NULL; 8163 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 8164 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 8165 PetscFunctionReturn(0); 8166 } 8167 8168 /*@C 8169 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 8170 8171 Input Parameters: 8172 + dm - The DM object 8173 . metric - The metric to which the mesh is adapted, defined vertex-wise. 8174 - 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_". 8175 8176 Output Parameter: 8177 . dmAdapt - Pointer to the DM object containing the adapted mesh 8178 8179 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 8180 8181 Level: advanced 8182 8183 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 8184 @*/ 8185 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 8186 { 8187 PetscErrorCode ierr; 8188 8189 PetscFunctionBegin; 8190 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8191 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 8192 if (bdLabel) PetscValidPointer(bdLabel, 3); 8193 PetscValidPointer(dmAdapt, 4); 8194 *dmAdapt = NULL; 8195 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 8196 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 8197 PetscFunctionReturn(0); 8198 } 8199 8200 /*@C 8201 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 8202 8203 Not Collective 8204 8205 Input Parameter: 8206 . dm - The DM 8207 8208 Output Parameters: 8209 + nranks - the number of neighbours 8210 - ranks - the neighbors ranks 8211 8212 Notes: 8213 Do not free the array, it is freed when the DM is destroyed. 8214 8215 Level: beginner 8216 8217 .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks() 8218 @*/ 8219 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 8220 { 8221 PetscErrorCode ierr; 8222 8223 PetscFunctionBegin; 8224 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8225 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 8226 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 8227 PetscFunctionReturn(0); 8228 } 8229 8230 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 8231 8232 /* 8233 Converts the input vector to a ghosted vector and then calls the standard coloring code. 8234 This has be a different function because it requires DM which is not defined in the Mat library 8235 */ 8236 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 8237 { 8238 PetscErrorCode ierr; 8239 8240 PetscFunctionBegin; 8241 if (coloring->ctype == IS_COLORING_LOCAL) { 8242 Vec x1local; 8243 DM dm; 8244 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 8245 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 8246 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 8247 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 8248 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 8249 x1 = x1local; 8250 } 8251 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 8252 if (coloring->ctype == IS_COLORING_LOCAL) { 8253 DM dm; 8254 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 8255 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 8256 } 8257 PetscFunctionReturn(0); 8258 } 8259 8260 /*@ 8261 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 8262 8263 Input Parameter: 8264 . coloring - the MatFDColoring object 8265 8266 Developer Notes: 8267 this routine exists because the PETSc Mat library does not know about the DM objects 8268 8269 Level: advanced 8270 8271 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 8272 @*/ 8273 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 8274 { 8275 PetscFunctionBegin; 8276 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 8277 PetscFunctionReturn(0); 8278 } 8279 8280 /*@ 8281 DMGetCompatibility - determine if two DMs are compatible 8282 8283 Collective 8284 8285 Input Parameters: 8286 + dm1 - the first DM 8287 - dm2 - the second DM 8288 8289 Output Parameters: 8290 + compatible - whether or not the two DMs are compatible 8291 - set - whether or not the compatible value was set 8292 8293 Notes: 8294 Two DMs are deemed compatible if they represent the same parallel decomposition 8295 of the same topology. This implies that the section (field data) on one 8296 "makes sense" with respect to the topology and parallel decomposition of the other. 8297 Loosely speaking, compatible DMs represent the same domain and parallel 8298 decomposition, but hold different data. 8299 8300 Typically, one would confirm compatibility if intending to simultaneously iterate 8301 over a pair of vectors obtained from different DMs. 8302 8303 For example, two DMDA objects are compatible if they have the same local 8304 and global sizes and the same stencil width. They can have different numbers 8305 of degrees of freedom per node. Thus, one could use the node numbering from 8306 either DM in bounds for a loop over vectors derived from either DM. 8307 8308 Consider the operation of summing data living on a 2-dof DMDA to data living 8309 on a 1-dof DMDA, which should be compatible, as in the following snippet. 8310 .vb 8311 ... 8312 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 8313 if (set && compatible) { 8314 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 8315 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 8316 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 8317 for (j=y; j<y+n; ++j) { 8318 for (i=x; i<x+m, ++i) { 8319 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 8320 } 8321 } 8322 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 8323 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 8324 } else { 8325 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 8326 } 8327 ... 8328 .ve 8329 8330 Checking compatibility might be expensive for a given implementation of DM, 8331 or might be impossible to unambiguously confirm or deny. For this reason, 8332 this function may decline to determine compatibility, and hence users should 8333 always check the "set" output parameter. 8334 8335 A DM is always compatible with itself. 8336 8337 In the current implementation, DMs which live on "unequal" communicators 8338 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 8339 incompatible. 8340 8341 This function is labeled "Collective," as information about all subdomains 8342 is required on each rank. However, in DM implementations which store all this 8343 information locally, this function may be merely "Logically Collective". 8344 8345 Developer Notes: 8346 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 8347 iff B is compatible with A. Thus, this function checks the implementations 8348 of both dm and dmc (if they are of different types), attempting to determine 8349 compatibility. It is left to DM implementers to ensure that symmetry is 8350 preserved. The simplest way to do this is, when implementing type-specific 8351 logic for this function, is to check for existing logic in the implementation 8352 of other DM types and let *set = PETSC_FALSE if found. 8353 8354 Level: advanced 8355 8356 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 8357 @*/ 8358 8359 PetscErrorCode DMGetCompatibility(DM dm1,DM dm2,PetscBool *compatible,PetscBool *set) 8360 { 8361 PetscErrorCode ierr; 8362 PetscMPIInt compareResult; 8363 DMType type,type2; 8364 PetscBool sameType; 8365 8366 PetscFunctionBegin; 8367 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 8368 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 8369 8370 /* Declare a DM compatible with itself */ 8371 if (dm1 == dm2) { 8372 *set = PETSC_TRUE; 8373 *compatible = PETSC_TRUE; 8374 PetscFunctionReturn(0); 8375 } 8376 8377 /* Declare a DM incompatible with a DM that lives on an "unequal" 8378 communicator. Note that this does not preclude compatibility with 8379 DMs living on "congruent" or "similar" communicators, but this must be 8380 determined by the implementation-specific logic */ 8381 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm1),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr); 8382 if (compareResult == MPI_UNEQUAL) { 8383 *set = PETSC_TRUE; 8384 *compatible = PETSC_FALSE; 8385 PetscFunctionReturn(0); 8386 } 8387 8388 /* Pass to the implementation-specific routine, if one exists. */ 8389 if (dm1->ops->getcompatibility) { 8390 ierr = (*dm1->ops->getcompatibility)(dm1,dm2,compatible,set);CHKERRQ(ierr); 8391 if (*set) PetscFunctionReturn(0); 8392 } 8393 8394 /* If dm1 and dm2 are of different types, then attempt to check compatibility 8395 with an implementation of this function from dm2 */ 8396 ierr = DMGetType(dm1,&type);CHKERRQ(ierr); 8397 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 8398 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 8399 if (!sameType && dm2->ops->getcompatibility) { 8400 ierr = (*dm2->ops->getcompatibility)(dm2,dm1,compatible,set);CHKERRQ(ierr); /* Note argument order */ 8401 } else { 8402 *set = PETSC_FALSE; 8403 } 8404 PetscFunctionReturn(0); 8405 } 8406 8407 /*@C 8408 DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance. 8409 8410 Logically Collective on DM 8411 8412 Input Parameters: 8413 + DM - the DM 8414 . f - the monitor function 8415 . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired) 8416 - monitordestroy - [optional] routine that frees monitor context (may be NULL) 8417 8418 Options Database Keys: 8419 - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but 8420 does not cancel those set via the options database. 8421 8422 Notes: 8423 Several different monitoring routines may be set by calling 8424 DMMonitorSet() multiple times; all will be called in the 8425 order in which they were set. 8426 8427 Fortran Notes: 8428 Only a single monitor function can be set for each DM object 8429 8430 Level: intermediate 8431 8432 .seealso: DMMonitorCancel() 8433 @*/ 8434 PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**)) 8435 { 8436 PetscInt m; 8437 PetscErrorCode ierr; 8438 8439 PetscFunctionBegin; 8440 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8441 for (m = 0; m < dm->numbermonitors; ++m) { 8442 PetscBool identical; 8443 8444 ierr = PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);CHKERRQ(ierr); 8445 if (identical) PetscFunctionReturn(0); 8446 } 8447 if (dm->numbermonitors >= MAXDMMONITORS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 8448 dm->monitor[dm->numbermonitors] = f; 8449 dm->monitordestroy[dm->numbermonitors] = monitordestroy; 8450 dm->monitorcontext[dm->numbermonitors++] = (void *) mctx; 8451 PetscFunctionReturn(0); 8452 } 8453 8454 /*@ 8455 DMMonitorCancel - Clears all the monitor functions for a DM object. 8456 8457 Logically Collective on DM 8458 8459 Input Parameter: 8460 . dm - the DM 8461 8462 Options Database Key: 8463 . -dm_monitor_cancel - cancels all monitors that have been hardwired 8464 into a code by calls to DMonitorSet(), but does not cancel those 8465 set via the options database 8466 8467 Notes: 8468 There is no way to clear one specific monitor from a DM object. 8469 8470 Level: intermediate 8471 8472 .seealso: DMMonitorSet() 8473 @*/ 8474 PetscErrorCode DMMonitorCancel(DM dm) 8475 { 8476 PetscErrorCode ierr; 8477 PetscInt m; 8478 8479 PetscFunctionBegin; 8480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8481 for (m = 0; m < dm->numbermonitors; ++m) { 8482 if (dm->monitordestroy[m]) {ierr = (*dm->monitordestroy[m])(&dm->monitorcontext[m]);CHKERRQ(ierr);} 8483 } 8484 dm->numbermonitors = 0; 8485 PetscFunctionReturn(0); 8486 } 8487 8488 /*@C 8489 DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 8490 8491 Collective on DM 8492 8493 Input Parameters: 8494 + dm - DM object you wish to monitor 8495 . name - the monitor type one is seeking 8496 . help - message indicating what monitoring is done 8497 . manual - manual page for the monitor 8498 . monitor - the monitor function 8499 - 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 8500 8501 Output Parameter: 8502 . flg - Flag set if the monitor was created 8503 8504 Level: developer 8505 8506 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 8507 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 8508 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 8509 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 8510 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 8511 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 8512 PetscOptionsFList(), PetscOptionsEList() 8513 @*/ 8514 PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg) 8515 { 8516 PetscViewer viewer; 8517 PetscViewerFormat format; 8518 PetscErrorCode ierr; 8519 8520 PetscFunctionBegin; 8521 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8522 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);CHKERRQ(ierr); 8523 if (*flg) { 8524 PetscViewerAndFormat *vf; 8525 8526 ierr = PetscViewerAndFormatCreate(viewer, format, &vf);CHKERRQ(ierr); 8527 ierr = PetscObjectDereference((PetscObject) viewer);CHKERRQ(ierr); 8528 if (monitorsetup) {ierr = (*monitorsetup)(dm, vf);CHKERRQ(ierr);} 8529 ierr = DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr); 8530 } 8531 PetscFunctionReturn(0); 8532 } 8533 8534 /*@ 8535 DMMonitor - runs the user provided monitor routines, if they exist 8536 8537 Collective on DM 8538 8539 Input Parameters: 8540 . dm - The DM 8541 8542 Level: developer 8543 8544 .seealso: DMMonitorSet() 8545 @*/ 8546 PetscErrorCode DMMonitor(DM dm) 8547 { 8548 PetscInt m; 8549 PetscErrorCode ierr; 8550 8551 PetscFunctionBegin; 8552 if (!dm) PetscFunctionReturn(0); 8553 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8554 for (m = 0; m < dm->numbermonitors; ++m) { 8555 ierr = (*dm->monitor[m])(dm, dm->monitorcontext[m]);CHKERRQ(ierr); 8556 } 8557 PetscFunctionReturn(0); 8558 } 8559