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