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