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