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