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. 6052 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates. Pass NULL to remove such information. 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 Notes: If per is PETSC_TRUE and maxCell is not provided, coordinates need to be already localized, or must be localized by hand by the user. 6057 6058 Level: developer 6059 6060 .seealso: DMGetPeriodicity() 6061 @*/ 6062 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 6063 { 6064 PetscInt dim, d; 6065 PetscErrorCode ierr; 6066 6067 PetscFunctionBegin; 6068 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6069 PetscValidLogicalCollectiveBool(dm,per,2); 6070 if (maxCell) {PetscValidRealPointer(maxCell,3);} 6071 if (L) {PetscValidRealPointer(L,4);} 6072 if (bd) {PetscValidPointer(bd,5);} 6073 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6074 if (maxCell) { 6075 if (!dm->maxCell) {ierr = PetscMalloc1(dim, &dm->maxCell);CHKERRQ(ierr);} 6076 for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d]; 6077 } else { /* remove maxCell information to disable automatic computation of localized vertices */ 6078 ierr = PetscFree(dm->maxCell);CHKERRQ(ierr); 6079 } 6080 6081 if (L) { 6082 if (!dm->L) {ierr = PetscMalloc1(dim, &dm->L);CHKERRQ(ierr);} 6083 for (d = 0; d < dim; ++d) dm->L[d] = L[d]; 6084 } 6085 if (bd) { 6086 if (!dm->bdtype) {ierr = PetscMalloc1(dim, &dm->bdtype);CHKERRQ(ierr);} 6087 for (d = 0; d < dim; ++d) dm->bdtype[d] = bd[d]; 6088 } 6089 dm->periodic = per; 6090 PetscFunctionReturn(0); 6091 } 6092 6093 /*@ 6094 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. 6095 6096 Input Parameters: 6097 + dm - The DM 6098 . in - The input coordinate point (dim numbers) 6099 - endpoint - Include the endpoint L_i 6100 6101 Output Parameter: 6102 . out - The localized coordinate point 6103 6104 Level: developer 6105 6106 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6107 @*/ 6108 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 6109 { 6110 PetscInt dim, d; 6111 PetscErrorCode ierr; 6112 6113 PetscFunctionBegin; 6114 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 6115 if (!dm->maxCell) { 6116 for (d = 0; d < dim; ++d) out[d] = in[d]; 6117 } else { 6118 if (endpoint) { 6119 for (d = 0; d < dim; ++d) { 6120 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)) { 6121 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 6122 } else { 6123 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6124 } 6125 } 6126 } else { 6127 for (d = 0; d < dim; ++d) { 6128 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6129 } 6130 } 6131 } 6132 PetscFunctionReturn(0); 6133 } 6134 6135 /* 6136 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. 6137 6138 Input Parameters: 6139 + dm - The DM 6140 . dim - The spatial dimension 6141 . anchor - The anchor point, the input point can be no more than maxCell away from it 6142 - in - The input coordinate point (dim numbers) 6143 6144 Output Parameter: 6145 . out - The localized coordinate point 6146 6147 Level: developer 6148 6149 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 6150 6151 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6152 */ 6153 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6154 { 6155 PetscInt d; 6156 6157 PetscFunctionBegin; 6158 if (!dm->maxCell) { 6159 for (d = 0; d < dim; ++d) out[d] = in[d]; 6160 } else { 6161 for (d = 0; d < dim; ++d) { 6162 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 6163 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6164 } else { 6165 out[d] = in[d]; 6166 } 6167 } 6168 } 6169 PetscFunctionReturn(0); 6170 } 6171 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 6172 { 6173 PetscInt d; 6174 6175 PetscFunctionBegin; 6176 if (!dm->maxCell) { 6177 for (d = 0; d < dim; ++d) out[d] = in[d]; 6178 } else { 6179 for (d = 0; d < dim; ++d) { 6180 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 6181 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6182 } else { 6183 out[d] = in[d]; 6184 } 6185 } 6186 } 6187 PetscFunctionReturn(0); 6188 } 6189 6190 /* 6191 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. 6192 6193 Input Parameters: 6194 + dm - The DM 6195 . dim - The spatial dimension 6196 . anchor - The anchor point, the input point can be no more than maxCell away from it 6197 . in - The input coordinate delta (dim numbers) 6198 - out - The input coordinate point (dim numbers) 6199 6200 Output Parameter: 6201 . out - The localized coordinate in + out 6202 6203 Level: developer 6204 6205 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 6206 6207 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 6208 */ 6209 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6210 { 6211 PetscInt d; 6212 6213 PetscFunctionBegin; 6214 if (!dm->maxCell) { 6215 for (d = 0; d < dim; ++d) out[d] += in[d]; 6216 } else { 6217 for (d = 0; d < dim; ++d) { 6218 const PetscReal maxC = dm->maxCell[d]; 6219 6220 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) { 6221 const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6222 6223 if (PetscAbsScalar(newCoord - anchor[d]) > maxC) 6224 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])); 6225 out[d] += newCoord; 6226 } else { 6227 out[d] += in[d]; 6228 } 6229 } 6230 } 6231 PetscFunctionReturn(0); 6232 } 6233 6234 /*@ 6235 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 6236 6237 Not collective 6238 6239 Input Parameter: 6240 . dm - The DM 6241 6242 Output Parameter: 6243 areLocalized - True if localized 6244 6245 Level: developer 6246 6247 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 6248 @*/ 6249 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 6250 { 6251 DM cdm; 6252 PetscSection coordSection; 6253 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 6254 PetscBool isPlex, alreadyLocalized; 6255 PetscErrorCode ierr; 6256 6257 PetscFunctionBegin; 6258 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6259 PetscValidBoolPointer(areLocalized, 2); 6260 *areLocalized = PETSC_FALSE; 6261 6262 /* We need some generic way of refering to cells/vertices */ 6263 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6264 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 6265 if (!isPlex) PetscFunctionReturn(0); 6266 6267 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6268 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6269 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 6270 alreadyLocalized = PETSC_FALSE; 6271 for (c = cStart; c < cEnd; ++c) { 6272 if (c < sStart || c >= sEnd) continue; 6273 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 6274 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 6275 } 6276 *areLocalized = alreadyLocalized; 6277 PetscFunctionReturn(0); 6278 } 6279 6280 /*@ 6281 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 6282 6283 Collective on dm 6284 6285 Input Parameter: 6286 . dm - The DM 6287 6288 Output Parameter: 6289 areLocalized - True if localized 6290 6291 Level: developer 6292 6293 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 6294 @*/ 6295 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 6296 { 6297 PetscBool localized; 6298 PetscErrorCode ierr; 6299 6300 PetscFunctionBegin; 6301 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6302 PetscValidBoolPointer(areLocalized, 2); 6303 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 6304 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6305 PetscFunctionReturn(0); 6306 } 6307 6308 /*@ 6309 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 6310 6311 Collective on dm 6312 6313 Input Parameter: 6314 . dm - The DM 6315 6316 Level: developer 6317 6318 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 6319 @*/ 6320 PetscErrorCode DMLocalizeCoordinates(DM dm) 6321 { 6322 DM cdm; 6323 PetscSection coordSection, cSection; 6324 Vec coordinates, cVec; 6325 PetscScalar *coords, *coords2, *anchor, *localized; 6326 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 6327 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 6328 PetscInt maxHeight = 0, h; 6329 PetscInt *pStart = NULL, *pEnd = NULL; 6330 PetscErrorCode ierr; 6331 6332 PetscFunctionBegin; 6333 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6334 if (!dm->periodic) PetscFunctionReturn(0); 6335 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 6336 if (alreadyLocalized) PetscFunctionReturn(0); 6337 6338 /* We need some generic way of refering to cells/vertices */ 6339 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6340 { 6341 PetscBool isplex; 6342 6343 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 6344 if (isplex) { 6345 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6346 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 6347 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6348 pEnd = &pStart[maxHeight + 1]; 6349 newStart = vStart; 6350 newEnd = vEnd; 6351 for (h = 0; h <= maxHeight; h++) { 6352 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 6353 newStart = PetscMin(newStart,pStart[h]); 6354 newEnd = PetscMax(newEnd,pEnd[h]); 6355 } 6356 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 6357 } 6358 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6359 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 6360 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6361 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 6362 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 6363 6364 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 6365 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 6366 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 6367 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 6368 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 6369 6370 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6371 localized = &anchor[bs]; 6372 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 6373 for (h = 0; h <= maxHeight; h++) { 6374 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6375 6376 for (c = cStart; c < cEnd; ++c) { 6377 PetscScalar *cellCoords = NULL; 6378 PetscInt b; 6379 6380 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 6381 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6382 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6383 for (d = 0; d < dof/bs; ++d) { 6384 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 6385 for (b = 0; b < bs; b++) { 6386 if (cellCoords[d*bs + b] != localized[b]) break; 6387 } 6388 if (b < bs) break; 6389 } 6390 if (d < dof/bs) { 6391 if (c >= sStart && c < sEnd) { 6392 PetscInt cdof; 6393 6394 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 6395 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 6396 } 6397 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 6398 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 6399 } 6400 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6401 } 6402 } 6403 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6404 if (alreadyLocalizedGlobal) { 6405 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6406 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6407 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6408 PetscFunctionReturn(0); 6409 } 6410 for (v = vStart; v < vEnd; ++v) { 6411 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6412 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 6413 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 6414 } 6415 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 6416 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 6417 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 6418 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 6419 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 6420 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 6421 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 6422 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6423 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 6424 for (v = vStart; v < vEnd; ++v) { 6425 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6426 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6427 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 6428 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 6429 } 6430 for (h = 0; h <= maxHeight; h++) { 6431 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6432 6433 for (c = cStart; c < cEnd; ++c) { 6434 PetscScalar *cellCoords = NULL; 6435 PetscInt b, cdof; 6436 6437 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 6438 if (!cdof) continue; 6439 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6440 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 6441 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6442 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 6443 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6444 } 6445 } 6446 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6447 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6448 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6449 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 6450 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 6451 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 6452 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 6453 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6454 PetscFunctionReturn(0); 6455 } 6456 6457 /*@ 6458 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 6459 6460 Collective on v (see explanation below) 6461 6462 Input Parameters: 6463 + dm - The DM 6464 . v - The Vec of points 6465 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 6466 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 6467 6468 Output Parameter: 6469 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 6470 - cells - The PetscSF containing the ranks and local indices of the containing points. 6471 6472 6473 Level: developer 6474 6475 Notes: 6476 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 6477 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 6478 6479 If *cellSF is NULL on input, a PetscSF will be created. 6480 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 6481 6482 An array that maps each point to its containing cell can be obtained with 6483 6484 $ const PetscSFNode *cells; 6485 $ PetscInt nFound; 6486 $ const PetscInt *found; 6487 $ 6488 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 6489 6490 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 6491 the index of the cell in its rank's local numbering. 6492 6493 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 6494 @*/ 6495 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 6496 { 6497 PetscErrorCode ierr; 6498 6499 PetscFunctionBegin; 6500 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6501 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 6502 PetscValidPointer(cellSF,4); 6503 if (*cellSF) { 6504 PetscMPIInt result; 6505 6506 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 6507 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 6508 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 6509 } else { 6510 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 6511 } 6512 if (!dm->ops->locatepoints) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 6513 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6514 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 6515 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6516 PetscFunctionReturn(0); 6517 } 6518 6519 /*@ 6520 DMGetOutputDM - Retrieve the DM associated with the layout for output 6521 6522 Collective on dm 6523 6524 Input Parameter: 6525 . dm - The original DM 6526 6527 Output Parameter: 6528 . odm - The DM which provides the layout for output 6529 6530 Level: intermediate 6531 6532 .seealso: VecView(), DMGetGlobalSection() 6533 @*/ 6534 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 6535 { 6536 PetscSection section; 6537 PetscBool hasConstraints, ghasConstraints; 6538 PetscErrorCode ierr; 6539 6540 PetscFunctionBegin; 6541 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6542 PetscValidPointer(odm,2); 6543 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 6544 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 6545 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 6546 if (!ghasConstraints) { 6547 *odm = dm; 6548 PetscFunctionReturn(0); 6549 } 6550 if (!dm->dmBC) { 6551 PetscSection newSection, gsection; 6552 PetscSF sf; 6553 6554 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 6555 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 6556 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 6557 ierr = DMSetLocalSection(dm->dmBC, newSection);CHKERRQ(ierr); 6558 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 6559 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 6560 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 6561 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 6562 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 6563 } 6564 *odm = dm->dmBC; 6565 PetscFunctionReturn(0); 6566 } 6567 6568 /*@ 6569 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 6570 6571 Input Parameter: 6572 . dm - The original DM 6573 6574 Output Parameters: 6575 + num - The output sequence number 6576 - val - The output sequence value 6577 6578 Level: intermediate 6579 6580 Note: This is intended for output that should appear in sequence, for instance 6581 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6582 6583 .seealso: VecView() 6584 @*/ 6585 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 6586 { 6587 PetscFunctionBegin; 6588 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6589 if (num) {PetscValidIntPointer(num,2); *num = dm->outputSequenceNum;} 6590 if (val) {PetscValidRealPointer(val,3);*val = dm->outputSequenceVal;} 6591 PetscFunctionReturn(0); 6592 } 6593 6594 /*@ 6595 DMSetOutputSequenceNumber - Set the sequence number/value for output 6596 6597 Input Parameters: 6598 + dm - The original DM 6599 . num - The output sequence number 6600 - val - The output sequence value 6601 6602 Level: intermediate 6603 6604 Note: This is intended for output that should appear in sequence, for instance 6605 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6606 6607 .seealso: VecView() 6608 @*/ 6609 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 6610 { 6611 PetscFunctionBegin; 6612 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6613 dm->outputSequenceNum = num; 6614 dm->outputSequenceVal = val; 6615 PetscFunctionReturn(0); 6616 } 6617 6618 /*@C 6619 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 6620 6621 Input Parameters: 6622 + dm - The original DM 6623 . name - The sequence name 6624 - num - The output sequence number 6625 6626 Output Parameter: 6627 . val - The output sequence value 6628 6629 Level: intermediate 6630 6631 Note: This is intended for output that should appear in sequence, for instance 6632 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6633 6634 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 6635 @*/ 6636 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 6637 { 6638 PetscBool ishdf5; 6639 PetscErrorCode ierr; 6640 6641 PetscFunctionBegin; 6642 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6643 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 6644 PetscValidRealPointer(val,4); 6645 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 6646 if (ishdf5) { 6647 #if defined(PETSC_HAVE_HDF5) 6648 PetscScalar value; 6649 6650 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 6651 *val = PetscRealPart(value); 6652 #endif 6653 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 6654 PetscFunctionReturn(0); 6655 } 6656 6657 /*@ 6658 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 6659 6660 Not collective 6661 6662 Input Parameter: 6663 . dm - The DM 6664 6665 Output Parameter: 6666 . useNatural - The flag to build the mapping to a natural order during distribution 6667 6668 Level: beginner 6669 6670 .seealso: DMSetUseNatural(), DMCreate() 6671 @*/ 6672 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 6673 { 6674 PetscFunctionBegin; 6675 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6676 PetscValidBoolPointer(useNatural, 2); 6677 *useNatural = dm->useNatural; 6678 PetscFunctionReturn(0); 6679 } 6680 6681 /*@ 6682 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 6683 6684 Collective on dm 6685 6686 Input Parameters: 6687 + dm - The DM 6688 - useNatural - The flag to build the mapping to a natural order during distribution 6689 6690 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 6691 6692 Level: beginner 6693 6694 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 6695 @*/ 6696 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 6697 { 6698 PetscFunctionBegin; 6699 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6700 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 6701 dm->useNatural = useNatural; 6702 PetscFunctionReturn(0); 6703 } 6704 6705 6706 /*@C 6707 DMCreateLabel - Create a label of the given name if it does not already exist 6708 6709 Not Collective 6710 6711 Input Parameters: 6712 + dm - The DM object 6713 - name - The label name 6714 6715 Level: intermediate 6716 6717 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6718 @*/ 6719 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 6720 { 6721 PetscBool flg; 6722 DMLabel label; 6723 PetscErrorCode ierr; 6724 6725 PetscFunctionBegin; 6726 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6727 PetscValidCharPointer(name, 2); 6728 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 6729 if (!flg) { 6730 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 6731 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 6732 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 6733 } 6734 PetscFunctionReturn(0); 6735 } 6736 6737 /*@C 6738 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 6739 6740 Not Collective 6741 6742 Input Parameters: 6743 + dm - The DM object 6744 . name - The label name 6745 - point - The mesh point 6746 6747 Output Parameter: 6748 . value - The label value for this point, or -1 if the point is not in the label 6749 6750 Level: beginner 6751 6752 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 6753 @*/ 6754 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 6755 { 6756 DMLabel label; 6757 PetscErrorCode ierr; 6758 6759 PetscFunctionBegin; 6760 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6761 PetscValidCharPointer(name, 2); 6762 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6763 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 6764 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 6765 PetscFunctionReturn(0); 6766 } 6767 6768 /*@C 6769 DMSetLabelValue - Add a point to a Sieve Label with given value 6770 6771 Not Collective 6772 6773 Input Parameters: 6774 + dm - The DM object 6775 . name - The label name 6776 . point - The mesh point 6777 - value - The label value for this point 6778 6779 Output Parameter: 6780 6781 Level: beginner 6782 6783 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 6784 @*/ 6785 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6786 { 6787 DMLabel label; 6788 PetscErrorCode ierr; 6789 6790 PetscFunctionBegin; 6791 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6792 PetscValidCharPointer(name, 2); 6793 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6794 if (!label) { 6795 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 6796 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6797 } 6798 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 6799 PetscFunctionReturn(0); 6800 } 6801 6802 /*@C 6803 DMClearLabelValue - Remove a point from a Sieve Label with given value 6804 6805 Not Collective 6806 6807 Input Parameters: 6808 + dm - The DM object 6809 . name - The label name 6810 . point - The mesh point 6811 - value - The label value for this point 6812 6813 Output Parameter: 6814 6815 Level: beginner 6816 6817 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 6818 @*/ 6819 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6820 { 6821 DMLabel label; 6822 PetscErrorCode ierr; 6823 6824 PetscFunctionBegin; 6825 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6826 PetscValidCharPointer(name, 2); 6827 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6828 if (!label) PetscFunctionReturn(0); 6829 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 6830 PetscFunctionReturn(0); 6831 } 6832 6833 /*@C 6834 DMGetLabelSize - Get the number of different integer ids in a Label 6835 6836 Not Collective 6837 6838 Input Parameters: 6839 + dm - The DM object 6840 - name - The label name 6841 6842 Output Parameter: 6843 . size - The number of different integer ids, or 0 if the label does not exist 6844 6845 Level: beginner 6846 6847 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 6848 @*/ 6849 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 6850 { 6851 DMLabel label; 6852 PetscErrorCode ierr; 6853 6854 PetscFunctionBegin; 6855 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6856 PetscValidCharPointer(name, 2); 6857 PetscValidIntPointer(size, 3); 6858 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6859 *size = 0; 6860 if (!label) PetscFunctionReturn(0); 6861 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 6862 PetscFunctionReturn(0); 6863 } 6864 6865 /*@C 6866 DMGetLabelIdIS - Get the integer ids in a label 6867 6868 Not Collective 6869 6870 Input Parameters: 6871 + mesh - The DM object 6872 - name - The label name 6873 6874 Output Parameter: 6875 . ids - The integer ids, or NULL if the label does not exist 6876 6877 Level: beginner 6878 6879 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 6880 @*/ 6881 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 6882 { 6883 DMLabel label; 6884 PetscErrorCode ierr; 6885 6886 PetscFunctionBegin; 6887 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6888 PetscValidCharPointer(name, 2); 6889 PetscValidPointer(ids, 3); 6890 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6891 *ids = NULL; 6892 if (label) { 6893 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 6894 } else { 6895 /* returning an empty IS */ 6896 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 6897 } 6898 PetscFunctionReturn(0); 6899 } 6900 6901 /*@C 6902 DMGetStratumSize - Get the number of points in a label stratum 6903 6904 Not Collective 6905 6906 Input Parameters: 6907 + dm - The DM object 6908 . name - The label name 6909 - value - The stratum value 6910 6911 Output Parameter: 6912 . size - The stratum size 6913 6914 Level: beginner 6915 6916 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 6917 @*/ 6918 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 6919 { 6920 DMLabel label; 6921 PetscErrorCode ierr; 6922 6923 PetscFunctionBegin; 6924 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6925 PetscValidCharPointer(name, 2); 6926 PetscValidIntPointer(size, 4); 6927 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6928 *size = 0; 6929 if (!label) PetscFunctionReturn(0); 6930 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 6931 PetscFunctionReturn(0); 6932 } 6933 6934 /*@C 6935 DMGetStratumIS - Get the points in a label stratum 6936 6937 Not Collective 6938 6939 Input Parameters: 6940 + dm - The DM object 6941 . name - The label name 6942 - value - The stratum value 6943 6944 Output Parameter: 6945 . points - The stratum points, or NULL if the label does not exist or does not have that value 6946 6947 Level: beginner 6948 6949 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 6950 @*/ 6951 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 6952 { 6953 DMLabel label; 6954 PetscErrorCode ierr; 6955 6956 PetscFunctionBegin; 6957 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6958 PetscValidCharPointer(name, 2); 6959 PetscValidPointer(points, 4); 6960 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6961 *points = NULL; 6962 if (!label) PetscFunctionReturn(0); 6963 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 6964 PetscFunctionReturn(0); 6965 } 6966 6967 /*@C 6968 DMSetStratumIS - Set the points in a label stratum 6969 6970 Not Collective 6971 6972 Input Parameters: 6973 + dm - The DM object 6974 . name - The label name 6975 . value - The stratum value 6976 - points - The stratum points 6977 6978 Level: beginner 6979 6980 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 6981 @*/ 6982 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 6983 { 6984 DMLabel label; 6985 PetscErrorCode ierr; 6986 6987 PetscFunctionBegin; 6988 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6989 PetscValidCharPointer(name, 2); 6990 PetscValidPointer(points, 4); 6991 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6992 if (!label) PetscFunctionReturn(0); 6993 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 6994 PetscFunctionReturn(0); 6995 } 6996 6997 /*@C 6998 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 6999 7000 Not Collective 7001 7002 Input Parameters: 7003 + dm - The DM object 7004 . name - The label name 7005 - value - The label value for this point 7006 7007 Output Parameter: 7008 7009 Level: beginner 7010 7011 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 7012 @*/ 7013 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 7014 { 7015 DMLabel label; 7016 PetscErrorCode ierr; 7017 7018 PetscFunctionBegin; 7019 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7020 PetscValidCharPointer(name, 2); 7021 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7022 if (!label) PetscFunctionReturn(0); 7023 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 7024 PetscFunctionReturn(0); 7025 } 7026 7027 /*@ 7028 DMGetNumLabels - Return the number of labels defined by the mesh 7029 7030 Not Collective 7031 7032 Input Parameter: 7033 . dm - The DM object 7034 7035 Output Parameter: 7036 . numLabels - the number of Labels 7037 7038 Level: intermediate 7039 7040 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7041 @*/ 7042 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 7043 { 7044 DMLabelLink next = dm->labels; 7045 PetscInt n = 0; 7046 7047 PetscFunctionBegin; 7048 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7049 PetscValidIntPointer(numLabels, 2); 7050 while (next) {++n; next = next->next;} 7051 *numLabels = n; 7052 PetscFunctionReturn(0); 7053 } 7054 7055 /*@C 7056 DMGetLabelName - Return the name of nth label 7057 7058 Not Collective 7059 7060 Input Parameters: 7061 + dm - The DM object 7062 - n - the label number 7063 7064 Output Parameter: 7065 . name - the label name 7066 7067 Level: intermediate 7068 7069 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7070 @*/ 7071 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 7072 { 7073 DMLabelLink next = dm->labels; 7074 PetscInt l = 0; 7075 PetscErrorCode ierr; 7076 7077 PetscFunctionBegin; 7078 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7079 PetscValidPointer(name, 3); 7080 while (next) { 7081 if (l == n) { 7082 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 7083 PetscFunctionReturn(0); 7084 } 7085 ++l; 7086 next = next->next; 7087 } 7088 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7089 } 7090 7091 /*@C 7092 DMHasLabel - Determine whether the mesh has a label of a given name 7093 7094 Not Collective 7095 7096 Input Parameters: 7097 + dm - The DM object 7098 - name - The label name 7099 7100 Output Parameter: 7101 . hasLabel - PETSC_TRUE if the label is present 7102 7103 Level: intermediate 7104 7105 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7106 @*/ 7107 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 7108 { 7109 DMLabelLink next = dm->labels; 7110 const char *lname; 7111 PetscErrorCode ierr; 7112 7113 PetscFunctionBegin; 7114 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7115 PetscValidCharPointer(name, 2); 7116 PetscValidBoolPointer(hasLabel, 3); 7117 *hasLabel = PETSC_FALSE; 7118 while (next) { 7119 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7120 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 7121 if (*hasLabel) break; 7122 next = next->next; 7123 } 7124 PetscFunctionReturn(0); 7125 } 7126 7127 /*@C 7128 DMGetLabel - Return the label of a given name, or NULL 7129 7130 Not Collective 7131 7132 Input Parameters: 7133 + dm - The DM object 7134 - name - The label name 7135 7136 Output Parameter: 7137 . label - The DMLabel, or NULL if the label is absent 7138 7139 Level: intermediate 7140 7141 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7142 @*/ 7143 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 7144 { 7145 DMLabelLink next = dm->labels; 7146 PetscBool hasLabel; 7147 const char *lname; 7148 PetscErrorCode ierr; 7149 7150 PetscFunctionBegin; 7151 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7152 PetscValidCharPointer(name, 2); 7153 PetscValidPointer(label, 3); 7154 *label = NULL; 7155 while (next) { 7156 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7157 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7158 if (hasLabel) { 7159 *label = next->label; 7160 break; 7161 } 7162 next = next->next; 7163 } 7164 PetscFunctionReturn(0); 7165 } 7166 7167 /*@C 7168 DMGetLabelByNum - Return the nth label 7169 7170 Not Collective 7171 7172 Input Parameters: 7173 + dm - The DM object 7174 - n - the label number 7175 7176 Output Parameter: 7177 . label - the label 7178 7179 Level: intermediate 7180 7181 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7182 @*/ 7183 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 7184 { 7185 DMLabelLink next = dm->labels; 7186 PetscInt l = 0; 7187 7188 PetscFunctionBegin; 7189 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7190 PetscValidPointer(label, 3); 7191 while (next) { 7192 if (l == n) { 7193 *label = next->label; 7194 PetscFunctionReturn(0); 7195 } 7196 ++l; 7197 next = next->next; 7198 } 7199 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7200 } 7201 7202 /*@C 7203 DMAddLabel - Add the label to this mesh 7204 7205 Not Collective 7206 7207 Input Parameters: 7208 + dm - The DM object 7209 - label - The DMLabel 7210 7211 Level: developer 7212 7213 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7214 @*/ 7215 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 7216 { 7217 DMLabelLink l, *p, tmpLabel; 7218 PetscBool hasLabel; 7219 const char *lname; 7220 PetscBool flg; 7221 PetscErrorCode ierr; 7222 7223 PetscFunctionBegin; 7224 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7225 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 7226 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 7227 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 7228 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 7229 tmpLabel->label = label; 7230 tmpLabel->output = PETSC_TRUE; 7231 for (p=&dm->labels; (l=*p); p=&l->next) {} 7232 *p = tmpLabel; 7233 ierr = PetscObjectReference((PetscObject)label);CHKERRQ(ierr); 7234 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 7235 if (flg) dm->depthLabel = label; 7236 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 7237 if (flg) dm->celltypeLabel = label; 7238 PetscFunctionReturn(0); 7239 } 7240 7241 /*@C 7242 DMRemoveLabel - Remove the label given by name from this mesh 7243 7244 Not Collective 7245 7246 Input Parameters: 7247 + dm - The DM object 7248 - name - The label name 7249 7250 Output Parameter: 7251 . label - The DMLabel, or NULL if the label is absent 7252 7253 Level: developer 7254 7255 Notes: 7256 DMRemoveLabel(dm,name,NULL) removes the label from dm and calls 7257 DMLabelDestroy() on the label. 7258 7259 DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT 7260 call DMLabelDestroy(). Instead, the label is returned and the user is 7261 responsible of calling DMLabelDestroy() at some point. 7262 7263 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf() 7264 @*/ 7265 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 7266 { 7267 DMLabelLink link, *pnext; 7268 PetscBool hasLabel; 7269 const char *lname; 7270 PetscErrorCode ierr; 7271 7272 PetscFunctionBegin; 7273 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7274 PetscValidCharPointer(name, 2); 7275 if (label) { 7276 PetscValidPointer(label, 3); 7277 *label = NULL; 7278 } 7279 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7280 ierr = PetscObjectGetName((PetscObject) link->label, &lname);CHKERRQ(ierr); 7281 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7282 if (hasLabel) { 7283 *pnext = link->next; /* Remove from list */ 7284 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 7285 if (hasLabel) dm->depthLabel = NULL; 7286 ierr = PetscStrcmp(name, "celltype", &hasLabel);CHKERRQ(ierr); 7287 if (hasLabel) dm->celltypeLabel = NULL; 7288 if (label) *label = link->label; 7289 else {ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);} 7290 ierr = PetscFree(link);CHKERRQ(ierr); 7291 break; 7292 } 7293 } 7294 PetscFunctionReturn(0); 7295 } 7296 7297 /*@ 7298 DMRemoveLabelBySelf - Remove the label from this mesh 7299 7300 Not Collective 7301 7302 Input Parameters: 7303 + dm - The DM object 7304 . label - (Optional) The DMLabel to be removed from the DM 7305 - failNotFound - Should it fail if the label is not found in the DM? 7306 7307 Level: developer 7308 7309 Notes: 7310 Only exactly the same instance is removed if found, name match is ignored. 7311 If the DM has an exclusive reference to the label, it gets destroyed and 7312 *label nullified. 7313 7314 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel() 7315 @*/ 7316 PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound) 7317 { 7318 DMLabelLink link, *pnext; 7319 PetscBool hasLabel = PETSC_FALSE; 7320 PetscErrorCode ierr; 7321 7322 PetscFunctionBegin; 7323 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7324 PetscValidPointer(label, 2); 7325 if (!*label && !failNotFound) PetscFunctionReturn(0); 7326 PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2); 7327 PetscValidLogicalCollectiveBool(dm,failNotFound,3); 7328 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7329 if (*label == link->label) { 7330 hasLabel = PETSC_TRUE; 7331 *pnext = link->next; /* Remove from list */ 7332 if (*label == dm->depthLabel) dm->depthLabel = NULL; 7333 if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL; 7334 if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */ 7335 ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr); 7336 ierr = PetscFree(link);CHKERRQ(ierr); 7337 break; 7338 } 7339 } 7340 if (!hasLabel && failNotFound) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM"); 7341 PetscFunctionReturn(0); 7342 } 7343 7344 /*@C 7345 DMGetLabelOutput - Get the output flag for a given label 7346 7347 Not Collective 7348 7349 Input Parameters: 7350 + dm - The DM object 7351 - name - The label name 7352 7353 Output Parameter: 7354 . output - The flag for output 7355 7356 Level: developer 7357 7358 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7359 @*/ 7360 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 7361 { 7362 DMLabelLink next = dm->labels; 7363 const char *lname; 7364 PetscErrorCode ierr; 7365 7366 PetscFunctionBegin; 7367 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7368 PetscValidPointer(name, 2); 7369 PetscValidPointer(output, 3); 7370 while (next) { 7371 PetscBool flg; 7372 7373 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7374 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7375 if (flg) {*output = next->output; PetscFunctionReturn(0);} 7376 next = next->next; 7377 } 7378 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7379 } 7380 7381 /*@C 7382 DMSetLabelOutput - Set the output flag for a given label 7383 7384 Not Collective 7385 7386 Input Parameters: 7387 + dm - The DM object 7388 . name - The label name 7389 - output - The flag for output 7390 7391 Level: developer 7392 7393 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7394 @*/ 7395 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 7396 { 7397 DMLabelLink next = dm->labels; 7398 const char *lname; 7399 PetscErrorCode ierr; 7400 7401 PetscFunctionBegin; 7402 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7403 PetscValidCharPointer(name, 2); 7404 while (next) { 7405 PetscBool flg; 7406 7407 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7408 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7409 if (flg) {next->output = output; PetscFunctionReturn(0);} 7410 next = next->next; 7411 } 7412 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7413 } 7414 7415 /*@ 7416 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 7417 7418 Collective on dmA 7419 7420 Input Parameter: 7421 + dmA - The DM object with initial labels 7422 . dmB - The DM object with copied labels 7423 . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES) 7424 - all - Copy all labels including "depth", "dim", and "celltype" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE) 7425 7426 Level: intermediate 7427 7428 Note: This is typically used when interpolating or otherwise adding to a mesh 7429 7430 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection(), DMShareLabels() 7431 @*/ 7432 PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all) 7433 { 7434 DMLabel label, labelNew; 7435 const char *name; 7436 PetscBool flg; 7437 DMLabelLink link; 7438 PetscErrorCode ierr; 7439 7440 PetscFunctionBegin; 7441 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 7442 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 7443 PetscValidLogicalCollectiveEnum(dmA, mode,3); 7444 PetscValidLogicalCollectiveBool(dmA, all, 4); 7445 if (mode==PETSC_USE_POINTER) SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects"); 7446 if (dmA == dmB) PetscFunctionReturn(0); 7447 for (link=dmA->labels; link; link=link->next) { 7448 label=link->label; 7449 ierr = PetscObjectGetName((PetscObject)label, &name);CHKERRQ(ierr); 7450 if (!all) { 7451 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 7452 if (flg) continue; 7453 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 7454 if (flg) continue; 7455 ierr = PetscStrcmp(name, "celltype", &flg);CHKERRQ(ierr); 7456 if (flg) continue; 7457 } 7458 if (mode==PETSC_COPY_VALUES) { 7459 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 7460 } else { 7461 labelNew = label; 7462 } 7463 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 7464 if (mode==PETSC_COPY_VALUES) {ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);} 7465 } 7466 PetscFunctionReturn(0); 7467 } 7468 7469 /*@ 7470 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 7471 7472 Input Parameter: 7473 . dm - The DM object 7474 7475 Output Parameter: 7476 . cdm - The coarse DM 7477 7478 Level: intermediate 7479 7480 .seealso: DMSetCoarseDM() 7481 @*/ 7482 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 7483 { 7484 PetscFunctionBegin; 7485 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7486 PetscValidPointer(cdm, 2); 7487 *cdm = dm->coarseMesh; 7488 PetscFunctionReturn(0); 7489 } 7490 7491 /*@ 7492 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 7493 7494 Input Parameters: 7495 + dm - The DM object 7496 - cdm - The coarse DM 7497 7498 Level: intermediate 7499 7500 .seealso: DMGetCoarseDM() 7501 @*/ 7502 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 7503 { 7504 PetscErrorCode ierr; 7505 7506 PetscFunctionBegin; 7507 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7508 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 7509 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 7510 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 7511 dm->coarseMesh = cdm; 7512 PetscFunctionReturn(0); 7513 } 7514 7515 /*@ 7516 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 7517 7518 Input Parameter: 7519 . dm - The DM object 7520 7521 Output Parameter: 7522 . fdm - The fine DM 7523 7524 Level: intermediate 7525 7526 .seealso: DMSetFineDM() 7527 @*/ 7528 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 7529 { 7530 PetscFunctionBegin; 7531 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7532 PetscValidPointer(fdm, 2); 7533 *fdm = dm->fineMesh; 7534 PetscFunctionReturn(0); 7535 } 7536 7537 /*@ 7538 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 7539 7540 Input Parameters: 7541 + dm - The DM object 7542 - fdm - The fine DM 7543 7544 Level: intermediate 7545 7546 .seealso: DMGetFineDM() 7547 @*/ 7548 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 7549 { 7550 PetscErrorCode ierr; 7551 7552 PetscFunctionBegin; 7553 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7554 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 7555 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 7556 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 7557 dm->fineMesh = fdm; 7558 PetscFunctionReturn(0); 7559 } 7560 7561 /*=== DMBoundary code ===*/ 7562 7563 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 7564 { 7565 PetscInt d; 7566 PetscErrorCode ierr; 7567 7568 PetscFunctionBegin; 7569 for (d = 0; d < dm->Nds; ++d) { 7570 ierr = PetscDSCopyBoundary(dm->probs[d].ds, dmNew->probs[d].ds);CHKERRQ(ierr); 7571 } 7572 PetscFunctionReturn(0); 7573 } 7574 7575 /*@C 7576 DMAddBoundary - Add a boundary condition to the model 7577 7578 Input Parameters: 7579 + dm - The DM, with a PetscDS that matches the problem being constrained 7580 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7581 . name - The BC name 7582 . labelname - The label defining constrained points 7583 . field - The field to constrain 7584 . numcomps - The number of constrained field components (0 will constrain all fields) 7585 . comps - An array of constrained component numbers 7586 . bcFunc - A pointwise function giving boundary values 7587 . numids - The number of DMLabel ids for constrained points 7588 . ids - An array of ids for constrained points 7589 - ctx - An optional user context for bcFunc 7590 7591 Options Database Keys: 7592 + -bc_<boundary name> <num> - Overrides the boundary ids 7593 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7594 7595 Level: developer 7596 7597 .seealso: DMGetBoundary() 7598 @*/ 7599 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) 7600 { 7601 PetscDS ds; 7602 PetscErrorCode ierr; 7603 7604 PetscFunctionBegin; 7605 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7606 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7607 ierr = PetscDSAddBoundary(ds, type,name, labelname, field, numcomps, comps, bcFunc, numids, ids, ctx);CHKERRQ(ierr); 7608 PetscFunctionReturn(0); 7609 } 7610 7611 /*@ 7612 DMGetNumBoundary - Get the number of registered BC 7613 7614 Input Parameters: 7615 . dm - The mesh object 7616 7617 Output Parameters: 7618 . numBd - The number of BC 7619 7620 Level: intermediate 7621 7622 .seealso: DMAddBoundary(), DMGetBoundary() 7623 @*/ 7624 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 7625 { 7626 PetscDS ds; 7627 PetscErrorCode ierr; 7628 7629 PetscFunctionBegin; 7630 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7631 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7632 ierr = PetscDSGetNumBoundary(ds, numBd);CHKERRQ(ierr); 7633 PetscFunctionReturn(0); 7634 } 7635 7636 /*@C 7637 DMGetBoundary - Get a model boundary condition 7638 7639 Input Parameters: 7640 + dm - The mesh object 7641 - bd - The BC number 7642 7643 Output Parameters: 7644 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7645 . name - The BC name 7646 . labelname - The label defining constrained points 7647 . field - The field to constrain 7648 . numcomps - The number of constrained field components 7649 . comps - An array of constrained component numbers 7650 . bcFunc - A pointwise function giving boundary values 7651 . numids - The number of DMLabel ids for constrained points 7652 . ids - An array of ids for constrained points 7653 - ctx - An optional user context for bcFunc 7654 7655 Options Database Keys: 7656 + -bc_<boundary name> <num> - Overrides the boundary ids 7657 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7658 7659 Level: developer 7660 7661 .seealso: DMAddBoundary() 7662 @*/ 7663 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) 7664 { 7665 PetscDS ds; 7666 PetscErrorCode ierr; 7667 7668 PetscFunctionBegin; 7669 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7670 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7671 ierr = PetscDSGetBoundary(ds, bd, type, name, labelname, field, numcomps, comps, func, numids, ids, ctx);CHKERRQ(ierr); 7672 PetscFunctionReturn(0); 7673 } 7674 7675 static PetscErrorCode DMPopulateBoundary(DM dm) 7676 { 7677 PetscDS ds; 7678 DMBoundary *lastnext; 7679 DSBoundary dsbound; 7680 PetscErrorCode ierr; 7681 7682 PetscFunctionBegin; 7683 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7684 dsbound = ds->boundary; 7685 if (dm->boundary) { 7686 DMBoundary next = dm->boundary; 7687 7688 /* quick check to see if the PetscDS has changed */ 7689 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 7690 /* the PetscDS has changed: tear down and rebuild */ 7691 while (next) { 7692 DMBoundary b = next; 7693 7694 next = b->next; 7695 ierr = PetscFree(b);CHKERRQ(ierr); 7696 } 7697 dm->boundary = NULL; 7698 } 7699 7700 lastnext = &(dm->boundary); 7701 while (dsbound) { 7702 DMBoundary dmbound; 7703 7704 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 7705 dmbound->dsboundary = dsbound; 7706 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 7707 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 7708 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 7709 *lastnext = dmbound; 7710 lastnext = &(dmbound->next); 7711 dsbound = dsbound->next; 7712 } 7713 PetscFunctionReturn(0); 7714 } 7715 7716 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 7717 { 7718 DMBoundary b; 7719 PetscErrorCode ierr; 7720 7721 PetscFunctionBegin; 7722 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7723 PetscValidBoolPointer(isBd, 3); 7724 *isBd = PETSC_FALSE; 7725 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 7726 b = dm->boundary; 7727 while (b && !(*isBd)) { 7728 DMLabel label = b->label; 7729 DSBoundary dsb = b->dsboundary; 7730 7731 if (label) { 7732 PetscInt i; 7733 7734 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 7735 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 7736 } 7737 } 7738 b = b->next; 7739 } 7740 PetscFunctionReturn(0); 7741 } 7742 7743 /*@C 7744 DMProjectFunction - This projects the given function into the function space provided, putting the coefficients in a global vector. 7745 7746 Collective on DM 7747 7748 Input Parameters: 7749 + dm - The DM 7750 . time - The time 7751 . funcs - The coordinate functions to evaluate, one per field 7752 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7753 - mode - The insertion mode for values 7754 7755 Output Parameter: 7756 . X - vector 7757 7758 Calling sequence of func: 7759 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7760 7761 + dim - The spatial dimension 7762 . x - The coordinates 7763 . Nf - The number of fields 7764 . u - The output field values 7765 - ctx - optional user-defined function context 7766 7767 Level: developer 7768 7769 .seealso: DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 7770 @*/ 7771 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 7772 { 7773 Vec localX; 7774 PetscErrorCode ierr; 7775 7776 PetscFunctionBegin; 7777 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7778 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7779 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7780 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7781 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7782 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7783 PetscFunctionReturn(0); 7784 } 7785 7786 /*@C 7787 DMProjectFunctionLocal - This projects the given function into the function space provided, putting the coefficients in a local vector. 7788 7789 Not collective 7790 7791 Input Parameters: 7792 + dm - The DM 7793 . time - The time 7794 . funcs - The coordinate functions to evaluate, one per field 7795 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7796 - mode - The insertion mode for values 7797 7798 Output Parameter: 7799 . localX - vector 7800 7801 Calling sequence of func: 7802 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7803 7804 + dim - The spatial dimension 7805 . x - The coordinates 7806 . Nf - The number of fields 7807 . u - The output field values 7808 - ctx - optional user-defined function context 7809 7810 Level: developer 7811 7812 .seealso: DMProjectFunction(), DMProjectFunctionLabel(), DMComputeL2Diff() 7813 @*/ 7814 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 7815 { 7816 PetscErrorCode ierr; 7817 7818 PetscFunctionBegin; 7819 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7820 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7821 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 7822 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7823 PetscFunctionReturn(0); 7824 } 7825 7826 /*@C 7827 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. 7828 7829 Collective on DM 7830 7831 Input Parameters: 7832 + dm - The DM 7833 . time - The time 7834 . label - The DMLabel selecting the portion of the mesh for projection 7835 . funcs - The coordinate functions to evaluate, one per field 7836 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7837 - mode - The insertion mode for values 7838 7839 Output Parameter: 7840 . X - vector 7841 7842 Calling sequence of func: 7843 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7844 7845 + dim - The spatial dimension 7846 . x - The coordinates 7847 . Nf - The number of fields 7848 . u - The output field values 7849 - ctx - optional user-defined function context 7850 7851 Level: developer 7852 7853 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal(), DMComputeL2Diff() 7854 @*/ 7855 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) 7856 { 7857 Vec localX; 7858 PetscErrorCode ierr; 7859 7860 PetscFunctionBegin; 7861 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7862 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7863 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7864 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7865 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7866 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7867 PetscFunctionReturn(0); 7868 } 7869 7870 /*@C 7871 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. 7872 7873 Not collective 7874 7875 Input Parameters: 7876 + dm - The DM 7877 . time - The time 7878 . label - The DMLabel selecting the portion of the mesh for projection 7879 . funcs - The coordinate functions to evaluate, one per field 7880 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7881 - mode - The insertion mode for values 7882 7883 Output Parameter: 7884 . localX - vector 7885 7886 Calling sequence of func: 7887 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7888 7889 + dim - The spatial dimension 7890 . x - The coordinates 7891 . Nf - The number of fields 7892 . u - The output field values 7893 - ctx - optional user-defined function context 7894 7895 Level: developer 7896 7897 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 7898 @*/ 7899 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) 7900 { 7901 PetscErrorCode ierr; 7902 7903 PetscFunctionBegin; 7904 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7905 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7906 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 7907 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7908 PetscFunctionReturn(0); 7909 } 7910 7911 /*@C 7912 DMProjectFieldLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector. 7913 7914 Not collective 7915 7916 Input Parameters: 7917 + dm - The DM 7918 . time - The time 7919 . localU - The input field vector 7920 . funcs - The functions to evaluate, one per field 7921 - mode - The insertion mode for values 7922 7923 Output Parameter: 7924 . localX - The output vector 7925 7926 Calling sequence of func: 7927 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 7928 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 7929 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 7930 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 7931 7932 + dim - The spatial dimension 7933 . Nf - The number of input fields 7934 . NfAux - The number of input auxiliary fields 7935 . uOff - The offset of each field in u[] 7936 . uOff_x - The offset of each field in u_x[] 7937 . u - The field values at this point in space 7938 . u_t - The field time derivative at this point in space (or NULL) 7939 . u_x - The field derivatives at this point in space 7940 . aOff - The offset of each auxiliary field in u[] 7941 . aOff_x - The offset of each auxiliary field in u_x[] 7942 . a - The auxiliary field values at this point in space 7943 . a_t - The auxiliary field time derivative at this point in space (or NULL) 7944 . a_x - The auxiliary field derivatives at this point in space 7945 . t - The current time 7946 . x - The coordinates of this point 7947 . numConstants - The number of constants 7948 . constants - The value of each constant 7949 - f - The value of the function at this point in space 7950 7951 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. 7952 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 7953 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 7954 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 7955 7956 Level: intermediate 7957 7958 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 7959 @*/ 7960 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 7961 void (**funcs)(PetscInt, PetscInt, PetscInt, 7962 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7963 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7964 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 7965 InsertMode mode, Vec localX) 7966 { 7967 PetscErrorCode ierr; 7968 7969 PetscFunctionBegin; 7970 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7971 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 7972 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 7973 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 7974 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 7975 PetscFunctionReturn(0); 7976 } 7977 7978 /*@C 7979 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. 7980 7981 Not collective 7982 7983 Input Parameters: 7984 + dm - The DM 7985 . time - The time 7986 . label - The DMLabel marking the portion of the domain to output 7987 . numIds - The number of label ids to use 7988 . ids - The label ids to use for marking 7989 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 7990 . comps - The components to set in the output, or NULL for all components 7991 . localU - The input field vector 7992 . funcs - The functions to evaluate, one per field 7993 - mode - The insertion mode for values 7994 7995 Output Parameter: 7996 . localX - The output vector 7997 7998 Calling sequence of func: 7999 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8000 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8001 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8002 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8003 8004 + dim - The spatial dimension 8005 . Nf - The number of input fields 8006 . NfAux - The number of input auxiliary fields 8007 . uOff - The offset of each field in u[] 8008 . uOff_x - The offset of each field in u_x[] 8009 . u - The field values at this point in space 8010 . u_t - The field time derivative at this point in space (or NULL) 8011 . u_x - The field derivatives at this point in space 8012 . aOff - The offset of each auxiliary field in u[] 8013 . aOff_x - The offset of each auxiliary field in u_x[] 8014 . a - The auxiliary field values at this point in space 8015 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8016 . a_x - The auxiliary field derivatives at this point in space 8017 . t - The current time 8018 . x - The coordinates of this point 8019 . numConstants - The number of constants 8020 . constants - The value of each constant 8021 - f - The value of the function at this point in space 8022 8023 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. 8024 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 8025 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8026 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8027 8028 Level: intermediate 8029 8030 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8031 @*/ 8032 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 8033 void (**funcs)(PetscInt, PetscInt, PetscInt, 8034 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8035 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8036 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8037 InsertMode mode, Vec localX) 8038 { 8039 PetscErrorCode ierr; 8040 8041 PetscFunctionBegin; 8042 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8043 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 8044 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 8045 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 8046 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 8047 PetscFunctionReturn(0); 8048 } 8049 8050 /*@C 8051 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 8052 8053 Input Parameters: 8054 + dm - The DM 8055 . time - The time 8056 . funcs - The functions to evaluate for each field component 8057 . ctxs - Optional array of contexts to pass to each function, or NULL. 8058 - X - The coefficient vector u_h, a global vector 8059 8060 Output Parameter: 8061 . diff - The diff ||u - u_h||_2 8062 8063 Level: developer 8064 8065 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 8066 @*/ 8067 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 8068 { 8069 PetscErrorCode ierr; 8070 8071 PetscFunctionBegin; 8072 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8073 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8074 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 8075 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 8076 PetscFunctionReturn(0); 8077 } 8078 8079 /*@C 8080 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 8081 8082 Collective on dm 8083 8084 Input Parameters: 8085 + dm - The DM 8086 , time - The time 8087 . funcs - The gradient functions to evaluate for each field component 8088 . ctxs - Optional array of contexts to pass to each function, or NULL. 8089 . X - The coefficient vector u_h, a global vector 8090 - n - The vector to project along 8091 8092 Output Parameter: 8093 . diff - The diff ||(grad u - grad u_h) . n||_2 8094 8095 Level: developer 8096 8097 .seealso: DMProjectFunction(), DMComputeL2Diff() 8098 @*/ 8099 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) 8100 { 8101 PetscErrorCode ierr; 8102 8103 PetscFunctionBegin; 8104 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8105 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8106 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 8107 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 8108 PetscFunctionReturn(0); 8109 } 8110 8111 /*@C 8112 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 8113 8114 Collective on dm 8115 8116 Input Parameters: 8117 + dm - The DM 8118 . time - The time 8119 . funcs - The functions to evaluate for each field component 8120 . ctxs - Optional array of contexts to pass to each function, or NULL. 8121 - X - The coefficient vector u_h, a global vector 8122 8123 Output Parameter: 8124 . diff - The array of differences, ||u^f - u^f_h||_2 8125 8126 Level: developer 8127 8128 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 8129 @*/ 8130 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 8131 { 8132 PetscErrorCode ierr; 8133 8134 PetscFunctionBegin; 8135 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8136 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8137 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 8138 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 8139 PetscFunctionReturn(0); 8140 } 8141 8142 /*@C 8143 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 8144 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 8145 8146 Collective on dm 8147 8148 Input parameters: 8149 + dm - the pre-adaptation DM object 8150 - label - label with the flags 8151 8152 Output parameters: 8153 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 8154 8155 Level: intermediate 8156 8157 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 8158 @*/ 8159 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 8160 { 8161 PetscErrorCode ierr; 8162 8163 PetscFunctionBegin; 8164 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8165 PetscValidPointer(label,2); 8166 PetscValidPointer(dmAdapt,3); 8167 *dmAdapt = NULL; 8168 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 8169 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 8170 PetscFunctionReturn(0); 8171 } 8172 8173 /*@C 8174 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 8175 8176 Input Parameters: 8177 + dm - The DM object 8178 . metric - The metric to which the mesh is adapted, defined vertex-wise. 8179 - 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_". 8180 8181 Output Parameter: 8182 . dmAdapt - Pointer to the DM object containing the adapted mesh 8183 8184 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 8185 8186 Level: advanced 8187 8188 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 8189 @*/ 8190 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 8191 { 8192 PetscErrorCode ierr; 8193 8194 PetscFunctionBegin; 8195 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8196 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 8197 if (bdLabel) PetscValidPointer(bdLabel, 3); 8198 PetscValidPointer(dmAdapt, 4); 8199 *dmAdapt = NULL; 8200 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 8201 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 8202 PetscFunctionReturn(0); 8203 } 8204 8205 /*@C 8206 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 8207 8208 Not Collective 8209 8210 Input Parameter: 8211 . dm - The DM 8212 8213 Output Parameters: 8214 + nranks - the number of neighbours 8215 - ranks - the neighbors ranks 8216 8217 Notes: 8218 Do not free the array, it is freed when the DM is destroyed. 8219 8220 Level: beginner 8221 8222 .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks() 8223 @*/ 8224 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 8225 { 8226 PetscErrorCode ierr; 8227 8228 PetscFunctionBegin; 8229 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8230 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 8231 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 8232 PetscFunctionReturn(0); 8233 } 8234 8235 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 8236 8237 /* 8238 Converts the input vector to a ghosted vector and then calls the standard coloring code. 8239 This has be a different function because it requires DM which is not defined in the Mat library 8240 */ 8241 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 8242 { 8243 PetscErrorCode ierr; 8244 8245 PetscFunctionBegin; 8246 if (coloring->ctype == IS_COLORING_LOCAL) { 8247 Vec x1local; 8248 DM dm; 8249 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 8250 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 8251 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 8252 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 8253 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 8254 x1 = x1local; 8255 } 8256 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 8257 if (coloring->ctype == IS_COLORING_LOCAL) { 8258 DM dm; 8259 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 8260 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 8261 } 8262 PetscFunctionReturn(0); 8263 } 8264 8265 /*@ 8266 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 8267 8268 Input Parameter: 8269 . coloring - the MatFDColoring object 8270 8271 Developer Notes: 8272 this routine exists because the PETSc Mat library does not know about the DM objects 8273 8274 Level: advanced 8275 8276 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 8277 @*/ 8278 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 8279 { 8280 PetscFunctionBegin; 8281 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 8282 PetscFunctionReturn(0); 8283 } 8284 8285 /*@ 8286 DMGetCompatibility - determine if two DMs are compatible 8287 8288 Collective 8289 8290 Input Parameters: 8291 + dm1 - the first DM 8292 - dm2 - the second DM 8293 8294 Output Parameters: 8295 + compatible - whether or not the two DMs are compatible 8296 - set - whether or not the compatible value was set 8297 8298 Notes: 8299 Two DMs are deemed compatible if they represent the same parallel decomposition 8300 of the same topology. This implies that the section (field data) on one 8301 "makes sense" with respect to the topology and parallel decomposition of the other. 8302 Loosely speaking, compatible DMs represent the same domain and parallel 8303 decomposition, but hold different data. 8304 8305 Typically, one would confirm compatibility if intending to simultaneously iterate 8306 over a pair of vectors obtained from different DMs. 8307 8308 For example, two DMDA objects are compatible if they have the same local 8309 and global sizes and the same stencil width. They can have different numbers 8310 of degrees of freedom per node. Thus, one could use the node numbering from 8311 either DM in bounds for a loop over vectors derived from either DM. 8312 8313 Consider the operation of summing data living on a 2-dof DMDA to data living 8314 on a 1-dof DMDA, which should be compatible, as in the following snippet. 8315 .vb 8316 ... 8317 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 8318 if (set && compatible) { 8319 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 8320 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 8321 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 8322 for (j=y; j<y+n; ++j) { 8323 for (i=x; i<x+m, ++i) { 8324 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 8325 } 8326 } 8327 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 8328 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 8329 } else { 8330 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 8331 } 8332 ... 8333 .ve 8334 8335 Checking compatibility might be expensive for a given implementation of DM, 8336 or might be impossible to unambiguously confirm or deny. For this reason, 8337 this function may decline to determine compatibility, and hence users should 8338 always check the "set" output parameter. 8339 8340 A DM is always compatible with itself. 8341 8342 In the current implementation, DMs which live on "unequal" communicators 8343 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 8344 incompatible. 8345 8346 This function is labeled "Collective," as information about all subdomains 8347 is required on each rank. However, in DM implementations which store all this 8348 information locally, this function may be merely "Logically Collective". 8349 8350 Developer Notes: 8351 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 8352 iff B is compatible with A. Thus, this function checks the implementations 8353 of both dm and dmc (if they are of different types), attempting to determine 8354 compatibility. It is left to DM implementers to ensure that symmetry is 8355 preserved. The simplest way to do this is, when implementing type-specific 8356 logic for this function, is to check for existing logic in the implementation 8357 of other DM types and let *set = PETSC_FALSE if found. 8358 8359 Level: advanced 8360 8361 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 8362 @*/ 8363 8364 PetscErrorCode DMGetCompatibility(DM dm1,DM dm2,PetscBool *compatible,PetscBool *set) 8365 { 8366 PetscErrorCode ierr; 8367 PetscMPIInt compareResult; 8368 DMType type,type2; 8369 PetscBool sameType; 8370 8371 PetscFunctionBegin; 8372 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 8373 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 8374 8375 /* Declare a DM compatible with itself */ 8376 if (dm1 == dm2) { 8377 *set = PETSC_TRUE; 8378 *compatible = PETSC_TRUE; 8379 PetscFunctionReturn(0); 8380 } 8381 8382 /* Declare a DM incompatible with a DM that lives on an "unequal" 8383 communicator. Note that this does not preclude compatibility with 8384 DMs living on "congruent" or "similar" communicators, but this must be 8385 determined by the implementation-specific logic */ 8386 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm1),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr); 8387 if (compareResult == MPI_UNEQUAL) { 8388 *set = PETSC_TRUE; 8389 *compatible = PETSC_FALSE; 8390 PetscFunctionReturn(0); 8391 } 8392 8393 /* Pass to the implementation-specific routine, if one exists. */ 8394 if (dm1->ops->getcompatibility) { 8395 ierr = (*dm1->ops->getcompatibility)(dm1,dm2,compatible,set);CHKERRQ(ierr); 8396 if (*set) PetscFunctionReturn(0); 8397 } 8398 8399 /* If dm1 and dm2 are of different types, then attempt to check compatibility 8400 with an implementation of this function from dm2 */ 8401 ierr = DMGetType(dm1,&type);CHKERRQ(ierr); 8402 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 8403 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 8404 if (!sameType && dm2->ops->getcompatibility) { 8405 ierr = (*dm2->ops->getcompatibility)(dm2,dm1,compatible,set);CHKERRQ(ierr); /* Note argument order */ 8406 } else { 8407 *set = PETSC_FALSE; 8408 } 8409 PetscFunctionReturn(0); 8410 } 8411 8412 /*@C 8413 DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance. 8414 8415 Logically Collective on DM 8416 8417 Input Parameters: 8418 + DM - the DM 8419 . f - the monitor function 8420 . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired) 8421 - monitordestroy - [optional] routine that frees monitor context (may be NULL) 8422 8423 Options Database Keys: 8424 - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but 8425 does not cancel those set via the options database. 8426 8427 Notes: 8428 Several different monitoring routines may be set by calling 8429 DMMonitorSet() multiple times; all will be called in the 8430 order in which they were set. 8431 8432 Fortran Notes: 8433 Only a single monitor function can be set for each DM object 8434 8435 Level: intermediate 8436 8437 .seealso: DMMonitorCancel() 8438 @*/ 8439 PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**)) 8440 { 8441 PetscInt m; 8442 PetscErrorCode ierr; 8443 8444 PetscFunctionBegin; 8445 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8446 for (m = 0; m < dm->numbermonitors; ++m) { 8447 PetscBool identical; 8448 8449 ierr = PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);CHKERRQ(ierr); 8450 if (identical) PetscFunctionReturn(0); 8451 } 8452 if (dm->numbermonitors >= MAXDMMONITORS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 8453 dm->monitor[dm->numbermonitors] = f; 8454 dm->monitordestroy[dm->numbermonitors] = monitordestroy; 8455 dm->monitorcontext[dm->numbermonitors++] = (void *) mctx; 8456 PetscFunctionReturn(0); 8457 } 8458 8459 /*@ 8460 DMMonitorCancel - Clears all the monitor functions for a DM object. 8461 8462 Logically Collective on DM 8463 8464 Input Parameter: 8465 . dm - the DM 8466 8467 Options Database Key: 8468 . -dm_monitor_cancel - cancels all monitors that have been hardwired 8469 into a code by calls to DMonitorSet(), but does not cancel those 8470 set via the options database 8471 8472 Notes: 8473 There is no way to clear one specific monitor from a DM object. 8474 8475 Level: intermediate 8476 8477 .seealso: DMMonitorSet() 8478 @*/ 8479 PetscErrorCode DMMonitorCancel(DM dm) 8480 { 8481 PetscErrorCode ierr; 8482 PetscInt m; 8483 8484 PetscFunctionBegin; 8485 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8486 for (m = 0; m < dm->numbermonitors; ++m) { 8487 if (dm->monitordestroy[m]) {ierr = (*dm->monitordestroy[m])(&dm->monitorcontext[m]);CHKERRQ(ierr);} 8488 } 8489 dm->numbermonitors = 0; 8490 PetscFunctionReturn(0); 8491 } 8492 8493 /*@C 8494 DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 8495 8496 Collective on DM 8497 8498 Input Parameters: 8499 + dm - DM object you wish to monitor 8500 . name - the monitor type one is seeking 8501 . help - message indicating what monitoring is done 8502 . manual - manual page for the monitor 8503 . monitor - the monitor function 8504 - 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 8505 8506 Output Parameter: 8507 . flg - Flag set if the monitor was created 8508 8509 Level: developer 8510 8511 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 8512 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 8513 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 8514 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 8515 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 8516 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 8517 PetscOptionsFList(), PetscOptionsEList() 8518 @*/ 8519 PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg) 8520 { 8521 PetscViewer viewer; 8522 PetscViewerFormat format; 8523 PetscErrorCode ierr; 8524 8525 PetscFunctionBegin; 8526 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8527 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);CHKERRQ(ierr); 8528 if (*flg) { 8529 PetscViewerAndFormat *vf; 8530 8531 ierr = PetscViewerAndFormatCreate(viewer, format, &vf);CHKERRQ(ierr); 8532 ierr = PetscObjectDereference((PetscObject) viewer);CHKERRQ(ierr); 8533 if (monitorsetup) {ierr = (*monitorsetup)(dm, vf);CHKERRQ(ierr);} 8534 ierr = DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr); 8535 } 8536 PetscFunctionReturn(0); 8537 } 8538 8539 /*@ 8540 DMMonitor - runs the user provided monitor routines, if they exist 8541 8542 Collective on DM 8543 8544 Input Parameters: 8545 . dm - The DM 8546 8547 Level: developer 8548 8549 .seealso: DMMonitorSet() 8550 @*/ 8551 PetscErrorCode DMMonitor(DM dm) 8552 { 8553 PetscInt m; 8554 PetscErrorCode ierr; 8555 8556 PetscFunctionBegin; 8557 if (!dm) PetscFunctionReturn(0); 8558 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8559 for (m = 0; m < dm->numbermonitors; ++m) { 8560 ierr = (*dm->monitor[m])(dm, dm->monitorcontext[m]);CHKERRQ(ierr); 8561 } 8562 PetscFunctionReturn(0); 8563 } 8564