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