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