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