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