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