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