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