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