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