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