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