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