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