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