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 or NULL to ensure a coordinate discretization exists 6830 6831 Level: intermediate 6832 6833 .seealso: DMGetCoordinateField() 6834 @*/ 6835 PetscErrorCode DMProjectCoordinates(DM dm, PetscFE disc) 6836 { 6837 PetscFE discOld; 6838 PetscClassId classid; 6839 DM cdmOld,cdmNew; 6840 Vec coordsOld,coordsNew; 6841 Mat matInterp; 6842 PetscBool same_space = PETSC_TRUE; 6843 PetscErrorCode ierr; 6844 6845 PetscFunctionBegin; 6846 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6847 if (disc) PetscValidHeaderSpecific(disc,PETSCFE_CLASSID,2); 6848 6849 ierr = DMGetCoordinateDM(dm, &cdmOld);CHKERRQ(ierr); 6850 /* Check current discretization is compatible */ 6851 ierr = DMGetField(cdmOld, 0, NULL, (PetscObject*)&discOld);CHKERRQ(ierr); 6852 ierr = PetscObjectGetClassId((PetscObject)discOld, &classid);CHKERRQ(ierr); 6853 if (classid != PETSCFE_CLASSID) { 6854 if (classid == PETSC_CONTAINER_CLASSID) { 6855 PetscFE feLinear; 6856 DMPolytopeType ct; 6857 PetscInt dim, dE, cStart; 6858 PetscBool simplex; 6859 6860 /* Assume linear vertex coordinates */ 6861 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6862 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 6863 ierr = DMPlexGetHeightStratum(cdmOld, 0, &cStart, NULL);CHKERRQ(ierr); 6864 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 6865 switch (ct) { 6866 case DM_POLYTOPE_TRI_PRISM: 6867 case DM_POLYTOPE_TRI_PRISM_TENSOR: 6868 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot autoamtically create coordinate space for prisms"); 6869 default: break; 6870 } 6871 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 6872 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, 1, -1, &feLinear);CHKERRQ(ierr); 6873 ierr = DMSetField(cdmOld, 0, NULL, (PetscObject) feLinear);CHKERRQ(ierr); 6874 ierr = PetscFEDestroy(&feLinear);CHKERRQ(ierr); 6875 ierr = DMCreateDS(cdmOld);CHKERRQ(ierr); 6876 ierr = DMGetField(cdmOld, 0, NULL, (PetscObject*)&discOld);CHKERRQ(ierr); 6877 } else { 6878 const char *discname; 6879 6880 ierr = PetscObjectGetType((PetscObject)discOld, &discname);CHKERRQ(ierr); 6881 SETERRQ(PetscObjectComm((PetscObject)discOld), PETSC_ERR_SUP, "Discretization type %s not supported", discname); 6882 } 6883 } 6884 if (!disc) PetscFunctionReturn(0); 6885 { // Check if the new space is the same as the old modulo quadrature 6886 PetscDualSpace dsOld, ds; 6887 ierr = PetscFEGetDualSpace(discOld, &dsOld);CHKERRQ(ierr); 6888 ierr = PetscFEGetDualSpace(disc, &ds);CHKERRQ(ierr); 6889 ierr = PetscDualSpaceEqual(dsOld, ds, &same_space);CHKERRQ(ierr); 6890 } 6891 /* Make a fresh clone of the coordinate DM */ 6892 ierr = DMClone(cdmOld, &cdmNew);CHKERRQ(ierr); 6893 ierr = DMSetField(cdmNew, 0, NULL, (PetscObject) disc);CHKERRQ(ierr); 6894 ierr = DMCreateDS(cdmNew);CHKERRQ(ierr); 6895 ierr = DMGetCoordinates(dm, &coordsOld);CHKERRQ(ierr); 6896 if (same_space) { 6897 ierr = PetscObjectReference((PetscObject)coordsOld);CHKERRQ(ierr); 6898 coordsNew = coordsOld; 6899 } else { // Project the coordinate vector from old to new space 6900 ierr = DMCreateGlobalVector(cdmNew, &coordsNew);CHKERRQ(ierr); 6901 ierr = DMCreateInterpolation(cdmOld, cdmNew, &matInterp, NULL);CHKERRQ(ierr); 6902 ierr = MatInterpolate(matInterp, coordsOld, coordsNew);CHKERRQ(ierr); 6903 ierr = MatDestroy(&matInterp);CHKERRQ(ierr); 6904 } 6905 /* Set new coordinate structures */ 6906 ierr = DMSetCoordinateField(dm, NULL);CHKERRQ(ierr); 6907 ierr = DMSetCoordinateDM(dm, cdmNew);CHKERRQ(ierr); 6908 ierr = DMSetCoordinates(dm, coordsNew);CHKERRQ(ierr); 6909 ierr = VecDestroy(&coordsNew);CHKERRQ(ierr); 6910 ierr = DMDestroy(&cdmNew);CHKERRQ(ierr); 6911 PetscFunctionReturn(0); 6912 } 6913 6914 /*@C 6915 DMGetPeriodicity - Get the description of mesh periodicity 6916 6917 Input Parameter: 6918 . dm - The DM object 6919 6920 Output Parameters: 6921 + per - Whether the DM is periodic or not 6922 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 6923 . L - If we assume the mesh is a torus, this is the length of each coordinate 6924 - bd - This describes the type of periodicity in each topological dimension 6925 6926 Level: developer 6927 6928 .seealso: DMGetPeriodicity() 6929 @*/ 6930 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 6931 { 6932 PetscFunctionBegin; 6933 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6934 if (per) *per = dm->periodic; 6935 if (L) *L = dm->L; 6936 if (maxCell) *maxCell = dm->maxCell; 6937 if (bd) *bd = dm->bdtype; 6938 PetscFunctionReturn(0); 6939 } 6940 6941 /*@C 6942 DMSetPeriodicity - Set the description of mesh periodicity 6943 6944 Input Parameters: 6945 + dm - The DM object 6946 . per - Whether the DM is periodic or not. 6947 . 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. 6948 . L - If we assume the mesh is a torus, this is the length of each coordinate 6949 - bd - This describes the type of periodicity in each topological dimension 6950 6951 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. 6952 6953 Level: developer 6954 6955 .seealso: DMGetPeriodicity() 6956 @*/ 6957 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 6958 { 6959 PetscInt dim, d; 6960 PetscErrorCode ierr; 6961 6962 PetscFunctionBegin; 6963 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6964 PetscValidLogicalCollectiveBool(dm,per,2); 6965 if (maxCell) {PetscValidRealPointer(maxCell,3);} 6966 if (L) {PetscValidRealPointer(L,4);} 6967 if (bd) {PetscValidPointer(bd,5);} 6968 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6969 if (maxCell) { 6970 if (!dm->maxCell) {ierr = PetscMalloc1(dim, &dm->maxCell);CHKERRQ(ierr);} 6971 for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d]; 6972 } else { /* remove maxCell information to disable automatic computation of localized vertices */ 6973 ierr = PetscFree(dm->maxCell);CHKERRQ(ierr); 6974 } 6975 6976 if (L) { 6977 if (!dm->L) {ierr = PetscMalloc1(dim, &dm->L);CHKERRQ(ierr);} 6978 for (d = 0; d < dim; ++d) dm->L[d] = L[d]; 6979 } 6980 if (bd) { 6981 if (!dm->bdtype) {ierr = PetscMalloc1(dim, &dm->bdtype);CHKERRQ(ierr);} 6982 for (d = 0; d < dim; ++d) dm->bdtype[d] = bd[d]; 6983 } 6984 dm->periodic = per; 6985 PetscFunctionReturn(0); 6986 } 6987 6988 /*@ 6989 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. 6990 6991 Input Parameters: 6992 + dm - The DM 6993 . in - The input coordinate point (dim numbers) 6994 - endpoint - Include the endpoint L_i 6995 6996 Output Parameter: 6997 . out - The localized coordinate point 6998 6999 Level: developer 7000 7001 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 7002 @*/ 7003 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 7004 { 7005 PetscInt dim, d; 7006 PetscErrorCode ierr; 7007 7008 PetscFunctionBegin; 7009 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 7010 if (!dm->maxCell) { 7011 for (d = 0; d < dim; ++d) out[d] = in[d]; 7012 } else { 7013 if (endpoint) { 7014 for (d = 0; d < dim; ++d) { 7015 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)) { 7016 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 7017 } else { 7018 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 7019 } 7020 } 7021 } else { 7022 for (d = 0; d < dim; ++d) { 7023 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 7024 } 7025 } 7026 } 7027 PetscFunctionReturn(0); 7028 } 7029 7030 /* 7031 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. 7032 7033 Input Parameters: 7034 + dm - The DM 7035 . dim - The spatial dimension 7036 . anchor - The anchor point, the input point can be no more than maxCell away from it 7037 - in - The input coordinate point (dim numbers) 7038 7039 Output Parameter: 7040 . out - The localized coordinate point 7041 7042 Level: developer 7043 7044 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 7045 7046 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 7047 */ 7048 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 7049 { 7050 PetscInt d; 7051 7052 PetscFunctionBegin; 7053 if (!dm->maxCell) { 7054 for (d = 0; d < dim; ++d) out[d] = in[d]; 7055 } else { 7056 for (d = 0; d < dim; ++d) { 7057 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 7058 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 7059 } else { 7060 out[d] = in[d]; 7061 } 7062 } 7063 } 7064 PetscFunctionReturn(0); 7065 } 7066 7067 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 7068 { 7069 PetscInt d; 7070 7071 PetscFunctionBegin; 7072 if (!dm->maxCell) { 7073 for (d = 0; d < dim; ++d) out[d] = in[d]; 7074 } else { 7075 for (d = 0; d < dim; ++d) { 7076 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 7077 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 7078 } else { 7079 out[d] = in[d]; 7080 } 7081 } 7082 } 7083 PetscFunctionReturn(0); 7084 } 7085 7086 /* 7087 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. 7088 7089 Input Parameters: 7090 + dm - The DM 7091 . dim - The spatial dimension 7092 . anchor - The anchor point, the input point can be no more than maxCell away from it 7093 . in - The input coordinate delta (dim numbers) 7094 - out - The input coordinate point (dim numbers) 7095 7096 Output Parameter: 7097 . out - The localized coordinate in + out 7098 7099 Level: developer 7100 7101 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 7102 7103 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 7104 */ 7105 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 7106 { 7107 PetscInt d; 7108 7109 PetscFunctionBegin; 7110 if (!dm->maxCell) { 7111 for (d = 0; d < dim; ++d) out[d] += in[d]; 7112 } else { 7113 for (d = 0; d < dim; ++d) { 7114 const PetscReal maxC = dm->maxCell[d]; 7115 7116 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) { 7117 const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 7118 7119 if (PetscAbsScalar(newCoord - anchor[d]) > maxC) 7120 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])); 7121 out[d] += newCoord; 7122 } else { 7123 out[d] += in[d]; 7124 } 7125 } 7126 } 7127 PetscFunctionReturn(0); 7128 } 7129 7130 /*@ 7131 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 7132 7133 Not collective 7134 7135 Input Parameter: 7136 . dm - The DM 7137 7138 Output Parameter: 7139 areLocalized - True if localized 7140 7141 Level: developer 7142 7143 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 7144 @*/ 7145 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 7146 { 7147 DM cdm; 7148 PetscSection coordSection; 7149 PetscInt depth, cStart, cEnd, sStart, sEnd, c, dof; 7150 PetscBool isPlex, alreadyLocalized; 7151 PetscErrorCode ierr; 7152 7153 PetscFunctionBegin; 7154 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7155 PetscValidBoolPointer(areLocalized, 2); 7156 *areLocalized = PETSC_FALSE; 7157 7158 /* We need some generic way of refering to cells/vertices */ 7159 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7160 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 7161 if (!isPlex) PetscFunctionReturn(0); 7162 ierr = DMPlexGetDepth(cdm, &depth);CHKERRQ(ierr); 7163 if (!depth) PetscFunctionReturn(0); 7164 7165 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7166 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7167 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 7168 alreadyLocalized = PETSC_FALSE; 7169 for (c = cStart; c < cEnd; ++c) { 7170 if (c < sStart || c >= sEnd) continue; 7171 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 7172 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 7173 } 7174 *areLocalized = alreadyLocalized; 7175 PetscFunctionReturn(0); 7176 } 7177 7178 /*@ 7179 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 7180 7181 Collective on dm 7182 7183 Input Parameter: 7184 . dm - The DM 7185 7186 Output Parameter: 7187 areLocalized - True if localized 7188 7189 Level: developer 7190 7191 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 7192 @*/ 7193 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 7194 { 7195 PetscBool localized; 7196 PetscErrorCode ierr; 7197 7198 PetscFunctionBegin; 7199 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7200 PetscValidBoolPointer(areLocalized, 2); 7201 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 7202 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 7203 PetscFunctionReturn(0); 7204 } 7205 7206 /*@ 7207 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 7208 7209 Collective on dm 7210 7211 Input Parameter: 7212 . dm - The DM 7213 7214 Level: developer 7215 7216 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 7217 @*/ 7218 PetscErrorCode DMLocalizeCoordinates(DM dm) 7219 { 7220 DM cdm; 7221 PetscSection coordSection, cSection; 7222 Vec coordinates, cVec; 7223 PetscScalar *coords, *coords2, *anchor, *localized; 7224 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 7225 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 7226 PetscInt maxHeight = 0, h; 7227 PetscInt *pStart = NULL, *pEnd = NULL; 7228 PetscErrorCode ierr; 7229 7230 PetscFunctionBegin; 7231 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7232 if (!dm->periodic) PetscFunctionReturn(0); 7233 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 7234 if (alreadyLocalized) PetscFunctionReturn(0); 7235 7236 /* We need some generic way of refering to cells/vertices */ 7237 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7238 { 7239 PetscBool isplex; 7240 7241 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 7242 if (isplex) { 7243 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 7244 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 7245 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7246 pEnd = &pStart[maxHeight + 1]; 7247 newStart = vStart; 7248 newEnd = vEnd; 7249 for (h = 0; h <= maxHeight; h++) { 7250 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 7251 newStart = PetscMin(newStart,pStart[h]); 7252 newEnd = PetscMax(newEnd,pEnd[h]); 7253 } 7254 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 7255 } 7256 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 7257 PetscCheckFalse(!coordinates,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 7258 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7259 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 7260 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 7261 7262 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 7263 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 7264 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 7265 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 7266 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 7267 7268 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7269 localized = &anchor[bs]; 7270 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 7271 for (h = 0; h <= maxHeight; h++) { 7272 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 7273 7274 for (c = cStart; c < cEnd; ++c) { 7275 PetscScalar *cellCoords = NULL; 7276 PetscInt b; 7277 7278 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 7279 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7280 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 7281 for (d = 0; d < dof/bs; ++d) { 7282 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 7283 for (b = 0; b < bs; b++) { 7284 if (cellCoords[d*bs + b] != localized[b]) break; 7285 } 7286 if (b < bs) break; 7287 } 7288 if (d < dof/bs) { 7289 if (c >= sStart && c < sEnd) { 7290 PetscInt cdof; 7291 7292 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 7293 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 7294 } 7295 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 7296 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 7297 } 7298 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7299 } 7300 } 7301 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 7302 if (alreadyLocalizedGlobal) { 7303 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7304 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 7305 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7306 PetscFunctionReturn(0); 7307 } 7308 for (v = vStart; v < vEnd; ++v) { 7309 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 7310 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 7311 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 7312 } 7313 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 7314 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 7315 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 7316 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 7317 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 7318 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 7319 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 7320 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 7321 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 7322 for (v = vStart; v < vEnd; ++v) { 7323 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 7324 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 7325 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 7326 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 7327 } 7328 for (h = 0; h <= maxHeight; h++) { 7329 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 7330 7331 for (c = cStart; c < cEnd; ++c) { 7332 PetscScalar *cellCoords = NULL; 7333 PetscInt b, cdof; 7334 7335 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 7336 if (!cdof) continue; 7337 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7338 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 7339 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 7340 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 7341 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7342 } 7343 } 7344 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7345 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7346 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 7347 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 7348 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 7349 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 7350 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 7351 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 7352 PetscFunctionReturn(0); 7353 } 7354 7355 /*@ 7356 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 7357 7358 Collective on v (see explanation below) 7359 7360 Input Parameters: 7361 + dm - The DM 7362 - ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 7363 7364 Input/Output Parameters: 7365 + v - The Vec of points, on output contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 7366 - cellSF - Points to either NULL, or a PetscSF with guesses for which cells contain each point; 7367 on output, the PetscSF containing the ranks and local indices of the containing points 7368 7369 Level: developer 7370 7371 Notes: 7372 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 7373 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 7374 7375 If *cellSF is NULL on input, a PetscSF will be created. 7376 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 7377 7378 An array that maps each point to its containing cell can be obtained with 7379 7380 $ const PetscSFNode *cells; 7381 $ PetscInt nFound; 7382 $ const PetscInt *found; 7383 $ 7384 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 7385 7386 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 7387 the index of the cell in its rank's local numbering. 7388 7389 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 7390 @*/ 7391 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 7392 { 7393 PetscErrorCode ierr; 7394 7395 PetscFunctionBegin; 7396 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7397 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 7398 PetscValidPointer(cellSF,4); 7399 if (*cellSF) { 7400 PetscMPIInt result; 7401 7402 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 7403 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRMPI(ierr); 7404 PetscCheckFalse(result != MPI_IDENT && result != MPI_CONGRUENT,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 7405 } else { 7406 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 7407 } 7408 PetscCheckFalse(!dm->ops->locatepoints,PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 7409 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 7410 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 7411 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 7412 PetscFunctionReturn(0); 7413 } 7414 7415 /*@ 7416 DMGetOutputDM - Retrieve the DM associated with the layout for output 7417 7418 Collective on dm 7419 7420 Input Parameter: 7421 . dm - The original DM 7422 7423 Output Parameter: 7424 . odm - The DM which provides the layout for output 7425 7426 Level: intermediate 7427 7428 .seealso: VecView(), DMGetGlobalSection() 7429 @*/ 7430 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 7431 { 7432 PetscSection section; 7433 PetscBool hasConstraints, ghasConstraints; 7434 PetscErrorCode ierr; 7435 7436 PetscFunctionBegin; 7437 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7438 PetscValidPointer(odm,2); 7439 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 7440 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 7441 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 7442 if (!ghasConstraints) { 7443 *odm = dm; 7444 PetscFunctionReturn(0); 7445 } 7446 if (!dm->dmBC) { 7447 PetscSection newSection, gsection; 7448 PetscSF sf; 7449 7450 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 7451 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 7452 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 7453 ierr = DMSetLocalSection(dm->dmBC, newSection);CHKERRQ(ierr); 7454 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 7455 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 7456 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 7457 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 7458 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 7459 } 7460 *odm = dm->dmBC; 7461 PetscFunctionReturn(0); 7462 } 7463 7464 /*@ 7465 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 7466 7467 Input Parameter: 7468 . dm - The original DM 7469 7470 Output Parameters: 7471 + num - The output sequence number 7472 - val - The output sequence value 7473 7474 Level: intermediate 7475 7476 Note: This is intended for output that should appear in sequence, for instance 7477 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7478 7479 .seealso: VecView() 7480 @*/ 7481 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 7482 { 7483 PetscFunctionBegin; 7484 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7485 if (num) {PetscValidIntPointer(num,2); *num = dm->outputSequenceNum;} 7486 if (val) {PetscValidRealPointer(val,3);*val = dm->outputSequenceVal;} 7487 PetscFunctionReturn(0); 7488 } 7489 7490 /*@ 7491 DMSetOutputSequenceNumber - Set the sequence number/value for output 7492 7493 Input Parameters: 7494 + dm - The original DM 7495 . num - The output sequence number 7496 - val - The output sequence value 7497 7498 Level: intermediate 7499 7500 Note: This is intended for output that should appear in sequence, for instance 7501 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7502 7503 .seealso: VecView() 7504 @*/ 7505 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 7506 { 7507 PetscFunctionBegin; 7508 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7509 dm->outputSequenceNum = num; 7510 dm->outputSequenceVal = val; 7511 PetscFunctionReturn(0); 7512 } 7513 7514 /*@C 7515 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 7516 7517 Input Parameters: 7518 + dm - The original DM 7519 . name - The sequence name 7520 - num - The output sequence number 7521 7522 Output Parameter: 7523 . val - The output sequence value 7524 7525 Level: intermediate 7526 7527 Note: This is intended for output that should appear in sequence, for instance 7528 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7529 7530 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 7531 @*/ 7532 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 7533 { 7534 PetscBool ishdf5; 7535 PetscErrorCode ierr; 7536 7537 PetscFunctionBegin; 7538 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7539 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 7540 PetscValidRealPointer(val,5); 7541 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 7542 if (ishdf5) { 7543 #if defined(PETSC_HAVE_HDF5) 7544 PetscScalar value; 7545 7546 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 7547 *val = PetscRealPart(value); 7548 #endif 7549 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 7550 PetscFunctionReturn(0); 7551 } 7552 7553 /*@ 7554 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 7555 7556 Not collective 7557 7558 Input Parameter: 7559 . dm - The DM 7560 7561 Output Parameter: 7562 . useNatural - The flag to build the mapping to a natural order during distribution 7563 7564 Level: beginner 7565 7566 .seealso: DMSetUseNatural(), DMCreate() 7567 @*/ 7568 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 7569 { 7570 PetscFunctionBegin; 7571 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7572 PetscValidBoolPointer(useNatural, 2); 7573 *useNatural = dm->useNatural; 7574 PetscFunctionReturn(0); 7575 } 7576 7577 /*@ 7578 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 7579 7580 Collective on dm 7581 7582 Input Parameters: 7583 + dm - The DM 7584 - useNatural - The flag to build the mapping to a natural order during distribution 7585 7586 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 7587 7588 Level: beginner 7589 7590 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 7591 @*/ 7592 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 7593 { 7594 PetscFunctionBegin; 7595 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7596 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 7597 dm->useNatural = useNatural; 7598 PetscFunctionReturn(0); 7599 } 7600 7601 /*@C 7602 DMCreateLabel - Create a label of the given name if it does not already exist 7603 7604 Not Collective 7605 7606 Input Parameters: 7607 + dm - The DM object 7608 - name - The label name 7609 7610 Level: intermediate 7611 7612 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7613 @*/ 7614 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 7615 { 7616 PetscBool flg; 7617 DMLabel label; 7618 PetscErrorCode ierr; 7619 7620 PetscFunctionBegin; 7621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7622 PetscValidCharPointer(name, 2); 7623 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 7624 if (!flg) { 7625 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 7626 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 7627 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 7628 } 7629 PetscFunctionReturn(0); 7630 } 7631 7632 /*@C 7633 DMCreateLabelAtIndex - Create a label of the given name at the iven index. If it already exists, move it to this index. 7634 7635 Not Collective 7636 7637 Input Parameters: 7638 + dm - The DM object 7639 . l - The index for the label 7640 - name - The label name 7641 7642 Level: intermediate 7643 7644 .seealso: DMCreateLabel(), DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7645 @*/ 7646 PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[]) 7647 { 7648 DMLabelLink orig, prev = NULL; 7649 DMLabel label; 7650 PetscInt Nl, m; 7651 PetscBool flg, match; 7652 const char *lname; 7653 PetscErrorCode ierr; 7654 7655 PetscFunctionBegin; 7656 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7657 PetscValidCharPointer(name, 3); 7658 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 7659 if (!flg) { 7660 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 7661 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 7662 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 7663 } 7664 ierr = DMGetNumLabels(dm, &Nl);CHKERRQ(ierr); 7665 PetscCheckFalse(l >= Nl,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %D must be in [0, %D)", l, Nl); 7666 for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) { 7667 ierr = PetscObjectGetName((PetscObject) orig->label, &lname);CHKERRQ(ierr); 7668 ierr = PetscStrcmp(name, lname, &match);CHKERRQ(ierr); 7669 if (match) break; 7670 } 7671 if (m == l) PetscFunctionReturn(0); 7672 if (!m) dm->labels = orig->next; 7673 else prev->next = orig->next; 7674 if (!l) { 7675 orig->next = dm->labels; 7676 dm->labels = orig; 7677 } else { 7678 for (m = 0, prev = dm->labels; m < l-1; ++m, prev = prev->next); 7679 orig->next = prev->next; 7680 prev->next = orig; 7681 } 7682 PetscFunctionReturn(0); 7683 } 7684 7685 /*@C 7686 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 7687 7688 Not Collective 7689 7690 Input Parameters: 7691 + dm - The DM object 7692 . name - The label name 7693 - point - The mesh point 7694 7695 Output Parameter: 7696 . value - The label value for this point, or -1 if the point is not in the label 7697 7698 Level: beginner 7699 7700 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 7701 @*/ 7702 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 7703 { 7704 DMLabel label; 7705 PetscErrorCode ierr; 7706 7707 PetscFunctionBegin; 7708 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7709 PetscValidCharPointer(name, 2); 7710 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7711 PetscCheckFalse(!label,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 7712 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 7713 PetscFunctionReturn(0); 7714 } 7715 7716 /*@C 7717 DMSetLabelValue - Add a point to a Sieve Label with given value 7718 7719 Not Collective 7720 7721 Input Parameters: 7722 + dm - The DM object 7723 . name - The label name 7724 . point - The mesh point 7725 - value - The label value for this point 7726 7727 Output Parameter: 7728 7729 Level: beginner 7730 7731 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 7732 @*/ 7733 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7734 { 7735 DMLabel label; 7736 PetscErrorCode ierr; 7737 7738 PetscFunctionBegin; 7739 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7740 PetscValidCharPointer(name, 2); 7741 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7742 if (!label) { 7743 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 7744 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7745 } 7746 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 7747 PetscFunctionReturn(0); 7748 } 7749 7750 /*@C 7751 DMClearLabelValue - Remove a point from a Sieve Label with given value 7752 7753 Not Collective 7754 7755 Input Parameters: 7756 + dm - The DM object 7757 . name - The label name 7758 . point - The mesh point 7759 - value - The label value for this point 7760 7761 Output Parameter: 7762 7763 Level: beginner 7764 7765 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 7766 @*/ 7767 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7768 { 7769 DMLabel label; 7770 PetscErrorCode ierr; 7771 7772 PetscFunctionBegin; 7773 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7774 PetscValidCharPointer(name, 2); 7775 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7776 if (!label) PetscFunctionReturn(0); 7777 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 7778 PetscFunctionReturn(0); 7779 } 7780 7781 /*@C 7782 DMGetLabelSize - Get the number of different integer ids in a Label 7783 7784 Not Collective 7785 7786 Input Parameters: 7787 + dm - The DM object 7788 - name - The label name 7789 7790 Output Parameter: 7791 . size - The number of different integer ids, or 0 if the label does not exist 7792 7793 Level: beginner 7794 7795 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 7796 @*/ 7797 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 7798 { 7799 DMLabel label; 7800 PetscErrorCode ierr; 7801 7802 PetscFunctionBegin; 7803 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7804 PetscValidCharPointer(name, 2); 7805 PetscValidIntPointer(size, 3); 7806 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7807 *size = 0; 7808 if (!label) PetscFunctionReturn(0); 7809 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 7810 PetscFunctionReturn(0); 7811 } 7812 7813 /*@C 7814 DMGetLabelIdIS - Get the integer ids in a label 7815 7816 Not Collective 7817 7818 Input Parameters: 7819 + mesh - The DM object 7820 - name - The label name 7821 7822 Output Parameter: 7823 . ids - The integer ids, or NULL if the label does not exist 7824 7825 Level: beginner 7826 7827 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 7828 @*/ 7829 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 7830 { 7831 DMLabel label; 7832 PetscErrorCode ierr; 7833 7834 PetscFunctionBegin; 7835 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7836 PetscValidCharPointer(name, 2); 7837 PetscValidPointer(ids, 3); 7838 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7839 *ids = NULL; 7840 if (label) { 7841 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 7842 } else { 7843 /* returning an empty IS */ 7844 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 7845 } 7846 PetscFunctionReturn(0); 7847 } 7848 7849 /*@C 7850 DMGetStratumSize - Get the number of points in a label stratum 7851 7852 Not Collective 7853 7854 Input Parameters: 7855 + dm - The DM object 7856 . name - The label name 7857 - value - The stratum value 7858 7859 Output Parameter: 7860 . size - The stratum size 7861 7862 Level: beginner 7863 7864 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 7865 @*/ 7866 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 7867 { 7868 DMLabel label; 7869 PetscErrorCode ierr; 7870 7871 PetscFunctionBegin; 7872 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7873 PetscValidCharPointer(name, 2); 7874 PetscValidIntPointer(size, 4); 7875 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7876 *size = 0; 7877 if (!label) PetscFunctionReturn(0); 7878 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 7879 PetscFunctionReturn(0); 7880 } 7881 7882 /*@C 7883 DMGetStratumIS - Get the points in a label stratum 7884 7885 Not Collective 7886 7887 Input Parameters: 7888 + dm - The DM object 7889 . name - The label name 7890 - value - The stratum value 7891 7892 Output Parameter: 7893 . points - The stratum points, or NULL if the label does not exist or does not have that value 7894 7895 Level: beginner 7896 7897 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 7898 @*/ 7899 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 7900 { 7901 DMLabel label; 7902 PetscErrorCode ierr; 7903 7904 PetscFunctionBegin; 7905 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7906 PetscValidCharPointer(name, 2); 7907 PetscValidPointer(points, 4); 7908 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7909 *points = NULL; 7910 if (!label) PetscFunctionReturn(0); 7911 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 7912 PetscFunctionReturn(0); 7913 } 7914 7915 /*@C 7916 DMSetStratumIS - Set the points in a label stratum 7917 7918 Not Collective 7919 7920 Input Parameters: 7921 + dm - The DM object 7922 . name - The label name 7923 . value - The stratum value 7924 - points - The stratum points 7925 7926 Level: beginner 7927 7928 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 7929 @*/ 7930 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 7931 { 7932 DMLabel label; 7933 PetscErrorCode ierr; 7934 7935 PetscFunctionBegin; 7936 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7937 PetscValidCharPointer(name, 2); 7938 PetscValidPointer(points, 4); 7939 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7940 if (!label) PetscFunctionReturn(0); 7941 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 7942 PetscFunctionReturn(0); 7943 } 7944 7945 /*@C 7946 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 7947 7948 Not Collective 7949 7950 Input Parameters: 7951 + dm - The DM object 7952 . name - The label name 7953 - value - The label value for this point 7954 7955 Output Parameter: 7956 7957 Level: beginner 7958 7959 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 7960 @*/ 7961 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 7962 { 7963 DMLabel label; 7964 PetscErrorCode ierr; 7965 7966 PetscFunctionBegin; 7967 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7968 PetscValidCharPointer(name, 2); 7969 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7970 if (!label) PetscFunctionReturn(0); 7971 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 7972 PetscFunctionReturn(0); 7973 } 7974 7975 /*@ 7976 DMGetNumLabels - Return the number of labels defined by the mesh 7977 7978 Not Collective 7979 7980 Input Parameter: 7981 . dm - The DM object 7982 7983 Output Parameter: 7984 . numLabels - the number of Labels 7985 7986 Level: intermediate 7987 7988 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7989 @*/ 7990 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 7991 { 7992 DMLabelLink next = dm->labels; 7993 PetscInt n = 0; 7994 7995 PetscFunctionBegin; 7996 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7997 PetscValidIntPointer(numLabels, 2); 7998 while (next) {++n; next = next->next;} 7999 *numLabels = n; 8000 PetscFunctionReturn(0); 8001 } 8002 8003 /*@C 8004 DMGetLabelName - Return the name of nth label 8005 8006 Not Collective 8007 8008 Input Parameters: 8009 + dm - The DM object 8010 - n - the label number 8011 8012 Output Parameter: 8013 . name - the label name 8014 8015 Level: intermediate 8016 8017 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8018 @*/ 8019 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 8020 { 8021 DMLabelLink next = dm->labels; 8022 PetscInt l = 0; 8023 PetscErrorCode ierr; 8024 8025 PetscFunctionBegin; 8026 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8027 PetscValidPointer(name, 3); 8028 while (next) { 8029 if (l == n) { 8030 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 8031 PetscFunctionReturn(0); 8032 } 8033 ++l; 8034 next = next->next; 8035 } 8036 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 8037 } 8038 8039 /*@C 8040 DMHasLabel - Determine whether the mesh has a label of a given name 8041 8042 Not Collective 8043 8044 Input Parameters: 8045 + dm - The DM object 8046 - name - The label name 8047 8048 Output Parameter: 8049 . hasLabel - PETSC_TRUE if the label is present 8050 8051 Level: intermediate 8052 8053 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8054 @*/ 8055 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 8056 { 8057 DMLabelLink next = dm->labels; 8058 const char *lname; 8059 PetscErrorCode ierr; 8060 8061 PetscFunctionBegin; 8062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8063 PetscValidCharPointer(name, 2); 8064 PetscValidBoolPointer(hasLabel, 3); 8065 *hasLabel = PETSC_FALSE; 8066 while (next) { 8067 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8068 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 8069 if (*hasLabel) break; 8070 next = next->next; 8071 } 8072 PetscFunctionReturn(0); 8073 } 8074 8075 /*@C 8076 DMGetLabel - Return the label of a given name, or NULL 8077 8078 Not Collective 8079 8080 Input Parameters: 8081 + dm - The DM object 8082 - name - The label name 8083 8084 Output Parameter: 8085 . label - The DMLabel, or NULL if the label is absent 8086 8087 Note: Some of the default labels in a DMPlex will be 8088 $ "depth" - Holds the depth (co-dimension) of each mesh point 8089 $ "celltype" - Holds the topological type of each cell 8090 $ "ghost" - If the DM is distributed with overlap, this marks the cells and faces in the overlap 8091 $ "Cell Sets" - Mirrors the cell sets defined by GMsh and ExodusII 8092 $ "Face Sets" - Mirrors the face sets defined by GMsh and ExodusII 8093 $ "Vertex Sets" - Mirrors the vertex sets defined by GMsh 8094 8095 Level: intermediate 8096 8097 .seealso: DMCreateLabel(), DMHasLabel(), DMPlexGetDepthLabel(), DMPlexGetCellType() 8098 @*/ 8099 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 8100 { 8101 DMLabelLink next = dm->labels; 8102 PetscBool hasLabel; 8103 const char *lname; 8104 PetscErrorCode ierr; 8105 8106 PetscFunctionBegin; 8107 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8108 PetscValidCharPointer(name, 2); 8109 PetscValidPointer(label, 3); 8110 *label = NULL; 8111 while (next) { 8112 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8113 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 8114 if (hasLabel) { 8115 *label = next->label; 8116 break; 8117 } 8118 next = next->next; 8119 } 8120 PetscFunctionReturn(0); 8121 } 8122 8123 /*@C 8124 DMGetLabelByNum - Return the nth label 8125 8126 Not Collective 8127 8128 Input Parameters: 8129 + dm - The DM object 8130 - n - the label number 8131 8132 Output Parameter: 8133 . label - the label 8134 8135 Level: intermediate 8136 8137 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8138 @*/ 8139 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 8140 { 8141 DMLabelLink next = dm->labels; 8142 PetscInt l = 0; 8143 8144 PetscFunctionBegin; 8145 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8146 PetscValidPointer(label, 3); 8147 while (next) { 8148 if (l == n) { 8149 *label = next->label; 8150 PetscFunctionReturn(0); 8151 } 8152 ++l; 8153 next = next->next; 8154 } 8155 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 8156 } 8157 8158 /*@C 8159 DMAddLabel - Add the label to this mesh 8160 8161 Not Collective 8162 8163 Input Parameters: 8164 + dm - The DM object 8165 - label - The DMLabel 8166 8167 Level: developer 8168 8169 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8170 @*/ 8171 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 8172 { 8173 DMLabelLink l, *p, tmpLabel; 8174 PetscBool hasLabel; 8175 const char *lname; 8176 PetscBool flg; 8177 PetscErrorCode ierr; 8178 8179 PetscFunctionBegin; 8180 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8181 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 8182 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 8183 PetscCheckFalse(hasLabel,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 8184 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 8185 tmpLabel->label = label; 8186 tmpLabel->output = PETSC_TRUE; 8187 for (p=&dm->labels; (l=*p); p=&l->next) {} 8188 *p = tmpLabel; 8189 ierr = PetscObjectReference((PetscObject)label);CHKERRQ(ierr); 8190 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 8191 if (flg) dm->depthLabel = label; 8192 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 8193 if (flg) dm->celltypeLabel = label; 8194 PetscFunctionReturn(0); 8195 } 8196 8197 /*@C 8198 DMSetLabel - Replaces the label of a given name, or ignores it if the name is not present 8199 8200 Not Collective 8201 8202 Input Parameters: 8203 + dm - The DM object 8204 - label - The DMLabel, having the same name, to substitute 8205 8206 Note: Some of the default labels in a DMPlex will be 8207 $ "depth" - Holds the depth (co-dimension) of each mesh point 8208 $ "celltype" - Holds the topological type of each cell 8209 $ "ghost" - If the DM is distributed with overlap, this marks the cells and faces in the overlap 8210 $ "Cell Sets" - Mirrors the cell sets defined by GMsh and ExodusII 8211 $ "Face Sets" - Mirrors the face sets defined by GMsh and ExodusII 8212 $ "Vertex Sets" - Mirrors the vertex sets defined by GMsh 8213 8214 Level: intermediate 8215 8216 .seealso: DMCreateLabel(), DMHasLabel(), DMPlexGetDepthLabel(), DMPlexGetCellType() 8217 @*/ 8218 PetscErrorCode DMSetLabel(DM dm, DMLabel label) 8219 { 8220 DMLabelLink next = dm->labels; 8221 PetscBool hasLabel, flg; 8222 const char *name, *lname; 8223 PetscErrorCode ierr; 8224 8225 PetscFunctionBegin; 8226 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8227 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 8228 ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr); 8229 while (next) { 8230 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8231 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 8232 if (hasLabel) { 8233 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 8234 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 8235 if (flg) dm->depthLabel = label; 8236 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 8237 if (flg) dm->celltypeLabel = label; 8238 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 8239 next->label = label; 8240 break; 8241 } 8242 next = next->next; 8243 } 8244 PetscFunctionReturn(0); 8245 } 8246 8247 /*@C 8248 DMRemoveLabel - Remove the label given by name from this mesh 8249 8250 Not Collective 8251 8252 Input Parameters: 8253 + dm - The DM object 8254 - name - The label name 8255 8256 Output Parameter: 8257 . label - The DMLabel, or NULL if the label is absent 8258 8259 Level: developer 8260 8261 Notes: 8262 DMRemoveLabel(dm,name,NULL) removes the label from dm and calls 8263 DMLabelDestroy() on the label. 8264 8265 DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT 8266 call DMLabelDestroy(). Instead, the label is returned and the user is 8267 responsible of calling DMLabelDestroy() at some point. 8268 8269 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf() 8270 @*/ 8271 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 8272 { 8273 DMLabelLink link, *pnext; 8274 PetscBool hasLabel; 8275 const char *lname; 8276 PetscErrorCode ierr; 8277 8278 PetscFunctionBegin; 8279 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8280 PetscValidCharPointer(name, 2); 8281 if (label) { 8282 PetscValidPointer(label, 3); 8283 *label = NULL; 8284 } 8285 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 8286 ierr = PetscObjectGetName((PetscObject) link->label, &lname);CHKERRQ(ierr); 8287 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 8288 if (hasLabel) { 8289 *pnext = link->next; /* Remove from list */ 8290 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 8291 if (hasLabel) dm->depthLabel = NULL; 8292 ierr = PetscStrcmp(name, "celltype", &hasLabel);CHKERRQ(ierr); 8293 if (hasLabel) dm->celltypeLabel = NULL; 8294 if (label) *label = link->label; 8295 else {ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);} 8296 ierr = PetscFree(link);CHKERRQ(ierr); 8297 break; 8298 } 8299 } 8300 PetscFunctionReturn(0); 8301 } 8302 8303 /*@ 8304 DMRemoveLabelBySelf - Remove the label from this mesh 8305 8306 Not Collective 8307 8308 Input Parameters: 8309 + dm - The DM object 8310 . label - The DMLabel to be removed from the DM 8311 - failNotFound - Should it fail if the label is not found in the DM? 8312 8313 Level: developer 8314 8315 Notes: 8316 Only exactly the same instance is removed if found, name match is ignored. 8317 If the DM has an exclusive reference to the label, it gets destroyed and 8318 *label nullified. 8319 8320 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel() 8321 @*/ 8322 PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound) 8323 { 8324 DMLabelLink link, *pnext; 8325 PetscBool hasLabel = PETSC_FALSE; 8326 PetscErrorCode ierr; 8327 8328 PetscFunctionBegin; 8329 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8330 PetscValidPointer(label, 2); 8331 if (!*label && !failNotFound) PetscFunctionReturn(0); 8332 PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2); 8333 PetscValidLogicalCollectiveBool(dm,failNotFound,3); 8334 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 8335 if (*label == link->label) { 8336 hasLabel = PETSC_TRUE; 8337 *pnext = link->next; /* Remove from list */ 8338 if (*label == dm->depthLabel) dm->depthLabel = NULL; 8339 if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL; 8340 if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */ 8341 ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr); 8342 ierr = PetscFree(link);CHKERRQ(ierr); 8343 break; 8344 } 8345 } 8346 PetscCheckFalse(!hasLabel && failNotFound,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM"); 8347 PetscFunctionReturn(0); 8348 } 8349 8350 /*@C 8351 DMGetLabelOutput - Get the output flag for a given label 8352 8353 Not Collective 8354 8355 Input Parameters: 8356 + dm - The DM object 8357 - name - The label name 8358 8359 Output Parameter: 8360 . output - The flag for output 8361 8362 Level: developer 8363 8364 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8365 @*/ 8366 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 8367 { 8368 DMLabelLink next = dm->labels; 8369 const char *lname; 8370 PetscErrorCode ierr; 8371 8372 PetscFunctionBegin; 8373 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8374 PetscValidPointer(name, 2); 8375 PetscValidPointer(output, 3); 8376 while (next) { 8377 PetscBool flg; 8378 8379 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8380 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 8381 if (flg) {*output = next->output; PetscFunctionReturn(0);} 8382 next = next->next; 8383 } 8384 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 8385 } 8386 8387 /*@C 8388 DMSetLabelOutput - Set the output flag for a given label 8389 8390 Not Collective 8391 8392 Input Parameters: 8393 + dm - The DM object 8394 . name - The label name 8395 - output - The flag for output 8396 8397 Level: developer 8398 8399 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8400 @*/ 8401 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 8402 { 8403 DMLabelLink next = dm->labels; 8404 const char *lname; 8405 PetscErrorCode ierr; 8406 8407 PetscFunctionBegin; 8408 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8409 PetscValidCharPointer(name, 2); 8410 while (next) { 8411 PetscBool flg; 8412 8413 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8414 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 8415 if (flg) {next->output = output; PetscFunctionReturn(0);} 8416 next = next->next; 8417 } 8418 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 8419 } 8420 8421 /*@ 8422 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 8423 8424 Collective on dmA 8425 8426 Input Parameters: 8427 + dmA - The DM object with initial labels 8428 . dmB - The DM object to which labels are copied 8429 . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES) 8430 . all - Copy all labels including "depth", "dim", and "celltype" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE) 8431 - emode - How to behave when a DMLabel in the source and destination DMs with the same name is encountered (see DMCopyLabelsMode) 8432 8433 Level: intermediate 8434 8435 Notes: 8436 This is typically used when interpolating or otherwise adding to a mesh, or testing. 8437 8438 .seealso: DMAddLabel(), DMCopyLabelsMode 8439 @*/ 8440 PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all, DMCopyLabelsMode emode) 8441 { 8442 DMLabel label, labelNew, labelOld; 8443 const char *name; 8444 PetscBool flg; 8445 DMLabelLink link; 8446 PetscErrorCode ierr; 8447 8448 PetscFunctionBegin; 8449 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 8450 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 8451 PetscValidLogicalCollectiveEnum(dmA, mode,3); 8452 PetscValidLogicalCollectiveBool(dmA, all, 4); 8453 PetscCheckFalse(mode==PETSC_USE_POINTER,PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects"); 8454 if (dmA == dmB) PetscFunctionReturn(0); 8455 for (link=dmA->labels; link; link=link->next) { 8456 label=link->label; 8457 ierr = PetscObjectGetName((PetscObject)label, &name);CHKERRQ(ierr); 8458 if (!all) { 8459 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 8460 if (flg) continue; 8461 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 8462 if (flg) continue; 8463 ierr = PetscStrcmp(name, "celltype", &flg);CHKERRQ(ierr); 8464 if (flg) continue; 8465 } 8466 ierr = DMGetLabel(dmB, name, &labelOld);CHKERRQ(ierr); 8467 if (labelOld) { 8468 switch (emode) { 8469 case DM_COPY_LABELS_KEEP: 8470 continue; 8471 case DM_COPY_LABELS_REPLACE: 8472 ierr = DMRemoveLabelBySelf(dmB, &labelOld, PETSC_TRUE);CHKERRQ(ierr); 8473 break; 8474 case DM_COPY_LABELS_FAIL: 8475 SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in destination DM", name); 8476 default: 8477 SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Unhandled DMCopyLabelsMode %d", emode); 8478 } 8479 } 8480 if (mode==PETSC_COPY_VALUES) { 8481 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 8482 } else { 8483 labelNew = label; 8484 } 8485 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 8486 if (mode==PETSC_COPY_VALUES) {ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);} 8487 } 8488 PetscFunctionReturn(0); 8489 } 8490 8491 /*@C 8492 DMCompareLabels - Compare labels of two DMPlex meshes 8493 8494 Collective 8495 8496 Input Parameters: 8497 + dm0 - First DM object 8498 - dm1 - Second DM object 8499 8500 Output Parameters 8501 + equal - (Optional) Flag whether labels of dm0 and dm1 are the same 8502 - message - (Optional) Message describing the difference, or NULL if there is no difference 8503 8504 Level: intermediate 8505 8506 Notes: 8507 The output flag equal is the same on all processes. 8508 If it is passed as NULL and difference is found, an error is thrown on all processes. 8509 Make sure to pass NULL on all processes. 8510 8511 The output message is set independently on each rank. 8512 It is set to NULL if no difference was found on the current rank. It must be freed by user. 8513 If message is passed as NULL and difference is found, the difference description is printed to stderr in synchronized manner. 8514 Make sure to pass NULL on all processes. 8515 8516 Labels are matched by name. If the number of labels and their names are equal, 8517 DMLabelCompare() is used to compare each pair of labels with the same name. 8518 8519 Fortran Notes: 8520 This function is currently not available from Fortran. 8521 8522 .seealso: DMAddLabel(), DMCopyLabelsMode, DMLabelCompare() 8523 @*/ 8524 PetscErrorCode DMCompareLabels(DM dm0, DM dm1, PetscBool *equal, char **message) 8525 { 8526 PetscInt n, i; 8527 char msg[PETSC_MAX_PATH_LEN] = ""; 8528 PetscBool eq; 8529 MPI_Comm comm; 8530 PetscMPIInt rank; 8531 PetscErrorCode ierr; 8532 8533 PetscFunctionBegin; 8534 PetscValidHeaderSpecific(dm0,DM_CLASSID,1); 8535 PetscValidHeaderSpecific(dm1,DM_CLASSID,2); 8536 PetscCheckSameComm(dm0,1,dm1,2); 8537 if (equal) PetscValidBoolPointer(equal,3); 8538 if (message) PetscValidPointer(message, 4); 8539 ierr = PetscObjectGetComm((PetscObject)dm0, &comm);CHKERRQ(ierr); 8540 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 8541 { 8542 PetscInt n1; 8543 8544 ierr = DMGetNumLabels(dm0, &n);CHKERRQ(ierr); 8545 ierr = DMGetNumLabels(dm1, &n1);CHKERRQ(ierr); 8546 eq = (PetscBool) (n == n1); 8547 if (!eq) { 8548 ierr = PetscSNPrintf(msg, sizeof(msg), "Number of labels in dm0 = %D != %D = Number of labels in dm1", n, n1);CHKERRQ(ierr); 8549 } 8550 ierr = MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRMPI(ierr); 8551 if (!eq) goto finish; 8552 } 8553 for (i=0; i<n; i++) { 8554 DMLabel l0, l1; 8555 const char *name; 8556 char *msgInner; 8557 8558 /* Ignore label order */ 8559 ierr = DMGetLabelByNum(dm0, i, &l0);CHKERRQ(ierr); 8560 ierr = PetscObjectGetName((PetscObject)l0, &name);CHKERRQ(ierr); 8561 ierr = DMGetLabel(dm1, name, &l1);CHKERRQ(ierr); 8562 if (!l1) { 8563 ierr = PetscSNPrintf(msg, sizeof(msg), "Label \"%s\" (#%D in dm0) not found in dm1", name, i);CHKERRQ(ierr); 8564 eq = PETSC_FALSE; 8565 break; 8566 } 8567 ierr = DMLabelCompare(comm, l0, l1, &eq, &msgInner);CHKERRQ(ierr); 8568 ierr = PetscStrncpy(msg, msgInner, sizeof(msg));CHKERRQ(ierr); 8569 ierr = PetscFree(msgInner);CHKERRQ(ierr); 8570 if (!eq) break; 8571 } 8572 ierr = MPI_Allreduce(MPI_IN_PLACE, &eq, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRMPI(ierr); 8573 finish: 8574 /* If message output arg not set, print to stderr */ 8575 if (message) { 8576 *message = NULL; 8577 if (msg[0]) { 8578 ierr = PetscStrallocpy(msg, message);CHKERRQ(ierr); 8579 } 8580 } else { 8581 if (msg[0]) { 8582 ierr = PetscSynchronizedFPrintf(comm, PETSC_STDERR, "[%d] %s\n", rank, msg);CHKERRQ(ierr); 8583 } 8584 ierr = PetscSynchronizedFlush(comm, PETSC_STDERR);CHKERRQ(ierr); 8585 } 8586 /* If same output arg not ser and labels are not equal, throw error */ 8587 if (equal) *equal = eq; 8588 else PetscCheckFalse(!eq,comm, PETSC_ERR_ARG_INCOMP, "DMLabels are not the same in dm0 and dm1"); 8589 PetscFunctionReturn(0); 8590 } 8591 8592 PetscErrorCode DMSetLabelValue_Fast(DM dm, DMLabel *label, const char name[], PetscInt point, PetscInt value) 8593 { 8594 PetscErrorCode ierr; 8595 8596 PetscFunctionBegin; 8597 PetscValidPointer(label,2); 8598 if (!*label) { 8599 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 8600 ierr = DMGetLabel(dm, name, label);CHKERRQ(ierr); 8601 } 8602 ierr = DMLabelSetValue(*label, point, value);CHKERRQ(ierr); 8603 PetscFunctionReturn(0); 8604 } 8605 8606 /* 8607 Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would 8608 like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every 8609 (label, id) pair in the DM. 8610 8611 However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to 8612 each label. 8613 */ 8614 PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal) 8615 { 8616 DMUniversalLabel ul; 8617 PetscBool *active; 8618 PetscInt pStart, pEnd, p, Nl, l, m; 8619 PetscErrorCode ierr; 8620 8621 PetscFunctionBegin; 8622 ierr = PetscMalloc1(1, &ul);CHKERRQ(ierr); 8623 ierr = DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label);CHKERRQ(ierr); 8624 ierr = DMGetNumLabels(dm, &Nl);CHKERRQ(ierr); 8625 ierr = PetscCalloc1(Nl, &active);CHKERRQ(ierr); 8626 ul->Nl = 0; 8627 for (l = 0; l < Nl; ++l) { 8628 PetscBool isdepth, iscelltype; 8629 const char *name; 8630 8631 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 8632 ierr = PetscStrncmp(name, "depth", 6, &isdepth);CHKERRQ(ierr); 8633 ierr = PetscStrncmp(name, "celltype", 9, &iscelltype);CHKERRQ(ierr); 8634 active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE; 8635 if (active[l]) ++ul->Nl; 8636 } 8637 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); 8638 ul->Nv = 0; 8639 for (l = 0, m = 0; l < Nl; ++l) { 8640 DMLabel label; 8641 PetscInt nv; 8642 const char *name; 8643 8644 if (!active[l]) continue; 8645 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 8646 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8647 ierr = DMLabelGetNumValues(label, &nv);CHKERRQ(ierr); 8648 ierr = PetscStrallocpy(name, &ul->names[m]);CHKERRQ(ierr); 8649 ul->indices[m] = l; 8650 ul->Nv += nv; 8651 ul->offsets[m+1] = nv; 8652 ul->bits[m+1] = PetscCeilReal(PetscLog2Real(nv+1)); 8653 ++m; 8654 } 8655 for (l = 1; l <= ul->Nl; ++l) { 8656 ul->offsets[l] = ul->offsets[l-1] + ul->offsets[l]; 8657 ul->bits[l] = ul->bits[l-1] + ul->bits[l]; 8658 } 8659 for (l = 0; l < ul->Nl; ++l) { 8660 PetscInt b; 8661 8662 ul->masks[l] = 0; 8663 for (b = ul->bits[l]; b < ul->bits[l+1]; ++b) ul->masks[l] |= 1 << b; 8664 } 8665 ierr = PetscMalloc1(ul->Nv, &ul->values);CHKERRQ(ierr); 8666 for (l = 0, m = 0; l < Nl; ++l) { 8667 DMLabel label; 8668 IS valueIS; 8669 const PetscInt *varr; 8670 PetscInt nv, v; 8671 8672 if (!active[l]) continue; 8673 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8674 ierr = DMLabelGetNumValues(label, &nv);CHKERRQ(ierr); 8675 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 8676 ierr = ISGetIndices(valueIS, &varr);CHKERRQ(ierr); 8677 for (v = 0; v < nv; ++v) { 8678 ul->values[ul->offsets[m]+v] = varr[v]; 8679 } 8680 ierr = ISRestoreIndices(valueIS, &varr);CHKERRQ(ierr); 8681 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 8682 ierr = PetscSortInt(nv, &ul->values[ul->offsets[m]]);CHKERRQ(ierr); 8683 ++m; 8684 } 8685 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8686 for (p = pStart; p < pEnd; ++p) { 8687 PetscInt uval = 0; 8688 PetscBool marked = PETSC_FALSE; 8689 8690 for (l = 0, m = 0; l < Nl; ++l) { 8691 DMLabel label; 8692 PetscInt val, defval, loc, nv; 8693 8694 if (!active[l]) continue; 8695 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8696 ierr = DMLabelGetValue(label, p, &val);CHKERRQ(ierr); 8697 ierr = DMLabelGetDefaultValue(label, &defval);CHKERRQ(ierr); 8698 if (val == defval) {++m; continue;} 8699 nv = ul->offsets[m+1]-ul->offsets[m]; 8700 marked = PETSC_TRUE; 8701 ierr = PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc);CHKERRQ(ierr); 8702 PetscCheckFalse(loc < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %D not found in compression array", val); 8703 uval += (loc+1) << ul->bits[m]; 8704 ++m; 8705 } 8706 if (marked) {ierr = DMLabelSetValue(ul->label, p, uval);CHKERRQ(ierr);} 8707 } 8708 ierr = PetscFree(active);CHKERRQ(ierr); 8709 *universal = ul; 8710 PetscFunctionReturn(0); 8711 } 8712 8713 PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal) 8714 { 8715 PetscInt l; 8716 PetscErrorCode ierr; 8717 8718 PetscFunctionBegin; 8719 for (l = 0; l < (*universal)->Nl; ++l) {ierr = PetscFree((*universal)->names[l]);CHKERRQ(ierr);} 8720 ierr = DMLabelDestroy(&(*universal)->label);CHKERRQ(ierr); 8721 ierr = PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks);CHKERRQ(ierr); 8722 ierr = PetscFree((*universal)->values);CHKERRQ(ierr); 8723 ierr = PetscFree(*universal);CHKERRQ(ierr); 8724 *universal = NULL; 8725 PetscFunctionReturn(0); 8726 } 8727 8728 PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel) 8729 { 8730 PetscFunctionBegin; 8731 PetscValidPointer(ulabel, 2); 8732 *ulabel = ul->label; 8733 PetscFunctionReturn(0); 8734 } 8735 8736 PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm) 8737 { 8738 PetscInt Nl = ul->Nl, l; 8739 PetscErrorCode ierr; 8740 8741 PetscFunctionBegin; 8742 PetscValidHeaderSpecific(dm, DM_CLASSID, 3); 8743 for (l = 0; l < Nl; ++l) { 8744 if (preserveOrder) {ierr = DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]);CHKERRQ(ierr);} 8745 else {ierr = DMCreateLabel(dm, ul->names[l]);CHKERRQ(ierr);} 8746 } 8747 if (preserveOrder) { 8748 for (l = 0; l < ul->Nl; ++l) { 8749 const char *name; 8750 PetscBool match; 8751 8752 ierr = DMGetLabelName(dm, ul->indices[l], &name);CHKERRQ(ierr); 8753 ierr = PetscStrcmp(name, ul->names[l], &match);CHKERRQ(ierr); 8754 PetscCheckFalse(!match,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %D name %s does not match new name %s", l, name, ul->names[l]); 8755 } 8756 } 8757 PetscFunctionReturn(0); 8758 } 8759 8760 PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value) 8761 { 8762 PetscInt l; 8763 PetscErrorCode ierr; 8764 8765 PetscFunctionBegin; 8766 for (l = 0; l < ul->Nl; ++l) { 8767 DMLabel label; 8768 PetscInt lval = (value & ul->masks[l]) >> ul->bits[l]; 8769 8770 if (lval) { 8771 if (useIndex) {ierr = DMGetLabelByNum(dm, ul->indices[l], &label);CHKERRQ(ierr);} 8772 else {ierr = DMGetLabel(dm, ul->names[l], &label);CHKERRQ(ierr);} 8773 ierr = DMLabelSetValue(label, p, ul->values[ul->offsets[l]+lval-1]);CHKERRQ(ierr); 8774 } 8775 } 8776 PetscFunctionReturn(0); 8777 } 8778 8779 /*@ 8780 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 8781 8782 Input Parameter: 8783 . dm - The DM object 8784 8785 Output Parameter: 8786 . cdm - The coarse DM 8787 8788 Level: intermediate 8789 8790 .seealso: DMSetCoarseDM() 8791 @*/ 8792 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 8793 { 8794 PetscFunctionBegin; 8795 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8796 PetscValidPointer(cdm, 2); 8797 *cdm = dm->coarseMesh; 8798 PetscFunctionReturn(0); 8799 } 8800 8801 /*@ 8802 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 8803 8804 Input Parameters: 8805 + dm - The DM object 8806 - cdm - The coarse DM 8807 8808 Level: intermediate 8809 8810 .seealso: DMGetCoarseDM() 8811 @*/ 8812 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 8813 { 8814 PetscErrorCode ierr; 8815 8816 PetscFunctionBegin; 8817 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8818 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 8819 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 8820 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 8821 dm->coarseMesh = cdm; 8822 PetscFunctionReturn(0); 8823 } 8824 8825 /*@ 8826 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 8827 8828 Input Parameter: 8829 . dm - The DM object 8830 8831 Output Parameter: 8832 . fdm - The fine DM 8833 8834 Level: intermediate 8835 8836 .seealso: DMSetFineDM() 8837 @*/ 8838 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 8839 { 8840 PetscFunctionBegin; 8841 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8842 PetscValidPointer(fdm, 2); 8843 *fdm = dm->fineMesh; 8844 PetscFunctionReturn(0); 8845 } 8846 8847 /*@ 8848 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 8849 8850 Input Parameters: 8851 + dm - The DM object 8852 - fdm - The fine DM 8853 8854 Level: intermediate 8855 8856 .seealso: DMGetFineDM() 8857 @*/ 8858 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 8859 { 8860 PetscErrorCode ierr; 8861 8862 PetscFunctionBegin; 8863 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8864 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 8865 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 8866 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 8867 dm->fineMesh = fdm; 8868 PetscFunctionReturn(0); 8869 } 8870 8871 /*=== DMBoundary code ===*/ 8872 8873 /*@C 8874 DMAddBoundary - Add a boundary condition to the model 8875 8876 Collective on dm 8877 8878 Input Parameters: 8879 + dm - The DM, with a PetscDS that matches the problem being constrained 8880 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 8881 . name - The BC name 8882 . label - The label defining constrained points 8883 . Nv - The number of DMLabel values for constrained points 8884 . values - An array of values for constrained points 8885 . field - The field to constrain 8886 . Nc - The number of constrained field components (0 will constrain all fields) 8887 . comps - An array of constrained component numbers 8888 . bcFunc - A pointwise function giving boundary values 8889 . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL 8890 - ctx - An optional user context for bcFunc 8891 8892 Output Parameter: 8893 . bd - (Optional) Boundary number 8894 8895 Options Database Keys: 8896 + -bc_<boundary name> <num> - Overrides the boundary ids 8897 - -bc_<boundary name>_comp <num> - Overrides the boundary components 8898 8899 Note: 8900 Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is: 8901 8902 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 8903 8904 If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is: 8905 8906 $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8907 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8908 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8909 $ PetscReal time, const PetscReal x[], PetscScalar bcval[]) 8910 8911 + dim - the spatial dimension 8912 . Nf - the number of fields 8913 . uOff - the offset into u[] and u_t[] for each field 8914 . uOff_x - the offset into u_x[] for each field 8915 . u - each field evaluated at the current point 8916 . u_t - the time derivative of each field evaluated at the current point 8917 . u_x - the gradient of each field evaluated at the current point 8918 . aOff - the offset into a[] and a_t[] for each auxiliary field 8919 . aOff_x - the offset into a_x[] for each auxiliary field 8920 . a - each auxiliary field evaluated at the current point 8921 . a_t - the time derivative of each auxiliary field evaluated at the current point 8922 . a_x - the gradient of auxiliary each field evaluated at the current point 8923 . t - current time 8924 . x - coordinates of the current point 8925 . numConstants - number of constant parameters 8926 . constants - constant parameters 8927 - bcval - output values at the current point 8928 8929 Level: intermediate 8930 8931 .seealso: DSGetBoundary(), PetscDSAddBoundary() 8932 @*/ 8933 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) 8934 { 8935 PetscDS ds; 8936 PetscErrorCode ierr; 8937 8938 PetscFunctionBegin; 8939 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8940 PetscValidLogicalCollectiveEnum(dm, type, 2); 8941 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4); 8942 PetscValidLogicalCollectiveInt(dm, Nv, 5); 8943 PetscValidLogicalCollectiveInt(dm, field, 7); 8944 PetscValidLogicalCollectiveInt(dm, Nc, 8); 8945 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 8946 ierr = DMCompleteBoundaryLabel_Internal(dm, ds, field, PETSC_MAX_INT, label);CHKERRQ(ierr); 8947 ierr = PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd);CHKERRQ(ierr); 8948 PetscFunctionReturn(0); 8949 } 8950 8951 /* TODO Remove this since now the structures are the same */ 8952 static PetscErrorCode DMPopulateBoundary(DM dm) 8953 { 8954 PetscDS ds; 8955 DMBoundary *lastnext; 8956 DSBoundary dsbound; 8957 PetscErrorCode ierr; 8958 8959 PetscFunctionBegin; 8960 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 8961 dsbound = ds->boundary; 8962 if (dm->boundary) { 8963 DMBoundary next = dm->boundary; 8964 8965 /* quick check to see if the PetscDS has changed */ 8966 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 8967 /* the PetscDS has changed: tear down and rebuild */ 8968 while (next) { 8969 DMBoundary b = next; 8970 8971 next = b->next; 8972 ierr = PetscFree(b);CHKERRQ(ierr); 8973 } 8974 dm->boundary = NULL; 8975 } 8976 8977 lastnext = &(dm->boundary); 8978 while (dsbound) { 8979 DMBoundary dmbound; 8980 8981 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 8982 dmbound->dsboundary = dsbound; 8983 dmbound->label = dsbound->label; 8984 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 8985 *lastnext = dmbound; 8986 lastnext = &(dmbound->next); 8987 dsbound = dsbound->next; 8988 } 8989 PetscFunctionReturn(0); 8990 } 8991 8992 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 8993 { 8994 DMBoundary b; 8995 PetscErrorCode ierr; 8996 8997 PetscFunctionBegin; 8998 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8999 PetscValidBoolPointer(isBd, 3); 9000 *isBd = PETSC_FALSE; 9001 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 9002 b = dm->boundary; 9003 while (b && !(*isBd)) { 9004 DMLabel label = b->label; 9005 DSBoundary dsb = b->dsboundary; 9006 PetscInt i; 9007 9008 if (label) { 9009 for (i = 0; i < dsb->Nv && !(*isBd); ++i) {ierr = DMLabelStratumHasPoint(label, dsb->values[i], point, isBd);CHKERRQ(ierr);} 9010 } 9011 b = b->next; 9012 } 9013 PetscFunctionReturn(0); 9014 } 9015 9016 /*@C 9017 DMProjectFunction - This projects the given function into the function space provided, putting the coefficients in a global vector. 9018 9019 Collective on DM 9020 9021 Input Parameters: 9022 + dm - The DM 9023 . time - The time 9024 . funcs - The coordinate functions to evaluate, one per field 9025 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 9026 - mode - The insertion mode for values 9027 9028 Output Parameter: 9029 . X - vector 9030 9031 Calling sequence of func: 9032 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 9033 9034 + dim - The spatial dimension 9035 . time - The time at which to sample 9036 . x - The coordinates 9037 . Nc - The number of components 9038 . u - The output field values 9039 - ctx - optional user-defined function context 9040 9041 Level: developer 9042 9043 .seealso: DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 9044 @*/ 9045 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 9046 { 9047 Vec localX; 9048 PetscErrorCode ierr; 9049 9050 PetscFunctionBegin; 9051 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9052 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9053 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 9054 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9055 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9056 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9057 PetscFunctionReturn(0); 9058 } 9059 9060 /*@C 9061 DMProjectFunctionLocal - This projects the given function into the function space provided, putting the coefficients in a local vector. 9062 9063 Not collective 9064 9065 Input Parameters: 9066 + dm - The DM 9067 . time - The time 9068 . funcs - The coordinate functions to evaluate, one per field 9069 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 9070 - mode - The insertion mode for values 9071 9072 Output Parameter: 9073 . localX - vector 9074 9075 Calling sequence of func: 9076 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 9077 9078 + dim - The spatial dimension 9079 . x - The coordinates 9080 . Nc - The number of components 9081 . u - The output field values 9082 - ctx - optional user-defined function context 9083 9084 Level: developer 9085 9086 .seealso: DMProjectFunction(), DMProjectFunctionLabel(), DMComputeL2Diff() 9087 @*/ 9088 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 9089 { 9090 PetscErrorCode ierr; 9091 9092 PetscFunctionBegin; 9093 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9094 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 9095 PetscCheckFalse(!dm->ops->projectfunctionlocal,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 9096 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 9097 PetscFunctionReturn(0); 9098 } 9099 9100 /*@C 9101 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. 9102 9103 Collective on DM 9104 9105 Input Parameters: 9106 + dm - The DM 9107 . time - The time 9108 . label - The DMLabel selecting the portion of the mesh for projection 9109 . funcs - The coordinate functions to evaluate, one per field 9110 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 9111 - mode - The insertion mode for values 9112 9113 Output Parameter: 9114 . X - vector 9115 9116 Calling sequence of func: 9117 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 9118 9119 + dim - The spatial dimension 9120 . x - The coordinates 9121 . Nc - The number of components 9122 . u - The output field values 9123 - ctx - optional user-defined function context 9124 9125 Level: developer 9126 9127 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal(), DMComputeL2Diff() 9128 @*/ 9129 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) 9130 { 9131 Vec localX; 9132 PetscErrorCode ierr; 9133 9134 PetscFunctionBegin; 9135 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9136 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9137 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 9138 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9139 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9140 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9141 PetscFunctionReturn(0); 9142 } 9143 9144 /*@C 9145 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. 9146 9147 Not collective 9148 9149 Input Parameters: 9150 + dm - The DM 9151 . time - The time 9152 . label - The DMLabel selecting the portion of the mesh for projection 9153 . funcs - The coordinate functions to evaluate, one per field 9154 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 9155 - mode - The insertion mode for values 9156 9157 Output Parameter: 9158 . localX - vector 9159 9160 Calling sequence of func: 9161 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 9162 9163 + dim - The spatial dimension 9164 . x - The coordinates 9165 . Nc - The number of components 9166 . u - The output field values 9167 - ctx - optional user-defined function context 9168 9169 Level: developer 9170 9171 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 9172 @*/ 9173 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) 9174 { 9175 PetscErrorCode ierr; 9176 9177 PetscFunctionBegin; 9178 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9179 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 9180 PetscCheckFalse(!dm->ops->projectfunctionlabellocal,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 9181 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 9182 PetscFunctionReturn(0); 9183 } 9184 9185 /*@C 9186 DMProjectFieldLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector. 9187 9188 Not collective 9189 9190 Input Parameters: 9191 + dm - The DM 9192 . time - The time 9193 . localU - The input field vector 9194 . funcs - The functions to evaluate, one per field 9195 - mode - The insertion mode for values 9196 9197 Output Parameter: 9198 . localX - The output vector 9199 9200 Calling sequence of func: 9201 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9202 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9203 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9204 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 9205 9206 + dim - The spatial dimension 9207 . Nf - The number of input fields 9208 . NfAux - The number of input auxiliary fields 9209 . uOff - The offset of each field in u[] 9210 . uOff_x - The offset of each field in u_x[] 9211 . u - The field values at this point in space 9212 . u_t - The field time derivative at this point in space (or NULL) 9213 . u_x - The field derivatives at this point in space 9214 . aOff - The offset of each auxiliary field in u[] 9215 . aOff_x - The offset of each auxiliary field in u_x[] 9216 . a - The auxiliary field values at this point in space 9217 . a_t - The auxiliary field time derivative at this point in space (or NULL) 9218 . a_x - The auxiliary field derivatives at this point in space 9219 . t - The current time 9220 . x - The coordinates of this point 9221 . numConstants - The number of constants 9222 . constants - The value of each constant 9223 - f - The value of the function at this point in space 9224 9225 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. 9226 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 9227 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 9228 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 9229 9230 Level: intermediate 9231 9232 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 9233 @*/ 9234 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 9235 void (**funcs)(PetscInt, PetscInt, PetscInt, 9236 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9237 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9238 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 9239 InsertMode mode, Vec localX) 9240 { 9241 PetscErrorCode ierr; 9242 9243 PetscFunctionBegin; 9244 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9245 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 9246 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 9247 PetscCheckFalse(!dm->ops->projectfieldlocal,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 9248 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 9249 PetscFunctionReturn(0); 9250 } 9251 9252 /*@C 9253 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. 9254 9255 Not collective 9256 9257 Input Parameters: 9258 + dm - The DM 9259 . time - The time 9260 . label - The DMLabel marking the portion of the domain to output 9261 . numIds - The number of label ids to use 9262 . ids - The label ids to use for marking 9263 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 9264 . comps - The components to set in the output, or NULL for all components 9265 . localU - The input field vector 9266 . funcs - The functions to evaluate, one per field 9267 - mode - The insertion mode for values 9268 9269 Output Parameter: 9270 . localX - The output vector 9271 9272 Calling sequence of func: 9273 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9274 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9275 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9276 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 9277 9278 + dim - The spatial dimension 9279 . Nf - The number of input fields 9280 . NfAux - The number of input auxiliary fields 9281 . uOff - The offset of each field in u[] 9282 . uOff_x - The offset of each field in u_x[] 9283 . u - The field values at this point in space 9284 . u_t - The field time derivative at this point in space (or NULL) 9285 . u_x - The field derivatives at this point in space 9286 . aOff - The offset of each auxiliary field in u[] 9287 . aOff_x - The offset of each auxiliary field in u_x[] 9288 . a - The auxiliary field values at this point in space 9289 . a_t - The auxiliary field time derivative at this point in space (or NULL) 9290 . a_x - The auxiliary field derivatives at this point in space 9291 . t - The current time 9292 . x - The coordinates of this point 9293 . numConstants - The number of constants 9294 . constants - The value of each constant 9295 - f - The value of the function at this point in space 9296 9297 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. 9298 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 9299 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 9300 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 9301 9302 Level: intermediate 9303 9304 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 9305 @*/ 9306 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 9307 void (**funcs)(PetscInt, PetscInt, PetscInt, 9308 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9309 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9310 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 9311 InsertMode mode, Vec localX) 9312 { 9313 PetscErrorCode ierr; 9314 9315 PetscFunctionBegin; 9316 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9317 PetscValidHeaderSpecific(localU,VEC_CLASSID,8); 9318 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 9319 PetscCheckFalse(!dm->ops->projectfieldlabellocal,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLabelLocal",((PetscObject)dm)->type_name); 9320 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 9321 PetscFunctionReturn(0); 9322 } 9323 9324 /*@C 9325 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. 9326 9327 Not collective 9328 9329 Input Parameters: 9330 + dm - The DM 9331 . time - The time 9332 . label - The DMLabel marking the portion of the domain boundary to output 9333 . numIds - The number of label ids to use 9334 . ids - The label ids to use for marking 9335 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 9336 . comps - The components to set in the output, or NULL for all components 9337 . localU - The input field vector 9338 . funcs - The functions to evaluate, one per field 9339 - mode - The insertion mode for values 9340 9341 Output Parameter: 9342 . localX - The output vector 9343 9344 Calling sequence of func: 9345 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9346 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9347 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 9348 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 9349 9350 + dim - The spatial dimension 9351 . Nf - The number of input fields 9352 . NfAux - The number of input auxiliary fields 9353 . uOff - The offset of each field in u[] 9354 . uOff_x - The offset of each field in u_x[] 9355 . u - The field values at this point in space 9356 . u_t - The field time derivative at this point in space (or NULL) 9357 . u_x - The field derivatives at this point in space 9358 . aOff - The offset of each auxiliary field in u[] 9359 . aOff_x - The offset of each auxiliary field in u_x[] 9360 . a - The auxiliary field values at this point in space 9361 . a_t - The auxiliary field time derivative at this point in space (or NULL) 9362 . a_x - The auxiliary field derivatives at this point in space 9363 . t - The current time 9364 . x - The coordinates of this point 9365 . n - The face normal 9366 . numConstants - The number of constants 9367 . constants - The value of each constant 9368 - f - The value of the function at this point in space 9369 9370 Note: 9371 There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 9372 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 9373 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 9374 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 9375 9376 Level: intermediate 9377 9378 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 9379 @*/ 9380 PetscErrorCode DMProjectBdFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 9381 void (**funcs)(PetscInt, PetscInt, PetscInt, 9382 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9383 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 9384 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 9385 InsertMode mode, Vec localX) 9386 { 9387 PetscErrorCode ierr; 9388 9389 PetscFunctionBegin; 9390 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9391 PetscValidHeaderSpecific(localU,VEC_CLASSID,8); 9392 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 9393 PetscCheckFalse(!dm->ops->projectbdfieldlabellocal,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectBdFieldLabelLocal",((PetscObject)dm)->type_name); 9394 ierr = (dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 9395 PetscFunctionReturn(0); 9396 } 9397 9398 /*@C 9399 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9400 9401 Input Parameters: 9402 + dm - The DM 9403 . time - The time 9404 . funcs - The functions to evaluate for each field component 9405 . ctxs - Optional array of contexts to pass to each function, or NULL. 9406 - X - The coefficient vector u_h, a global vector 9407 9408 Output Parameter: 9409 . diff - The diff ||u - u_h||_2 9410 9411 Level: developer 9412 9413 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 9414 @*/ 9415 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 9416 { 9417 PetscErrorCode ierr; 9418 9419 PetscFunctionBegin; 9420 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9421 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9422 PetscCheckFalse(!dm->ops->computel2diff,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 9423 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 9424 PetscFunctionReturn(0); 9425 } 9426 9427 /*@C 9428 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 9429 9430 Collective on dm 9431 9432 Input Parameters: 9433 + dm - The DM 9434 , time - The time 9435 . funcs - The gradient functions to evaluate for each field component 9436 . ctxs - Optional array of contexts to pass to each function, or NULL. 9437 . X - The coefficient vector u_h, a global vector 9438 - n - The vector to project along 9439 9440 Output Parameter: 9441 . diff - The diff ||(grad u - grad u_h) . n||_2 9442 9443 Level: developer 9444 9445 .seealso: DMProjectFunction(), DMComputeL2Diff() 9446 @*/ 9447 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) 9448 { 9449 PetscErrorCode ierr; 9450 9451 PetscFunctionBegin; 9452 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9453 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9454 PetscCheckFalse(!dm->ops->computel2gradientdiff,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 9455 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 9456 PetscFunctionReturn(0); 9457 } 9458 9459 /*@C 9460 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 9461 9462 Collective on dm 9463 9464 Input Parameters: 9465 + dm - The DM 9466 . time - The time 9467 . funcs - The functions to evaluate for each field component 9468 . ctxs - Optional array of contexts to pass to each function, or NULL. 9469 - X - The coefficient vector u_h, a global vector 9470 9471 Output Parameter: 9472 . diff - The array of differences, ||u^f - u^f_h||_2 9473 9474 Level: developer 9475 9476 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 9477 @*/ 9478 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 9479 { 9480 PetscErrorCode ierr; 9481 9482 PetscFunctionBegin; 9483 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9484 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9485 PetscCheckFalse(!dm->ops->computel2fielddiff,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 9486 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 9487 PetscFunctionReturn(0); 9488 } 9489 9490 /*@C 9491 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 9492 9493 Not Collective 9494 9495 Input Parameter: 9496 . dm - The DM 9497 9498 Output Parameters: 9499 + nranks - the number of neighbours 9500 - ranks - the neighbors ranks 9501 9502 Notes: 9503 Do not free the array, it is freed when the DM is destroyed. 9504 9505 Level: beginner 9506 9507 .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks() 9508 @*/ 9509 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 9510 { 9511 PetscErrorCode ierr; 9512 9513 PetscFunctionBegin; 9514 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9515 PetscCheckFalse(!dm->ops->getneighbors,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 9516 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 9517 PetscFunctionReturn(0); 9518 } 9519 9520 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 9521 9522 /* 9523 Converts the input vector to a ghosted vector and then calls the standard coloring code. 9524 This has be a different function because it requires DM which is not defined in the Mat library 9525 */ 9526 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 9527 { 9528 PetscErrorCode ierr; 9529 9530 PetscFunctionBegin; 9531 if (coloring->ctype == IS_COLORING_LOCAL) { 9532 Vec x1local; 9533 DM dm; 9534 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 9535 PetscCheckFalse(!dm,PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 9536 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 9537 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 9538 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 9539 x1 = x1local; 9540 } 9541 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 9542 if (coloring->ctype == IS_COLORING_LOCAL) { 9543 DM dm; 9544 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 9545 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 9546 } 9547 PetscFunctionReturn(0); 9548 } 9549 9550 /*@ 9551 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 9552 9553 Input Parameter: 9554 . coloring - the MatFDColoring object 9555 9556 Developer Notes: 9557 this routine exists because the PETSc Mat library does not know about the DM objects 9558 9559 Level: advanced 9560 9561 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 9562 @*/ 9563 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 9564 { 9565 PetscFunctionBegin; 9566 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 9567 PetscFunctionReturn(0); 9568 } 9569 9570 /*@ 9571 DMGetCompatibility - determine if two DMs are compatible 9572 9573 Collective 9574 9575 Input Parameters: 9576 + dm1 - the first DM 9577 - dm2 - the second DM 9578 9579 Output Parameters: 9580 + compatible - whether or not the two DMs are compatible 9581 - set - whether or not the compatible value was set 9582 9583 Notes: 9584 Two DMs are deemed compatible if they represent the same parallel decomposition 9585 of the same topology. This implies that the section (field data) on one 9586 "makes sense" with respect to the topology and parallel decomposition of the other. 9587 Loosely speaking, compatible DMs represent the same domain and parallel 9588 decomposition, but hold different data. 9589 9590 Typically, one would confirm compatibility if intending to simultaneously iterate 9591 over a pair of vectors obtained from different DMs. 9592 9593 For example, two DMDA objects are compatible if they have the same local 9594 and global sizes and the same stencil width. They can have different numbers 9595 of degrees of freedom per node. Thus, one could use the node numbering from 9596 either DM in bounds for a loop over vectors derived from either DM. 9597 9598 Consider the operation of summing data living on a 2-dof DMDA to data living 9599 on a 1-dof DMDA, which should be compatible, as in the following snippet. 9600 .vb 9601 ... 9602 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 9603 if (set && compatible) { 9604 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 9605 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 9606 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 9607 for (j=y; j<y+n; ++j) { 9608 for (i=x; i<x+m, ++i) { 9609 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 9610 } 9611 } 9612 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 9613 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 9614 } else { 9615 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 9616 } 9617 ... 9618 .ve 9619 9620 Checking compatibility might be expensive for a given implementation of DM, 9621 or might be impossible to unambiguously confirm or deny. For this reason, 9622 this function may decline to determine compatibility, and hence users should 9623 always check the "set" output parameter. 9624 9625 A DM is always compatible with itself. 9626 9627 In the current implementation, DMs which live on "unequal" communicators 9628 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 9629 incompatible. 9630 9631 This function is labeled "Collective," as information about all subdomains 9632 is required on each rank. However, in DM implementations which store all this 9633 information locally, this function may be merely "Logically Collective". 9634 9635 Developer Notes: 9636 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 9637 iff B is compatible with A. Thus, this function checks the implementations 9638 of both dm and dmc (if they are of different types), attempting to determine 9639 compatibility. It is left to DM implementers to ensure that symmetry is 9640 preserved. The simplest way to do this is, when implementing type-specific 9641 logic for this function, is to check for existing logic in the implementation 9642 of other DM types and let *set = PETSC_FALSE if found. 9643 9644 Level: advanced 9645 9646 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 9647 @*/ 9648 9649 PetscErrorCode DMGetCompatibility(DM dm1,DM dm2,PetscBool *compatible,PetscBool *set) 9650 { 9651 PetscErrorCode ierr; 9652 PetscMPIInt compareResult; 9653 DMType type,type2; 9654 PetscBool sameType; 9655 9656 PetscFunctionBegin; 9657 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 9658 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 9659 9660 /* Declare a DM compatible with itself */ 9661 if (dm1 == dm2) { 9662 *set = PETSC_TRUE; 9663 *compatible = PETSC_TRUE; 9664 PetscFunctionReturn(0); 9665 } 9666 9667 /* Declare a DM incompatible with a DM that lives on an "unequal" 9668 communicator. Note that this does not preclude compatibility with 9669 DMs living on "congruent" or "similar" communicators, but this must be 9670 determined by the implementation-specific logic */ 9671 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm1),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRMPI(ierr); 9672 if (compareResult == MPI_UNEQUAL) { 9673 *set = PETSC_TRUE; 9674 *compatible = PETSC_FALSE; 9675 PetscFunctionReturn(0); 9676 } 9677 9678 /* Pass to the implementation-specific routine, if one exists. */ 9679 if (dm1->ops->getcompatibility) { 9680 ierr = (*dm1->ops->getcompatibility)(dm1,dm2,compatible,set);CHKERRQ(ierr); 9681 if (*set) PetscFunctionReturn(0); 9682 } 9683 9684 /* If dm1 and dm2 are of different types, then attempt to check compatibility 9685 with an implementation of this function from dm2 */ 9686 ierr = DMGetType(dm1,&type);CHKERRQ(ierr); 9687 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 9688 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 9689 if (!sameType && dm2->ops->getcompatibility) { 9690 ierr = (*dm2->ops->getcompatibility)(dm2,dm1,compatible,set);CHKERRQ(ierr); /* Note argument order */ 9691 } else { 9692 *set = PETSC_FALSE; 9693 } 9694 PetscFunctionReturn(0); 9695 } 9696 9697 /*@C 9698 DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance. 9699 9700 Logically Collective on DM 9701 9702 Input Parameters: 9703 + DM - the DM 9704 . f - the monitor function 9705 . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired) 9706 - monitordestroy - [optional] routine that frees monitor context (may be NULL) 9707 9708 Options Database Keys: 9709 - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but 9710 does not cancel those set via the options database. 9711 9712 Notes: 9713 Several different monitoring routines may be set by calling 9714 DMMonitorSet() multiple times; all will be called in the 9715 order in which they were set. 9716 9717 Fortran Notes: 9718 Only a single monitor function can be set for each DM object 9719 9720 Level: intermediate 9721 9722 .seealso: DMMonitorCancel() 9723 @*/ 9724 PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**)) 9725 { 9726 PetscInt m; 9727 PetscErrorCode ierr; 9728 9729 PetscFunctionBegin; 9730 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9731 for (m = 0; m < dm->numbermonitors; ++m) { 9732 PetscBool identical; 9733 9734 ierr = PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);CHKERRQ(ierr); 9735 if (identical) PetscFunctionReturn(0); 9736 } 9737 PetscCheckFalse(dm->numbermonitors >= MAXDMMONITORS,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 9738 dm->monitor[dm->numbermonitors] = f; 9739 dm->monitordestroy[dm->numbermonitors] = monitordestroy; 9740 dm->monitorcontext[dm->numbermonitors++] = (void *) mctx; 9741 PetscFunctionReturn(0); 9742 } 9743 9744 /*@ 9745 DMMonitorCancel - Clears all the monitor functions for a DM object. 9746 9747 Logically Collective on DM 9748 9749 Input Parameter: 9750 . dm - the DM 9751 9752 Options Database Key: 9753 . -dm_monitor_cancel - cancels all monitors that have been hardwired 9754 into a code by calls to DMonitorSet(), but does not cancel those 9755 set via the options database 9756 9757 Notes: 9758 There is no way to clear one specific monitor from a DM object. 9759 9760 Level: intermediate 9761 9762 .seealso: DMMonitorSet() 9763 @*/ 9764 PetscErrorCode DMMonitorCancel(DM dm) 9765 { 9766 PetscErrorCode ierr; 9767 PetscInt m; 9768 9769 PetscFunctionBegin; 9770 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9771 for (m = 0; m < dm->numbermonitors; ++m) { 9772 if (dm->monitordestroy[m]) {ierr = (*dm->monitordestroy[m])(&dm->monitorcontext[m]);CHKERRQ(ierr);} 9773 } 9774 dm->numbermonitors = 0; 9775 PetscFunctionReturn(0); 9776 } 9777 9778 /*@C 9779 DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 9780 9781 Collective on DM 9782 9783 Input Parameters: 9784 + dm - DM object you wish to monitor 9785 . name - the monitor type one is seeking 9786 . help - message indicating what monitoring is done 9787 . manual - manual page for the monitor 9788 . monitor - the monitor function 9789 - 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 9790 9791 Output Parameter: 9792 . flg - Flag set if the monitor was created 9793 9794 Level: developer 9795 9796 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 9797 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 9798 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 9799 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 9800 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 9801 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 9802 PetscOptionsFList(), PetscOptionsEList() 9803 @*/ 9804 PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg) 9805 { 9806 PetscViewer viewer; 9807 PetscViewerFormat format; 9808 PetscErrorCode ierr; 9809 9810 PetscFunctionBegin; 9811 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9812 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);CHKERRQ(ierr); 9813 if (*flg) { 9814 PetscViewerAndFormat *vf; 9815 9816 ierr = PetscViewerAndFormatCreate(viewer, format, &vf);CHKERRQ(ierr); 9817 ierr = PetscObjectDereference((PetscObject) viewer);CHKERRQ(ierr); 9818 if (monitorsetup) {ierr = (*monitorsetup)(dm, vf);CHKERRQ(ierr);} 9819 ierr = DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr); 9820 } 9821 PetscFunctionReturn(0); 9822 } 9823 9824 /*@ 9825 DMMonitor - runs the user provided monitor routines, if they exist 9826 9827 Collective on DM 9828 9829 Input Parameters: 9830 . dm - The DM 9831 9832 Level: developer 9833 9834 .seealso: DMMonitorSet() 9835 @*/ 9836 PetscErrorCode DMMonitor(DM dm) 9837 { 9838 PetscInt m; 9839 PetscErrorCode ierr; 9840 9841 PetscFunctionBegin; 9842 if (!dm) PetscFunctionReturn(0); 9843 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9844 for (m = 0; m < dm->numbermonitors; ++m) { 9845 ierr = (*dm->monitor[m])(dm, dm->monitorcontext[m]);CHKERRQ(ierr); 9846 } 9847 PetscFunctionReturn(0); 9848 } 9849 9850 /*@ 9851 DMComputeError - Computes the error assuming the user has given exact solution functions 9852 9853 Collective on DM 9854 9855 Input Parameters: 9856 + dm - The DM 9857 - sol - The solution vector 9858 9859 Input/Output Parameter: 9860 . errors - An array of length Nf, the number of fields, or NULL for no output; on output 9861 contains the error in each field 9862 9863 Output Parameter: 9864 . errorVec - A vector to hold the cellwise error (may be NULL) 9865 9866 Note: The exact solutions come from the PetscDS object, and the time comes from DMGetOutputSequenceNumber(). 9867 9868 Level: developer 9869 9870 .seealso: DMMonitorSet(), DMGetRegionNumDS(), PetscDSGetExactSolution(), DMGetOutputSequenceNumber() 9871 @*/ 9872 PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec) 9873 { 9874 PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 9875 void **ctxs; 9876 PetscReal time; 9877 PetscInt Nf, f, Nds, s; 9878 PetscErrorCode ierr; 9879 9880 PetscFunctionBegin; 9881 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9882 ierr = PetscCalloc2(Nf, &exactSol, Nf, &ctxs);CHKERRQ(ierr); 9883 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 9884 for (s = 0; s < Nds; ++s) { 9885 PetscDS ds; 9886 DMLabel label; 9887 IS fieldIS; 9888 const PetscInt *fields; 9889 PetscInt dsNf; 9890 9891 ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 9892 ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 9893 if (fieldIS) {ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr);} 9894 for (f = 0; f < dsNf; ++f) { 9895 const PetscInt field = fields[f]; 9896 ierr = PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]);CHKERRQ(ierr); 9897 } 9898 if (fieldIS) {ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr);} 9899 } 9900 for (f = 0; f < Nf; ++f) { 9901 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); 9902 } 9903 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 9904 if (errors) {ierr = DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors);CHKERRQ(ierr);} 9905 if (errorVec) { 9906 DM edm; 9907 DMPolytopeType ct; 9908 PetscBool simplex; 9909 PetscInt dim, cStart, Nf; 9910 9911 ierr = DMClone(dm, &edm);CHKERRQ(ierr); 9912 ierr = DMGetDimension(edm, &dim);CHKERRQ(ierr); 9913 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 9914 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 9915 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 9916 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9917 for (f = 0; f < Nf; ++f) { 9918 PetscFE fe, efe; 9919 PetscQuadrature q; 9920 const char *name; 9921 9922 ierr = DMGetField(dm, f, NULL, (PetscObject *) &fe);CHKERRQ(ierr); 9923 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe);CHKERRQ(ierr); 9924 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 9925 ierr = PetscObjectSetName((PetscObject) efe, name);CHKERRQ(ierr); 9926 ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 9927 ierr = PetscFESetQuadrature(efe, q);CHKERRQ(ierr); 9928 ierr = DMSetField(edm, f, NULL, (PetscObject) efe);CHKERRQ(ierr); 9929 ierr = PetscFEDestroy(&efe);CHKERRQ(ierr); 9930 } 9931 ierr = DMCreateDS(edm);CHKERRQ(ierr); 9932 9933 ierr = DMCreateGlobalVector(edm, errorVec);CHKERRQ(ierr); 9934 ierr = PetscObjectSetName((PetscObject) *errorVec, "Error");CHKERRQ(ierr); 9935 ierr = DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec);CHKERRQ(ierr); 9936 ierr = DMDestroy(&edm);CHKERRQ(ierr); 9937 } 9938 ierr = PetscFree2(exactSol, ctxs);CHKERRQ(ierr); 9939 PetscFunctionReturn(0); 9940 } 9941 9942 /*@ 9943 DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this DM 9944 9945 Not collective 9946 9947 Input Parameter: 9948 . dm - The DM 9949 9950 Output Parameter: 9951 . numAux - The number of auxiliary data vectors 9952 9953 Level: advanced 9954 9955 .seealso: DMGetAuxiliaryLabels(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 9956 @*/ 9957 PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux) 9958 { 9959 PetscErrorCode ierr; 9960 9961 PetscFunctionBegin; 9962 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9963 ierr = PetscHMapAuxGetSize(dm->auxData, numAux);CHKERRQ(ierr); 9964 PetscFunctionReturn(0); 9965 } 9966 9967 /*@ 9968 DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value 9969 9970 Not collective 9971 9972 Input Parameters: 9973 + dm - The DM 9974 . label - The DMLabel 9975 - value - The label value indicating the region 9976 9977 Output Parameter: 9978 . aux - The Vec holding auxiliary field data 9979 9980 Note: If no auxiliary vector is found for this (label, value), (NULL, 0) is checked as well. 9981 9982 Level: advanced 9983 9984 .seealso: DMSetAuxiliaryVec(), DMGetNumAuxiliaryVec() 9985 @*/ 9986 PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, Vec *aux) 9987 { 9988 PetscHashAuxKey key, wild = {NULL, 0}; 9989 PetscBool has; 9990 PetscErrorCode ierr; 9991 9992 PetscFunctionBegin; 9993 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9994 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 9995 key.label = label; 9996 key.value = value; 9997 ierr = PetscHMapAuxHas(dm->auxData, key, &has);CHKERRQ(ierr); 9998 if (has) {ierr = PetscHMapAuxGet(dm->auxData, key, aux);CHKERRQ(ierr);} 9999 else {ierr = PetscHMapAuxGet(dm->auxData, wild, aux);CHKERRQ(ierr);} 10000 PetscFunctionReturn(0); 10001 } 10002 10003 /*@ 10004 DMSetAuxiliaryVec - Set the auxiliary vector for region specified by the given label and value 10005 10006 Not collective 10007 10008 Input Parameters: 10009 + dm - The DM 10010 . label - The DMLabel 10011 . value - The label value indicating the region 10012 - aux - The Vec holding auxiliary field data 10013 10014 Level: advanced 10015 10016 .seealso: DMGetAuxiliaryVec() 10017 @*/ 10018 PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, Vec aux) 10019 { 10020 Vec old; 10021 PetscHashAuxKey key; 10022 PetscErrorCode ierr; 10023 10024 PetscFunctionBegin; 10025 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10026 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 10027 key.label = label; 10028 key.value = value; 10029 ierr = PetscHMapAuxGet(dm->auxData, key, &old);CHKERRQ(ierr); 10030 ierr = PetscObjectReference((PetscObject) aux);CHKERRQ(ierr); 10031 ierr = PetscObjectDereference((PetscObject) old);CHKERRQ(ierr); 10032 if (!aux) {ierr = PetscHMapAuxDel(dm->auxData, key);CHKERRQ(ierr);} 10033 else {ierr = PetscHMapAuxSet(dm->auxData, key, aux);CHKERRQ(ierr);} 10034 PetscFunctionReturn(0); 10035 } 10036 10037 /*@C 10038 DMGetAuxiliaryLabels - Get the labels and values for all auxiliary vectors in this DM 10039 10040 Not collective 10041 10042 Input Parameter: 10043 . dm - The DM 10044 10045 Output Parameters: 10046 + labels - The DMLabels for each Vec 10047 - values - The label values for each Vec 10048 10049 Note: The arrays passed in must be at least as large as DMGetNumAuxiliaryVec(). 10050 10051 Level: advanced 10052 10053 .seealso: DMGetNumAuxiliaryVec(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 10054 @*/ 10055 PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[]) 10056 { 10057 PetscHashAuxKey *keys; 10058 PetscInt n, i, off = 0; 10059 PetscErrorCode ierr; 10060 10061 PetscFunctionBegin; 10062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10063 PetscValidPointer(labels, 2); 10064 PetscValidPointer(values, 3); 10065 ierr = DMGetNumAuxiliaryVec(dm, &n);CHKERRQ(ierr); 10066 ierr = PetscMalloc1(n, &keys);CHKERRQ(ierr); 10067 ierr = PetscHMapAuxGetKeys(dm->auxData, &off, keys);CHKERRQ(ierr); 10068 for (i = 0; i < n; ++i) {labels[i] = keys[i].label; values[i] = keys[i].value;} 10069 ierr = PetscFree(keys);CHKERRQ(ierr); 10070 PetscFunctionReturn(0); 10071 } 10072 10073 /*@ 10074 DMCopyAuxiliaryVec - Copy the auxiliary data to a new DM 10075 10076 Not collective 10077 10078 Input Parameter: 10079 . dm - The DM 10080 10081 Output Parameter: 10082 . dmNew - The new DM, now with the same auxiliary data 10083 10084 Level: advanced 10085 10086 .seealso: DMGetNumAuxiliaryVec(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 10087 @*/ 10088 PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew) 10089 { 10090 PetscErrorCode ierr; 10091 10092 PetscFunctionBegin; 10093 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10094 ierr = PetscHMapAuxDestroy(&dmNew->auxData);CHKERRQ(ierr); 10095 ierr = PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData);CHKERRQ(ierr); 10096 PetscFunctionReturn(0); 10097 } 10098 10099 /*@C 10100 DMPolytopeMatchOrientation - Determine an orientation that takes the source face arrangement to the target face arrangement 10101 10102 Not collective 10103 10104 Input Parameters: 10105 + ct - The DMPolytopeType 10106 . sourceCone - The source arrangement of faces 10107 - targetCone - The target arrangement of faces 10108 10109 Output Parameters: 10110 + ornt - The orientation which will take the source arrangement to the target arrangement 10111 - found - Flag indicating that a suitable orientation was found 10112 10113 Level: advanced 10114 10115 .seealso: DMPolytopeGetOrientation(), DMPolytopeMatchVertexOrientation() 10116 @*/ 10117 PetscErrorCode DMPolytopeMatchOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt, PetscBool *found) 10118 { 10119 const PetscInt cS = DMPolytopeTypeGetConeSize(ct); 10120 const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct)/2; 10121 PetscInt o, c; 10122 10123 PetscFunctionBegin; 10124 if (!nO) {*ornt = 0; *found = PETSC_TRUE; PetscFunctionReturn(0);} 10125 for (o = -nO; o < nO; ++o) { 10126 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o); 10127 10128 for (c = 0; c < cS; ++c) if (sourceCone[arr[c*2]] != targetCone[c]) break; 10129 if (c == cS) {*ornt = o; break;} 10130 } 10131 *found = o == nO ? PETSC_FALSE : PETSC_TRUE; 10132 PetscFunctionReturn(0); 10133 } 10134 10135 /*@C 10136 DMPolytopeGetOrientation - Determine an orientation that takes the source face arrangement to the target face arrangement 10137 10138 Not collective 10139 10140 Input Parameters: 10141 + ct - The DMPolytopeType 10142 . sourceCone - The source arrangement of faces 10143 - targetCone - The target arrangement of faces 10144 10145 Output Parameters: 10146 . ornt - The orientation which will take the source arrangement to the target arrangement 10147 10148 Note: This function will fail if no suitable orientation can be found. 10149 10150 Level: advanced 10151 10152 .seealso: DMPolytopeMatchOrientation(), DMPolytopeGetVertexOrientation() 10153 @*/ 10154 PetscErrorCode DMPolytopeGetOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt) 10155 { 10156 PetscBool found; 10157 PetscErrorCode ierr; 10158 10159 PetscFunctionBegin; 10160 ierr = DMPolytopeMatchOrientation(ct, sourceCone, targetCone, ornt, &found);CHKERRQ(ierr); 10161 PetscCheckFalse(!found,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]); 10162 PetscFunctionReturn(0); 10163 } 10164 10165 /*@C 10166 DMPolytopeMatchVertexOrientation - Determine an orientation that takes the source vertex arrangement to the target vertex arrangement 10167 10168 Not collective 10169 10170 Input Parameters: 10171 + ct - The DMPolytopeType 10172 . sourceVert - The source arrangement of vertices 10173 - targetVert - The target arrangement of vertices 10174 10175 Output Parameters: 10176 + ornt - The orientation which will take the source arrangement to the target arrangement 10177 - found - Flag indicating that a suitable orientation was found 10178 10179 Level: advanced 10180 10181 .seealso: DMPolytopeGetOrientation(), DMPolytopeMatchOrientation() 10182 @*/ 10183 PetscErrorCode DMPolytopeMatchVertexOrientation(DMPolytopeType ct, const PetscInt sourceVert[], const PetscInt targetVert[], PetscInt *ornt, PetscBool *found) 10184 { 10185 const PetscInt cS = DMPolytopeTypeGetNumVertices(ct); 10186 const PetscInt nO = DMPolytopeTypeGetNumArrangments(ct)/2; 10187 PetscInt o, c; 10188 10189 PetscFunctionBegin; 10190 if (!nO) {*ornt = 0; *found = PETSC_TRUE; PetscFunctionReturn(0);} 10191 for (o = -nO; o < nO; ++o) { 10192 const PetscInt *arr = DMPolytopeTypeGetVertexArrangment(ct, o); 10193 10194 for (c = 0; c < cS; ++c) if (sourceVert[arr[c]] != targetVert[c]) break; 10195 if (c == cS) {*ornt = o; break;} 10196 } 10197 *found = o == nO ? PETSC_FALSE : PETSC_TRUE; 10198 PetscFunctionReturn(0); 10199 } 10200 10201 /*@C 10202 DMPolytopeGetVertexOrientation - Determine an orientation that takes the source vertex arrangement to the target vertex arrangement 10203 10204 Not collective 10205 10206 Input Parameters: 10207 + ct - The DMPolytopeType 10208 . sourceCone - The source arrangement of vertices 10209 - targetCone - The target arrangement of vertices 10210 10211 Output Parameters: 10212 . ornt - The orientation which will take the source arrangement to the target arrangement 10213 10214 Note: This function will fail if no suitable orientation can be found. 10215 10216 Level: advanced 10217 10218 .seealso: DMPolytopeMatchVertexOrientation(), DMPolytopeGetOrientation() 10219 @*/ 10220 PetscErrorCode DMPolytopeGetVertexOrientation(DMPolytopeType ct, const PetscInt sourceCone[], const PetscInt targetCone[], PetscInt *ornt) 10221 { 10222 PetscBool found; 10223 PetscErrorCode ierr; 10224 10225 PetscFunctionBegin; 10226 ierr = DMPolytopeMatchVertexOrientation(ct, sourceCone, targetCone, ornt, &found);CHKERRQ(ierr); 10227 PetscCheckFalse(!found,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find orientation for %s", DMPolytopeTypes[ct]); 10228 PetscFunctionReturn(0); 10229 } 10230 10231 /*@C 10232 DMPolytopeInCellTest - Check whether a point lies inside the reference cell of given type 10233 10234 Not collective 10235 10236 Input Parameters: 10237 + ct - The DMPolytopeType 10238 - point - Coordinates of the point 10239 10240 Output Parameters: 10241 . inside - Flag indicating whether the point is inside the reference cell of given type 10242 10243 Level: advanced 10244 10245 .seealso: DMLocatePoints() 10246 @*/ 10247 PetscErrorCode DMPolytopeInCellTest(DMPolytopeType ct, const PetscReal point[], PetscBool *inside) 10248 { 10249 PetscReal sum = 0.0; 10250 PetscInt d; 10251 10252 PetscFunctionBegin; 10253 *inside = PETSC_TRUE; 10254 switch (ct) { 10255 case DM_POLYTOPE_TRIANGLE: 10256 case DM_POLYTOPE_TETRAHEDRON: 10257 for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) { 10258 if (point[d] < -1.0) {*inside = PETSC_FALSE; break;} 10259 sum += point[d]; 10260 } 10261 if (sum > PETSC_SMALL) {*inside = PETSC_FALSE; break;} 10262 break; 10263 case DM_POLYTOPE_QUADRILATERAL: 10264 case DM_POLYTOPE_HEXAHEDRON: 10265 for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) 10266 if (PetscAbsReal(point[d]) > 1.+PETSC_SMALL) {*inside = PETSC_FALSE; break;} 10267 break; 10268 default: 10269 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]); 10270 } 10271 PetscFunctionReturn(0); 10272 } 10273