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