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