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", "interior_ghost_cell", "unknown", "invalid", "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, 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 Collective on DM 5513 5514 Input Parameters: 5515 + dm - The DM 5516 - time - The time 5517 5518 Output Parameters: 5519 + u - The vector will be filled with exact solution values, or NULL 5520 - u_t - The vector will be filled with the time derivative of exact solution values, or NULL 5521 5522 Note: The user must call PetscDSSetExactSolution() beforehand 5523 5524 Level: developer 5525 5526 .seealso: PetscDSSetExactSolution() 5527 @*/ 5528 PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t) 5529 { 5530 PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx); 5531 void **ectxs; 5532 PetscInt Nf, Nds, s; 5533 PetscErrorCode ierr; 5534 5535 PetscFunctionBegin; 5536 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5537 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 5538 if (u_t) PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4); 5539 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5540 ierr = PetscMalloc2(Nf, &exacts, Nf, &ectxs);CHKERRQ(ierr); 5541 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5542 for (s = 0; s < Nds; ++s) { 5543 PetscDS ds; 5544 DMLabel label; 5545 IS fieldIS; 5546 const PetscInt *fields, id = 1; 5547 PetscInt dsNf, f; 5548 5549 ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 5550 ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 5551 ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr); 5552 ierr = PetscArrayzero(exacts, Nf);CHKERRQ(ierr); 5553 ierr = PetscArrayzero(ectxs, Nf);CHKERRQ(ierr); 5554 if (u) { 5555 for (f = 0; f < dsNf; ++f) { 5556 const PetscInt field = fields[f]; 5557 ierr = PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr); 5558 } 5559 ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 5560 if (label) { 5561 ierr = DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); 5562 } else { 5563 ierr = DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); 5564 } 5565 } 5566 if (u_t) { 5567 ierr = PetscArrayzero(exacts, Nf);CHKERRQ(ierr); 5568 ierr = PetscArrayzero(ectxs, Nf);CHKERRQ(ierr); 5569 for (f = 0; f < dsNf; ++f) { 5570 const PetscInt field = fields[f]; 5571 ierr = PetscDSGetExactSolutionTimeDerivative(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr); 5572 } 5573 ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 5574 if (label) { 5575 ierr = DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u_t);CHKERRQ(ierr); 5576 } else { 5577 ierr = DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u_t);CHKERRQ(ierr); 5578 } 5579 } 5580 } 5581 if (u) { 5582 ierr = PetscObjectSetName((PetscObject) u, "Exact Solution");CHKERRQ(ierr); 5583 ierr = PetscObjectSetOptionsPrefix((PetscObject) u, "exact_");CHKERRQ(ierr); 5584 } 5585 if (u_t) { 5586 ierr = PetscObjectSetName((PetscObject) u, "Exact Solution Time Derivative");CHKERRQ(ierr); 5587 ierr = PetscObjectSetOptionsPrefix((PetscObject) u_t, "exact_t_");CHKERRQ(ierr); 5588 } 5589 ierr = PetscFree2(exacts, ectxs);CHKERRQ(ierr); 5590 PetscFunctionReturn(0); 5591 } 5592 5593 /*@ 5594 DMCopyDS - Copy the discrete systems for the DM into another DM 5595 5596 Collective on dm 5597 5598 Input Parameter: 5599 . dm - The DM 5600 5601 Output Parameter: 5602 . newdm - The DM 5603 5604 Level: advanced 5605 5606 .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5607 @*/ 5608 PetscErrorCode DMCopyDS(DM dm, DM newdm) 5609 { 5610 PetscInt Nds, s; 5611 PetscErrorCode ierr; 5612 5613 PetscFunctionBegin; 5614 if (dm == newdm) PetscFunctionReturn(0); 5615 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5616 ierr = DMClearDS(newdm);CHKERRQ(ierr); 5617 for (s = 0; s < Nds; ++s) { 5618 DMLabel label; 5619 IS fields; 5620 PetscDS ds; 5621 PetscInt Nbd, bd; 5622 5623 ierr = DMGetRegionNumDS(dm, s, &label, &fields, &ds);CHKERRQ(ierr); 5624 ierr = DMSetRegionDS(newdm, label, fields, ds);CHKERRQ(ierr); 5625 ierr = PetscDSGetNumBoundary(ds, &Nbd);CHKERRQ(ierr); 5626 for (bd = 0; bd < Nbd; ++bd) { 5627 const char *labelname, *name; 5628 PetscInt field; 5629 5630 /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */ 5631 ierr = PetscDSGetBoundary(ds, bd, NULL, &name, &labelname, &field, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5632 ierr = DMCompleteBoundaryLabel_Internal(newdm, ds, field, bd, labelname);CHKERRQ(ierr); 5633 } 5634 } 5635 PetscFunctionReturn(0); 5636 } 5637 5638 /*@ 5639 DMCopyDisc - Copy the fields and discrete systems for the DM into another DM 5640 5641 Collective on dm 5642 5643 Input Parameter: 5644 . dm - The DM 5645 5646 Output Parameter: 5647 . newdm - The DM 5648 5649 Level: advanced 5650 5651 .seealso: DMCopyFields(), DMCopyDS() 5652 @*/ 5653 PetscErrorCode DMCopyDisc(DM dm, DM newdm) 5654 { 5655 PetscErrorCode ierr; 5656 5657 PetscFunctionBegin; 5658 ierr = DMCopyFields(dm, newdm);CHKERRQ(ierr); 5659 ierr = DMCopyDS(dm, newdm);CHKERRQ(ierr); 5660 PetscFunctionReturn(0); 5661 } 5662 5663 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 5664 { 5665 DM dm_coord,dmc_coord; 5666 PetscErrorCode ierr; 5667 Vec coords,ccoords; 5668 Mat inject; 5669 PetscFunctionBegin; 5670 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5671 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 5672 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5673 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 5674 if (coords && !ccoords) { 5675 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 5676 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5677 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 5678 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 5679 ierr = MatDestroy(&inject);CHKERRQ(ierr); 5680 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 5681 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5682 } 5683 PetscFunctionReturn(0); 5684 } 5685 5686 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 5687 { 5688 DM dm_coord,subdm_coord; 5689 PetscErrorCode ierr; 5690 Vec coords,ccoords,clcoords; 5691 VecScatter *scat_i,*scat_g; 5692 PetscFunctionBegin; 5693 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5694 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 5695 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5696 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 5697 if (coords && !ccoords) { 5698 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 5699 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5700 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 5701 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 5702 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 5703 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5704 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5705 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5706 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5707 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 5708 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 5709 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 5710 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 5711 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5712 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 5713 ierr = PetscFree(scat_i);CHKERRQ(ierr); 5714 ierr = PetscFree(scat_g);CHKERRQ(ierr); 5715 } 5716 PetscFunctionReturn(0); 5717 } 5718 5719 /*@ 5720 DMGetDimension - Return the topological dimension of the DM 5721 5722 Not collective 5723 5724 Input Parameter: 5725 . dm - The DM 5726 5727 Output Parameter: 5728 . dim - The topological dimension 5729 5730 Level: beginner 5731 5732 .seealso: DMSetDimension(), DMCreate() 5733 @*/ 5734 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 5735 { 5736 PetscFunctionBegin; 5737 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5738 PetscValidIntPointer(dim, 2); 5739 *dim = dm->dim; 5740 PetscFunctionReturn(0); 5741 } 5742 5743 /*@ 5744 DMSetDimension - Set the topological dimension of the DM 5745 5746 Collective on dm 5747 5748 Input Parameters: 5749 + dm - The DM 5750 - dim - The topological dimension 5751 5752 Level: beginner 5753 5754 .seealso: DMGetDimension(), DMCreate() 5755 @*/ 5756 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 5757 { 5758 PetscDS ds; 5759 PetscErrorCode ierr; 5760 5761 PetscFunctionBegin; 5762 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5763 PetscValidLogicalCollectiveInt(dm, dim, 2); 5764 dm->dim = dim; 5765 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5766 if (ds->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(ds, dm->dim);CHKERRQ(ierr);} 5767 PetscFunctionReturn(0); 5768 } 5769 5770 /*@ 5771 DMGetDimPoints - Get the half-open interval for all points of a given dimension 5772 5773 Collective on dm 5774 5775 Input Parameters: 5776 + dm - the DM 5777 - dim - the dimension 5778 5779 Output Parameters: 5780 + pStart - The first point of the given dimension 5781 - pEnd - The first point following points of the given dimension 5782 5783 Note: 5784 The points are vertices in the Hasse diagram encoding the topology. This is explained in 5785 https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme, 5786 then the interval is empty. 5787 5788 Level: intermediate 5789 5790 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 5791 @*/ 5792 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5793 { 5794 PetscInt d; 5795 PetscErrorCode ierr; 5796 5797 PetscFunctionBegin; 5798 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5799 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 5800 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 5801 if (!dm->ops->getdimpoints) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DM type %s does not implement DMGetDimPoints",((PetscObject)dm)->type_name); 5802 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 5803 PetscFunctionReturn(0); 5804 } 5805 5806 /*@ 5807 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 5808 5809 Collective on dm 5810 5811 Input Parameters: 5812 + dm - the DM 5813 - c - coordinate vector 5814 5815 Notes: 5816 The coordinates do include those for ghost points, which are in the local vector. 5817 5818 The vector c should be destroyed by the caller. 5819 5820 Level: intermediate 5821 5822 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5823 @*/ 5824 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 5825 { 5826 PetscErrorCode ierr; 5827 5828 PetscFunctionBegin; 5829 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5830 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5831 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5832 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5833 dm->coordinates = c; 5834 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5835 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5836 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5837 PetscFunctionReturn(0); 5838 } 5839 5840 /*@ 5841 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 5842 5843 Not collective 5844 5845 Input Parameters: 5846 + dm - the DM 5847 - c - coordinate vector 5848 5849 Notes: 5850 The coordinates of ghost points can be set using DMSetCoordinates() 5851 followed by DMGetCoordinatesLocal(). This is intended to enable the 5852 setting of ghost coordinates outside of the domain. 5853 5854 The vector c should be destroyed by the caller. 5855 5856 Level: intermediate 5857 5858 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 5859 @*/ 5860 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 5861 { 5862 PetscErrorCode ierr; 5863 5864 PetscFunctionBegin; 5865 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5866 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5867 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5868 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5869 5870 dm->coordinatesLocal = c; 5871 5872 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5873 PetscFunctionReturn(0); 5874 } 5875 5876 /*@ 5877 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 5878 5879 Collective on dm 5880 5881 Input Parameter: 5882 . dm - the DM 5883 5884 Output Parameter: 5885 . c - global coordinate vector 5886 5887 Note: 5888 This is a borrowed reference, so the user should NOT destroy this vector 5889 5890 Each process has only the local coordinates (does NOT have the ghost coordinates). 5891 5892 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5893 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5894 5895 Level: intermediate 5896 5897 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5898 @*/ 5899 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 5900 { 5901 PetscErrorCode ierr; 5902 5903 PetscFunctionBegin; 5904 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5905 PetscValidPointer(c,2); 5906 if (!dm->coordinates && dm->coordinatesLocal) { 5907 DM cdm = NULL; 5908 PetscBool localized; 5909 5910 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5911 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 5912 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5913 /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */ 5914 if (localized) { 5915 PetscInt cdim; 5916 5917 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5918 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5919 } 5920 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 5921 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5922 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5923 } 5924 *c = dm->coordinates; 5925 PetscFunctionReturn(0); 5926 } 5927 5928 /*@ 5929 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 5930 5931 Collective on dm 5932 5933 Input Parameter: 5934 . dm - the DM 5935 5936 Level: advanced 5937 5938 .seealso: DMGetCoordinatesLocalNoncollective() 5939 @*/ 5940 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 5941 { 5942 PetscErrorCode ierr; 5943 5944 PetscFunctionBegin; 5945 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5946 if (!dm->coordinatesLocal && dm->coordinates) { 5947 DM cdm = NULL; 5948 PetscBool localized; 5949 5950 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5951 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 5952 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5953 /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */ 5954 if (localized) { 5955 PetscInt cdim; 5956 5957 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5958 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5959 } 5960 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 5961 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5962 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5963 } 5964 PetscFunctionReturn(0); 5965 } 5966 5967 /*@ 5968 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 5969 5970 Collective on dm 5971 5972 Input Parameter: 5973 . dm - the DM 5974 5975 Output Parameter: 5976 . c - coordinate vector 5977 5978 Note: 5979 This is a borrowed reference, so the user should NOT destroy this vector 5980 5981 Each process has the local and ghost coordinates 5982 5983 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5984 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5985 5986 Level: intermediate 5987 5988 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 5989 @*/ 5990 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 5991 { 5992 PetscErrorCode ierr; 5993 5994 PetscFunctionBegin; 5995 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5996 PetscValidPointer(c,2); 5997 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 5998 *c = dm->coordinatesLocal; 5999 PetscFunctionReturn(0); 6000 } 6001 6002 /*@ 6003 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 6004 6005 Not collective 6006 6007 Input Parameter: 6008 . dm - the DM 6009 6010 Output Parameter: 6011 . c - coordinate vector 6012 6013 Level: advanced 6014 6015 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 6016 @*/ 6017 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 6018 { 6019 PetscFunctionBegin; 6020 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6021 PetscValidPointer(c,2); 6022 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 6023 *c = dm->coordinatesLocal; 6024 PetscFunctionReturn(0); 6025 } 6026 6027 /*@ 6028 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 6029 6030 Not collective 6031 6032 Input Parameter: 6033 + dm - the DM 6034 - p - the IS of points whose coordinates will be returned 6035 6036 Output Parameter: 6037 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 6038 - pCoord - the Vec with coordinates of points in p 6039 6040 Note: 6041 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 6042 6043 This creates a new vector, so the user SHOULD destroy this vector 6044 6045 Each process has the local and ghost coordinates 6046 6047 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6048 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6049 6050 Level: advanced 6051 6052 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 6053 @*/ 6054 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 6055 { 6056 PetscSection cs, newcs; 6057 Vec coords; 6058 const PetscScalar *arr; 6059 PetscScalar *newarr=NULL; 6060 PetscInt n; 6061 PetscErrorCode ierr; 6062 6063 PetscFunctionBegin; 6064 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6065 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 6066 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 6067 if (pCoord) PetscValidPointer(pCoord, 4); 6068 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 6069 if (!dm->coordinateDM || !dm->coordinateDM->localSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 6070 cs = dm->coordinateDM->localSection; 6071 coords = dm->coordinatesLocal; 6072 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 6073 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 6074 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 6075 if (pCoord) { 6076 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 6077 /* set array in two steps to mimic PETSC_OWN_POINTER */ 6078 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 6079 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 6080 } else { 6081 ierr = PetscFree(newarr);CHKERRQ(ierr); 6082 } 6083 if (pCoordSection) {*pCoordSection = newcs;} 6084 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 6085 PetscFunctionReturn(0); 6086 } 6087 6088 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 6089 { 6090 PetscErrorCode ierr; 6091 6092 PetscFunctionBegin; 6093 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6094 PetscValidPointer(field,2); 6095 if (!dm->coordinateField) { 6096 if (dm->ops->createcoordinatefield) { 6097 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 6098 } 6099 } 6100 *field = dm->coordinateField; 6101 PetscFunctionReturn(0); 6102 } 6103 6104 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 6105 { 6106 PetscErrorCode ierr; 6107 6108 PetscFunctionBegin; 6109 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6110 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 6111 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 6112 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 6113 dm->coordinateField = field; 6114 PetscFunctionReturn(0); 6115 } 6116 6117 /*@ 6118 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 6119 6120 Collective on dm 6121 6122 Input Parameter: 6123 . dm - the DM 6124 6125 Output Parameter: 6126 . cdm - coordinate DM 6127 6128 Level: intermediate 6129 6130 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 6131 @*/ 6132 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 6133 { 6134 PetscErrorCode ierr; 6135 6136 PetscFunctionBegin; 6137 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6138 PetscValidPointer(cdm,2); 6139 if (!dm->coordinateDM) { 6140 DM cdm; 6141 6142 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 6143 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 6144 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 6145 * until the call to CreateCoordinateDM) */ 6146 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 6147 dm->coordinateDM = cdm; 6148 } 6149 *cdm = dm->coordinateDM; 6150 PetscFunctionReturn(0); 6151 } 6152 6153 /*@ 6154 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 6155 6156 Logically Collective on dm 6157 6158 Input Parameters: 6159 + dm - the DM 6160 - cdm - coordinate DM 6161 6162 Level: intermediate 6163 6164 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 6165 @*/ 6166 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 6167 { 6168 PetscErrorCode ierr; 6169 6170 PetscFunctionBegin; 6171 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6172 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 6173 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 6174 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 6175 dm->coordinateDM = cdm; 6176 PetscFunctionReturn(0); 6177 } 6178 6179 /*@ 6180 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 6181 6182 Not Collective 6183 6184 Input Parameter: 6185 . dm - The DM object 6186 6187 Output Parameter: 6188 . dim - The embedding dimension 6189 6190 Level: intermediate 6191 6192 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 6193 @*/ 6194 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 6195 { 6196 PetscFunctionBegin; 6197 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6198 PetscValidIntPointer(dim, 2); 6199 if (dm->dimEmbed == PETSC_DEFAULT) { 6200 dm->dimEmbed = dm->dim; 6201 } 6202 *dim = dm->dimEmbed; 6203 PetscFunctionReturn(0); 6204 } 6205 6206 /*@ 6207 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 6208 6209 Not Collective 6210 6211 Input Parameters: 6212 + dm - The DM object 6213 - dim - The embedding dimension 6214 6215 Level: intermediate 6216 6217 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 6218 @*/ 6219 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 6220 { 6221 PetscDS ds; 6222 PetscErrorCode ierr; 6223 6224 PetscFunctionBegin; 6225 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6226 dm->dimEmbed = dim; 6227 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 6228 ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr); 6229 PetscFunctionReturn(0); 6230 } 6231 6232 /*@ 6233 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 6234 6235 Collective on dm 6236 6237 Input Parameter: 6238 . dm - The DM object 6239 6240 Output Parameter: 6241 . section - The PetscSection object 6242 6243 Level: intermediate 6244 6245 .seealso: DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 6246 @*/ 6247 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 6248 { 6249 DM cdm; 6250 PetscErrorCode ierr; 6251 6252 PetscFunctionBegin; 6253 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6254 PetscValidPointer(section, 2); 6255 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6256 ierr = DMGetLocalSection(cdm, section);CHKERRQ(ierr); 6257 PetscFunctionReturn(0); 6258 } 6259 6260 /*@ 6261 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 6262 6263 Not Collective 6264 6265 Input Parameters: 6266 + dm - The DM object 6267 . dim - The embedding dimension, or PETSC_DETERMINE 6268 - section - The PetscSection object 6269 6270 Level: intermediate 6271 6272 .seealso: DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 6273 @*/ 6274 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 6275 { 6276 DM cdm; 6277 PetscErrorCode ierr; 6278 6279 PetscFunctionBegin; 6280 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6281 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 6282 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6283 ierr = DMSetLocalSection(cdm, section);CHKERRQ(ierr); 6284 if (dim == PETSC_DETERMINE) { 6285 PetscInt d = PETSC_DEFAULT; 6286 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 6287 6288 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6289 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6290 pStart = PetscMax(vStart, pStart); 6291 pEnd = PetscMin(vEnd, pEnd); 6292 for (v = pStart; v < pEnd; ++v) { 6293 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 6294 if (dd) {d = dd; break;} 6295 } 6296 if (d >= 0) {ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);} 6297 } 6298 PetscFunctionReturn(0); 6299 } 6300 6301 /*@C 6302 DMGetPeriodicity - Get the description of mesh periodicity 6303 6304 Input Parameters: 6305 . dm - The DM object 6306 6307 Output Parameters: 6308 + per - Whether the DM is periodic or not 6309 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 6310 . L - If we assume the mesh is a torus, this is the length of each coordinate 6311 - bd - This describes the type of periodicity in each topological dimension 6312 6313 Level: developer 6314 6315 .seealso: DMGetPeriodicity() 6316 @*/ 6317 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 6318 { 6319 PetscFunctionBegin; 6320 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6321 if (per) *per = dm->periodic; 6322 if (L) *L = dm->L; 6323 if (maxCell) *maxCell = dm->maxCell; 6324 if (bd) *bd = dm->bdtype; 6325 PetscFunctionReturn(0); 6326 } 6327 6328 /*@C 6329 DMSetPeriodicity - Set the description of mesh periodicity 6330 6331 Input Parameters: 6332 + dm - The DM object 6333 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 6334 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 6335 . L - If we assume the mesh is a torus, this is the length of each coordinate 6336 - bd - This describes the type of periodicity in each topological dimension 6337 6338 Level: developer 6339 6340 .seealso: DMGetPeriodicity() 6341 @*/ 6342 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 6343 { 6344 PetscInt dim, d; 6345 PetscErrorCode ierr; 6346 6347 PetscFunctionBegin; 6348 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6349 PetscValidLogicalCollectiveBool(dm,per,2); 6350 if (maxCell) {PetscValidRealPointer(maxCell,3);} 6351 if (L) {PetscValidRealPointer(L,4);} 6352 if (bd) {PetscValidPointer(bd,5);} 6353 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6354 if (maxCell) { 6355 if (!dm->maxCell) {ierr = PetscMalloc1(dim, &dm->maxCell);CHKERRQ(ierr);} 6356 for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d]; 6357 } 6358 if (L) { 6359 if (!dm->L) {ierr = PetscMalloc1(dim, &dm->L);CHKERRQ(ierr);} 6360 for (d = 0; d < dim; ++d) dm->L[d] = L[d]; 6361 } 6362 if (bd) { 6363 if (!dm->bdtype) {ierr = PetscMalloc1(dim, &dm->bdtype);CHKERRQ(ierr);} 6364 for (d = 0; d < dim; ++d) dm->bdtype[d] = bd[d]; 6365 } 6366 dm->periodic = per; 6367 PetscFunctionReturn(0); 6368 } 6369 6370 /*@ 6371 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. 6372 6373 Input Parameters: 6374 + dm - The DM 6375 . in - The input coordinate point (dim numbers) 6376 - endpoint - Include the endpoint L_i 6377 6378 Output Parameter: 6379 . out - The localized coordinate point 6380 6381 Level: developer 6382 6383 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6384 @*/ 6385 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 6386 { 6387 PetscInt dim, d; 6388 PetscErrorCode ierr; 6389 6390 PetscFunctionBegin; 6391 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 6392 if (!dm->maxCell) { 6393 for (d = 0; d < dim; ++d) out[d] = in[d]; 6394 } else { 6395 if (endpoint) { 6396 for (d = 0; d < dim; ++d) { 6397 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)) { 6398 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 6399 } else { 6400 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6401 } 6402 } 6403 } else { 6404 for (d = 0; d < dim; ++d) { 6405 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6406 } 6407 } 6408 } 6409 PetscFunctionReturn(0); 6410 } 6411 6412 /* 6413 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. 6414 6415 Input Parameters: 6416 + dm - The DM 6417 . dim - The spatial dimension 6418 . anchor - The anchor point, the input point can be no more than maxCell away from it 6419 - in - The input coordinate point (dim numbers) 6420 6421 Output Parameter: 6422 . out - The localized coordinate point 6423 6424 Level: developer 6425 6426 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 6427 6428 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6429 */ 6430 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6431 { 6432 PetscInt d; 6433 6434 PetscFunctionBegin; 6435 if (!dm->maxCell) { 6436 for (d = 0; d < dim; ++d) out[d] = in[d]; 6437 } else { 6438 for (d = 0; d < dim; ++d) { 6439 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 6440 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6441 } else { 6442 out[d] = in[d]; 6443 } 6444 } 6445 } 6446 PetscFunctionReturn(0); 6447 } 6448 6449 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 6450 { 6451 PetscInt d; 6452 6453 PetscFunctionBegin; 6454 if (!dm->maxCell) { 6455 for (d = 0; d < dim; ++d) out[d] = in[d]; 6456 } else { 6457 for (d = 0; d < dim; ++d) { 6458 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 6459 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6460 } else { 6461 out[d] = in[d]; 6462 } 6463 } 6464 } 6465 PetscFunctionReturn(0); 6466 } 6467 6468 /* 6469 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. 6470 6471 Input Parameters: 6472 + dm - The DM 6473 . dim - The spatial dimension 6474 . anchor - The anchor point, the input point can be no more than maxCell away from it 6475 . in - The input coordinate delta (dim numbers) 6476 - out - The input coordinate point (dim numbers) 6477 6478 Output Parameter: 6479 . out - The localized coordinate in + out 6480 6481 Level: developer 6482 6483 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 6484 6485 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 6486 */ 6487 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6488 { 6489 PetscInt d; 6490 6491 PetscFunctionBegin; 6492 if (!dm->maxCell) { 6493 for (d = 0; d < dim; ++d) out[d] += in[d]; 6494 } else { 6495 for (d = 0; d < dim; ++d) { 6496 const PetscReal maxC = dm->maxCell[d]; 6497 6498 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) { 6499 const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6500 6501 if (PetscAbsScalar(newCoord - anchor[d]) > maxC) 6502 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])); 6503 out[d] += newCoord; 6504 } else { 6505 out[d] += in[d]; 6506 } 6507 } 6508 } 6509 PetscFunctionReturn(0); 6510 } 6511 6512 /*@ 6513 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 6514 6515 Not collective 6516 6517 Input Parameter: 6518 . dm - The DM 6519 6520 Output Parameter: 6521 areLocalized - True if localized 6522 6523 Level: developer 6524 6525 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 6526 @*/ 6527 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 6528 { 6529 DM cdm; 6530 PetscSection coordSection; 6531 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 6532 PetscBool isPlex, alreadyLocalized; 6533 PetscErrorCode ierr; 6534 6535 PetscFunctionBegin; 6536 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6537 PetscValidBoolPointer(areLocalized, 2); 6538 *areLocalized = PETSC_FALSE; 6539 6540 /* We need some generic way of refering to cells/vertices */ 6541 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6542 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 6543 if (!isPlex) PetscFunctionReturn(0); 6544 6545 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6546 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6547 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 6548 alreadyLocalized = PETSC_FALSE; 6549 for (c = cStart; c < cEnd; ++c) { 6550 if (c < sStart || c >= sEnd) continue; 6551 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 6552 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 6553 } 6554 *areLocalized = alreadyLocalized; 6555 PetscFunctionReturn(0); 6556 } 6557 6558 /*@ 6559 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 6560 6561 Collective on dm 6562 6563 Input Parameter: 6564 . dm - The DM 6565 6566 Output Parameter: 6567 areLocalized - True if localized 6568 6569 Level: developer 6570 6571 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 6572 @*/ 6573 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 6574 { 6575 PetscBool localized; 6576 PetscErrorCode ierr; 6577 6578 PetscFunctionBegin; 6579 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6580 PetscValidBoolPointer(areLocalized, 2); 6581 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 6582 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6583 PetscFunctionReturn(0); 6584 } 6585 6586 /*@ 6587 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 6588 6589 Collective on dm 6590 6591 Input Parameter: 6592 . dm - The DM 6593 6594 Level: developer 6595 6596 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 6597 @*/ 6598 PetscErrorCode DMLocalizeCoordinates(DM dm) 6599 { 6600 DM cdm; 6601 PetscSection coordSection, cSection; 6602 Vec coordinates, cVec; 6603 PetscScalar *coords, *coords2, *anchor, *localized; 6604 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 6605 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 6606 PetscInt maxHeight = 0, h; 6607 PetscInt *pStart = NULL, *pEnd = NULL; 6608 PetscErrorCode ierr; 6609 6610 PetscFunctionBegin; 6611 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6612 if (!dm->periodic) PetscFunctionReturn(0); 6613 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 6614 if (alreadyLocalized) PetscFunctionReturn(0); 6615 6616 /* We need some generic way of refering to cells/vertices */ 6617 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6618 { 6619 PetscBool isplex; 6620 6621 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 6622 if (isplex) { 6623 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6624 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 6625 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6626 pEnd = &pStart[maxHeight + 1]; 6627 newStart = vStart; 6628 newEnd = vEnd; 6629 for (h = 0; h <= maxHeight; h++) { 6630 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 6631 newStart = PetscMin(newStart,pStart[h]); 6632 newEnd = PetscMax(newEnd,pEnd[h]); 6633 } 6634 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 6635 } 6636 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6637 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 6638 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6639 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 6640 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 6641 6642 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 6643 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 6644 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 6645 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 6646 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 6647 6648 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6649 localized = &anchor[bs]; 6650 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 6651 for (h = 0; h <= maxHeight; h++) { 6652 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6653 6654 for (c = cStart; c < cEnd; ++c) { 6655 PetscScalar *cellCoords = NULL; 6656 PetscInt b; 6657 6658 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 6659 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6660 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6661 for (d = 0; d < dof/bs; ++d) { 6662 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 6663 for (b = 0; b < bs; b++) { 6664 if (cellCoords[d*bs + b] != localized[b]) break; 6665 } 6666 if (b < bs) break; 6667 } 6668 if (d < dof/bs) { 6669 if (c >= sStart && c < sEnd) { 6670 PetscInt cdof; 6671 6672 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 6673 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 6674 } 6675 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 6676 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 6677 } 6678 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6679 } 6680 } 6681 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6682 if (alreadyLocalizedGlobal) { 6683 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6684 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6685 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6686 PetscFunctionReturn(0); 6687 } 6688 for (v = vStart; v < vEnd; ++v) { 6689 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6690 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 6691 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 6692 } 6693 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 6694 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 6695 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 6696 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 6697 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 6698 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 6699 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 6700 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6701 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 6702 for (v = vStart; v < vEnd; ++v) { 6703 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6704 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6705 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 6706 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 6707 } 6708 for (h = 0; h <= maxHeight; h++) { 6709 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6710 6711 for (c = cStart; c < cEnd; ++c) { 6712 PetscScalar *cellCoords = NULL; 6713 PetscInt b, cdof; 6714 6715 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 6716 if (!cdof) continue; 6717 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6718 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 6719 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6720 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 6721 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6722 } 6723 } 6724 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6725 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6726 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6727 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 6728 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 6729 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 6730 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 6731 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6732 PetscFunctionReturn(0); 6733 } 6734 6735 /*@ 6736 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 6737 6738 Collective on v (see explanation below) 6739 6740 Input Parameters: 6741 + dm - The DM 6742 . v - The Vec of points 6743 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 6744 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 6745 6746 Output Parameter: 6747 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 6748 - cells - The PetscSF containing the ranks and local indices of the containing points. 6749 6750 6751 Level: developer 6752 6753 Notes: 6754 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 6755 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 6756 6757 If *cellSF is NULL on input, a PetscSF will be created. 6758 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 6759 6760 An array that maps each point to its containing cell can be obtained with 6761 6762 $ const PetscSFNode *cells; 6763 $ PetscInt nFound; 6764 $ const PetscInt *found; 6765 $ 6766 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 6767 6768 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 6769 the index of the cell in its rank's local numbering. 6770 6771 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 6772 @*/ 6773 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 6774 { 6775 PetscErrorCode ierr; 6776 6777 PetscFunctionBegin; 6778 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6779 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 6780 PetscValidPointer(cellSF,4); 6781 if (*cellSF) { 6782 PetscMPIInt result; 6783 6784 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 6785 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 6786 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 6787 } else { 6788 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 6789 } 6790 if (!dm->ops->locatepoints) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 6791 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6792 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 6793 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6794 PetscFunctionReturn(0); 6795 } 6796 6797 /*@ 6798 DMGetOutputDM - Retrieve the DM associated with the layout for output 6799 6800 Collective on dm 6801 6802 Input Parameter: 6803 . dm - The original DM 6804 6805 Output Parameter: 6806 . odm - The DM which provides the layout for output 6807 6808 Level: intermediate 6809 6810 .seealso: VecView(), DMGetGlobalSection() 6811 @*/ 6812 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 6813 { 6814 PetscSection section; 6815 PetscBool hasConstraints, ghasConstraints; 6816 PetscErrorCode ierr; 6817 6818 PetscFunctionBegin; 6819 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6820 PetscValidPointer(odm,2); 6821 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 6822 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 6823 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 6824 if (!ghasConstraints) { 6825 *odm = dm; 6826 PetscFunctionReturn(0); 6827 } 6828 if (!dm->dmBC) { 6829 PetscSection newSection, gsection; 6830 PetscSF sf; 6831 6832 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 6833 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 6834 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 6835 ierr = DMSetLocalSection(dm->dmBC, newSection);CHKERRQ(ierr); 6836 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 6837 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 6838 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 6839 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 6840 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 6841 } 6842 *odm = dm->dmBC; 6843 PetscFunctionReturn(0); 6844 } 6845 6846 /*@ 6847 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 6848 6849 Input Parameter: 6850 . dm - The original DM 6851 6852 Output Parameters: 6853 + num - The output sequence number 6854 - val - The output sequence value 6855 6856 Level: intermediate 6857 6858 Note: This is intended for output that should appear in sequence, for instance 6859 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6860 6861 .seealso: VecView() 6862 @*/ 6863 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 6864 { 6865 PetscFunctionBegin; 6866 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6867 if (num) {PetscValidIntPointer(num,2); *num = dm->outputSequenceNum;} 6868 if (val) {PetscValidRealPointer(val,3);*val = dm->outputSequenceVal;} 6869 PetscFunctionReturn(0); 6870 } 6871 6872 /*@ 6873 DMSetOutputSequenceNumber - Set the sequence number/value for output 6874 6875 Input Parameters: 6876 + dm - The original DM 6877 . num - The output sequence number 6878 - val - The output sequence value 6879 6880 Level: intermediate 6881 6882 Note: This is intended for output that should appear in sequence, for instance 6883 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6884 6885 .seealso: VecView() 6886 @*/ 6887 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 6888 { 6889 PetscFunctionBegin; 6890 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6891 dm->outputSequenceNum = num; 6892 dm->outputSequenceVal = val; 6893 PetscFunctionReturn(0); 6894 } 6895 6896 /*@C 6897 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 6898 6899 Input Parameters: 6900 + dm - The original DM 6901 . name - The sequence name 6902 - num - The output sequence number 6903 6904 Output Parameter: 6905 . val - The output sequence value 6906 6907 Level: intermediate 6908 6909 Note: This is intended for output that should appear in sequence, for instance 6910 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6911 6912 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 6913 @*/ 6914 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 6915 { 6916 PetscBool ishdf5; 6917 PetscErrorCode ierr; 6918 6919 PetscFunctionBegin; 6920 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6921 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 6922 PetscValidRealPointer(val,4); 6923 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 6924 if (ishdf5) { 6925 #if defined(PETSC_HAVE_HDF5) 6926 PetscScalar value; 6927 6928 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 6929 *val = PetscRealPart(value); 6930 #endif 6931 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 6932 PetscFunctionReturn(0); 6933 } 6934 6935 /*@ 6936 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 6937 6938 Not collective 6939 6940 Input Parameter: 6941 . dm - The DM 6942 6943 Output Parameter: 6944 . useNatural - The flag to build the mapping to a natural order during distribution 6945 6946 Level: beginner 6947 6948 .seealso: DMSetUseNatural(), DMCreate() 6949 @*/ 6950 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 6951 { 6952 PetscFunctionBegin; 6953 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6954 PetscValidBoolPointer(useNatural, 2); 6955 *useNatural = dm->useNatural; 6956 PetscFunctionReturn(0); 6957 } 6958 6959 /*@ 6960 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 6961 6962 Collective on dm 6963 6964 Input Parameters: 6965 + dm - The DM 6966 - useNatural - The flag to build the mapping to a natural order during distribution 6967 6968 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 6969 6970 Level: beginner 6971 6972 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 6973 @*/ 6974 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 6975 { 6976 PetscFunctionBegin; 6977 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6978 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 6979 dm->useNatural = useNatural; 6980 PetscFunctionReturn(0); 6981 } 6982 6983 6984 /*@C 6985 DMCreateLabel - Create a label of the given name if it does not already exist 6986 6987 Not Collective 6988 6989 Input Parameters: 6990 + dm - The DM object 6991 - name - The label name 6992 6993 Level: intermediate 6994 6995 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6996 @*/ 6997 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 6998 { 6999 PetscBool flg; 7000 DMLabel label; 7001 PetscErrorCode ierr; 7002 7003 PetscFunctionBegin; 7004 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7005 PetscValidCharPointer(name, 2); 7006 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 7007 if (!flg) { 7008 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 7009 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 7010 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 7011 } 7012 PetscFunctionReturn(0); 7013 } 7014 7015 /*@C 7016 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 7017 7018 Not Collective 7019 7020 Input Parameters: 7021 + dm - The DM object 7022 . name - The label name 7023 - point - The mesh point 7024 7025 Output Parameter: 7026 . value - The label value for this point, or -1 if the point is not in the label 7027 7028 Level: beginner 7029 7030 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 7031 @*/ 7032 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 7033 { 7034 DMLabel label; 7035 PetscErrorCode ierr; 7036 7037 PetscFunctionBegin; 7038 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7039 PetscValidCharPointer(name, 2); 7040 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7041 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 7042 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 7043 PetscFunctionReturn(0); 7044 } 7045 7046 /*@C 7047 DMSetLabelValue - Add a point to a Sieve Label with given value 7048 7049 Not Collective 7050 7051 Input Parameters: 7052 + dm - The DM object 7053 . name - The label name 7054 . point - The mesh point 7055 - value - The label value for this point 7056 7057 Output Parameter: 7058 7059 Level: beginner 7060 7061 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 7062 @*/ 7063 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7064 { 7065 DMLabel label; 7066 PetscErrorCode ierr; 7067 7068 PetscFunctionBegin; 7069 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7070 PetscValidCharPointer(name, 2); 7071 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7072 if (!label) { 7073 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 7074 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7075 } 7076 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 7077 PetscFunctionReturn(0); 7078 } 7079 7080 /*@C 7081 DMClearLabelValue - Remove a point from a Sieve Label with given value 7082 7083 Not Collective 7084 7085 Input Parameters: 7086 + dm - The DM object 7087 . name - The label name 7088 . point - The mesh point 7089 - value - The label value for this point 7090 7091 Output Parameter: 7092 7093 Level: beginner 7094 7095 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 7096 @*/ 7097 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7098 { 7099 DMLabel label; 7100 PetscErrorCode ierr; 7101 7102 PetscFunctionBegin; 7103 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7104 PetscValidCharPointer(name, 2); 7105 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7106 if (!label) PetscFunctionReturn(0); 7107 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 7108 PetscFunctionReturn(0); 7109 } 7110 7111 /*@C 7112 DMGetLabelSize - Get the number of different integer ids in a Label 7113 7114 Not Collective 7115 7116 Input Parameters: 7117 + dm - The DM object 7118 - name - The label name 7119 7120 Output Parameter: 7121 . size - The number of different integer ids, or 0 if the label does not exist 7122 7123 Level: beginner 7124 7125 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 7126 @*/ 7127 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 7128 { 7129 DMLabel label; 7130 PetscErrorCode ierr; 7131 7132 PetscFunctionBegin; 7133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7134 PetscValidCharPointer(name, 2); 7135 PetscValidIntPointer(size, 3); 7136 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7137 *size = 0; 7138 if (!label) PetscFunctionReturn(0); 7139 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 7140 PetscFunctionReturn(0); 7141 } 7142 7143 /*@C 7144 DMGetLabelIdIS - Get the integer ids in a label 7145 7146 Not Collective 7147 7148 Input Parameters: 7149 + mesh - The DM object 7150 - name - The label name 7151 7152 Output Parameter: 7153 . ids - The integer ids, or NULL if the label does not exist 7154 7155 Level: beginner 7156 7157 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 7158 @*/ 7159 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 7160 { 7161 DMLabel label; 7162 PetscErrorCode ierr; 7163 7164 PetscFunctionBegin; 7165 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7166 PetscValidCharPointer(name, 2); 7167 PetscValidPointer(ids, 3); 7168 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7169 *ids = NULL; 7170 if (label) { 7171 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 7172 } else { 7173 /* returning an empty IS */ 7174 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 7175 } 7176 PetscFunctionReturn(0); 7177 } 7178 7179 /*@C 7180 DMGetStratumSize - Get the number of points in a label stratum 7181 7182 Not Collective 7183 7184 Input Parameters: 7185 + dm - The DM object 7186 . name - The label name 7187 - value - The stratum value 7188 7189 Output Parameter: 7190 . size - The stratum size 7191 7192 Level: beginner 7193 7194 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 7195 @*/ 7196 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 7197 { 7198 DMLabel label; 7199 PetscErrorCode ierr; 7200 7201 PetscFunctionBegin; 7202 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7203 PetscValidCharPointer(name, 2); 7204 PetscValidIntPointer(size, 4); 7205 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7206 *size = 0; 7207 if (!label) PetscFunctionReturn(0); 7208 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 7209 PetscFunctionReturn(0); 7210 } 7211 7212 /*@C 7213 DMGetStratumIS - Get the points in a label stratum 7214 7215 Not Collective 7216 7217 Input Parameters: 7218 + dm - The DM object 7219 . name - The label name 7220 - value - The stratum value 7221 7222 Output Parameter: 7223 . points - The stratum points, or NULL if the label does not exist or does not have that value 7224 7225 Level: beginner 7226 7227 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 7228 @*/ 7229 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 7230 { 7231 DMLabel label; 7232 PetscErrorCode ierr; 7233 7234 PetscFunctionBegin; 7235 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7236 PetscValidCharPointer(name, 2); 7237 PetscValidPointer(points, 4); 7238 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7239 *points = NULL; 7240 if (!label) PetscFunctionReturn(0); 7241 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 7242 PetscFunctionReturn(0); 7243 } 7244 7245 /*@C 7246 DMSetStratumIS - Set the points in a label stratum 7247 7248 Not Collective 7249 7250 Input Parameters: 7251 + dm - The DM object 7252 . name - The label name 7253 . value - The stratum value 7254 - points - The stratum points 7255 7256 Level: beginner 7257 7258 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 7259 @*/ 7260 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 7261 { 7262 DMLabel label; 7263 PetscErrorCode ierr; 7264 7265 PetscFunctionBegin; 7266 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7267 PetscValidCharPointer(name, 2); 7268 PetscValidPointer(points, 4); 7269 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7270 if (!label) PetscFunctionReturn(0); 7271 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 7272 PetscFunctionReturn(0); 7273 } 7274 7275 /*@C 7276 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 7277 7278 Not Collective 7279 7280 Input Parameters: 7281 + dm - The DM object 7282 . name - The label name 7283 - value - The label value for this point 7284 7285 Output Parameter: 7286 7287 Level: beginner 7288 7289 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 7290 @*/ 7291 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 7292 { 7293 DMLabel label; 7294 PetscErrorCode ierr; 7295 7296 PetscFunctionBegin; 7297 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7298 PetscValidCharPointer(name, 2); 7299 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7300 if (!label) PetscFunctionReturn(0); 7301 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 7302 PetscFunctionReturn(0); 7303 } 7304 7305 /*@ 7306 DMGetNumLabels - Return the number of labels defined by the mesh 7307 7308 Not Collective 7309 7310 Input Parameter: 7311 . dm - The DM object 7312 7313 Output Parameter: 7314 . numLabels - the number of Labels 7315 7316 Level: intermediate 7317 7318 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7319 @*/ 7320 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 7321 { 7322 DMLabelLink next = dm->labels; 7323 PetscInt n = 0; 7324 7325 PetscFunctionBegin; 7326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7327 PetscValidIntPointer(numLabels, 2); 7328 while (next) {++n; next = next->next;} 7329 *numLabels = n; 7330 PetscFunctionReturn(0); 7331 } 7332 7333 /*@C 7334 DMGetLabelName - Return the name of nth label 7335 7336 Not Collective 7337 7338 Input Parameters: 7339 + dm - The DM object 7340 - n - the label number 7341 7342 Output Parameter: 7343 . name - the label name 7344 7345 Level: intermediate 7346 7347 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7348 @*/ 7349 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 7350 { 7351 DMLabelLink next = dm->labels; 7352 PetscInt l = 0; 7353 PetscErrorCode ierr; 7354 7355 PetscFunctionBegin; 7356 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7357 PetscValidPointer(name, 3); 7358 while (next) { 7359 if (l == n) { 7360 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 7361 PetscFunctionReturn(0); 7362 } 7363 ++l; 7364 next = next->next; 7365 } 7366 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7367 } 7368 7369 /*@C 7370 DMHasLabel - Determine whether the mesh has a label of a given name 7371 7372 Not Collective 7373 7374 Input Parameters: 7375 + dm - The DM object 7376 - name - The label name 7377 7378 Output Parameter: 7379 . hasLabel - PETSC_TRUE if the label is present 7380 7381 Level: intermediate 7382 7383 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7384 @*/ 7385 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 7386 { 7387 DMLabelLink next = dm->labels; 7388 const char *lname; 7389 PetscErrorCode ierr; 7390 7391 PetscFunctionBegin; 7392 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7393 PetscValidCharPointer(name, 2); 7394 PetscValidBoolPointer(hasLabel, 3); 7395 *hasLabel = PETSC_FALSE; 7396 while (next) { 7397 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7398 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 7399 if (*hasLabel) break; 7400 next = next->next; 7401 } 7402 PetscFunctionReturn(0); 7403 } 7404 7405 /*@C 7406 DMGetLabel - Return the label of a given name, or NULL 7407 7408 Not Collective 7409 7410 Input Parameters: 7411 + dm - The DM object 7412 - name - The label name 7413 7414 Output Parameter: 7415 . label - The DMLabel, or NULL if the label is absent 7416 7417 Level: intermediate 7418 7419 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7420 @*/ 7421 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 7422 { 7423 DMLabelLink next = dm->labels; 7424 PetscBool hasLabel; 7425 const char *lname; 7426 PetscErrorCode ierr; 7427 7428 PetscFunctionBegin; 7429 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7430 PetscValidCharPointer(name, 2); 7431 PetscValidPointer(label, 3); 7432 *label = NULL; 7433 while (next) { 7434 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7435 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7436 if (hasLabel) { 7437 *label = next->label; 7438 break; 7439 } 7440 next = next->next; 7441 } 7442 PetscFunctionReturn(0); 7443 } 7444 7445 /*@C 7446 DMGetLabelByNum - Return the nth label 7447 7448 Not Collective 7449 7450 Input Parameters: 7451 + dm - The DM object 7452 - n - the label number 7453 7454 Output Parameter: 7455 . label - the label 7456 7457 Level: intermediate 7458 7459 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7460 @*/ 7461 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 7462 { 7463 DMLabelLink next = dm->labels; 7464 PetscInt l = 0; 7465 7466 PetscFunctionBegin; 7467 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7468 PetscValidPointer(label, 3); 7469 while (next) { 7470 if (l == n) { 7471 *label = next->label; 7472 PetscFunctionReturn(0); 7473 } 7474 ++l; 7475 next = next->next; 7476 } 7477 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7478 } 7479 7480 /*@C 7481 DMAddLabel - Add the label to this mesh 7482 7483 Not Collective 7484 7485 Input Parameters: 7486 + dm - The DM object 7487 - label - The DMLabel 7488 7489 Level: developer 7490 7491 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7492 @*/ 7493 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 7494 { 7495 DMLabelLink l, *p, tmpLabel; 7496 PetscBool hasLabel; 7497 const char *lname; 7498 PetscBool flg; 7499 PetscErrorCode ierr; 7500 7501 PetscFunctionBegin; 7502 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7503 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 7504 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 7505 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 7506 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 7507 tmpLabel->label = label; 7508 tmpLabel->output = PETSC_TRUE; 7509 for (p=&dm->labels; (l=*p); p=&l->next) {} 7510 *p = tmpLabel; 7511 ierr = PetscObjectReference((PetscObject)label);CHKERRQ(ierr); 7512 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 7513 if (flg) dm->depthLabel = label; 7514 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 7515 if (flg) dm->celltypeLabel = label; 7516 PetscFunctionReturn(0); 7517 } 7518 7519 /*@C 7520 DMRemoveLabel - Remove the label given by name from this mesh 7521 7522 Not Collective 7523 7524 Input Parameters: 7525 + dm - The DM object 7526 - name - The label name 7527 7528 Output Parameter: 7529 . label - The DMLabel, or NULL if the label is absent 7530 7531 Level: developer 7532 7533 Notes: 7534 DMRemoveLabel(dm,name,NULL) removes the label from dm and calls 7535 DMLabelDestroy() on the label. 7536 7537 DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT 7538 call DMLabelDestroy(). Instead, the label is returned and the user is 7539 responsible of calling DMLabelDestroy() at some point. 7540 7541 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf() 7542 @*/ 7543 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 7544 { 7545 DMLabelLink link, *pnext; 7546 PetscBool hasLabel; 7547 const char *lname; 7548 PetscErrorCode ierr; 7549 7550 PetscFunctionBegin; 7551 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7552 PetscValidCharPointer(name, 2); 7553 if (label) { 7554 PetscValidPointer(label, 3); 7555 *label = NULL; 7556 } 7557 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7558 ierr = PetscObjectGetName((PetscObject) link->label, &lname);CHKERRQ(ierr); 7559 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7560 if (hasLabel) { 7561 *pnext = link->next; /* Remove from list */ 7562 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 7563 if (hasLabel) dm->depthLabel = NULL; 7564 ierr = PetscStrcmp(name, "celltype", &hasLabel);CHKERRQ(ierr); 7565 if (hasLabel) dm->celltypeLabel = NULL; 7566 if (label) *label = link->label; 7567 else {ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);} 7568 ierr = PetscFree(link);CHKERRQ(ierr); 7569 break; 7570 } 7571 } 7572 PetscFunctionReturn(0); 7573 } 7574 7575 /*@ 7576 DMRemoveLabelBySelf - Remove the label from this mesh 7577 7578 Not Collective 7579 7580 Input Parameters: 7581 + dm - The DM object 7582 . label - (Optional) The DMLabel to be removed from the DM 7583 - failNotFound - Should it fail if the label is not found in the DM? 7584 7585 Level: developer 7586 7587 Notes: 7588 Only exactly the same instance is removed if found, name match is ignored. 7589 If the DM has an exclusive reference to the label, it gets destroyed and 7590 *label nullified. 7591 7592 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel() 7593 @*/ 7594 PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound) 7595 { 7596 DMLabelLink link, *pnext; 7597 PetscBool hasLabel = PETSC_FALSE; 7598 PetscErrorCode ierr; 7599 7600 PetscFunctionBegin; 7601 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7602 PetscValidPointer(label, 2); 7603 if (!*label && !failNotFound) PetscFunctionReturn(0); 7604 PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2); 7605 PetscValidLogicalCollectiveBool(dm,failNotFound,3); 7606 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7607 if (*label == link->label) { 7608 hasLabel = PETSC_TRUE; 7609 *pnext = link->next; /* Remove from list */ 7610 if (*label == dm->depthLabel) dm->depthLabel = NULL; 7611 if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL; 7612 if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */ 7613 ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr); 7614 ierr = PetscFree(link);CHKERRQ(ierr); 7615 break; 7616 } 7617 } 7618 if (!hasLabel && failNotFound) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM"); 7619 PetscFunctionReturn(0); 7620 } 7621 7622 /*@C 7623 DMGetLabelOutput - Get the output flag for a given label 7624 7625 Not Collective 7626 7627 Input Parameters: 7628 + dm - The DM object 7629 - name - The label name 7630 7631 Output Parameter: 7632 . output - The flag for output 7633 7634 Level: developer 7635 7636 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7637 @*/ 7638 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 7639 { 7640 DMLabelLink next = dm->labels; 7641 const char *lname; 7642 PetscErrorCode ierr; 7643 7644 PetscFunctionBegin; 7645 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7646 PetscValidPointer(name, 2); 7647 PetscValidPointer(output, 3); 7648 while (next) { 7649 PetscBool flg; 7650 7651 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7652 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7653 if (flg) {*output = next->output; PetscFunctionReturn(0);} 7654 next = next->next; 7655 } 7656 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7657 } 7658 7659 /*@C 7660 DMSetLabelOutput - Set the output flag for a given label 7661 7662 Not Collective 7663 7664 Input Parameters: 7665 + dm - The DM object 7666 . name - The label name 7667 - output - The flag for output 7668 7669 Level: developer 7670 7671 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7672 @*/ 7673 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 7674 { 7675 DMLabelLink next = dm->labels; 7676 const char *lname; 7677 PetscErrorCode ierr; 7678 7679 PetscFunctionBegin; 7680 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7681 PetscValidCharPointer(name, 2); 7682 while (next) { 7683 PetscBool flg; 7684 7685 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7686 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7687 if (flg) {next->output = output; PetscFunctionReturn(0);} 7688 next = next->next; 7689 } 7690 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7691 } 7692 7693 /*@ 7694 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 7695 7696 Collective on dmA 7697 7698 Input Parameter: 7699 + dmA - The DM object with initial labels 7700 . dmB - The DM object with copied labels 7701 . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES) 7702 - all - Copy all labels including "depth", "dim", and "celltype" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE) 7703 7704 Level: intermediate 7705 7706 Note: This is typically used when interpolating or otherwise adding to a mesh 7707 7708 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection(), DMShareLabels() 7709 @*/ 7710 PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all) 7711 { 7712 DMLabel label, labelNew; 7713 const char *name; 7714 PetscBool flg; 7715 DMLabelLink link; 7716 PetscErrorCode ierr; 7717 7718 PetscFunctionBegin; 7719 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 7720 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 7721 PetscValidLogicalCollectiveEnum(dmA, mode,3); 7722 PetscValidLogicalCollectiveBool(dmA, all, 4); 7723 if (mode==PETSC_USE_POINTER) SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects"); 7724 if (dmA == dmB) PetscFunctionReturn(0); 7725 for (link=dmA->labels; link; link=link->next) { 7726 label=link->label; 7727 ierr = PetscObjectGetName((PetscObject)label, &name);CHKERRQ(ierr); 7728 if (!all) { 7729 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 7730 if (flg) continue; 7731 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 7732 if (flg) continue; 7733 ierr = PetscStrcmp(name, "celltype", &flg);CHKERRQ(ierr); 7734 if (flg) continue; 7735 } 7736 if (mode==PETSC_COPY_VALUES) { 7737 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 7738 } else { 7739 labelNew = label; 7740 } 7741 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 7742 if (mode==PETSC_COPY_VALUES) {ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);} 7743 } 7744 PetscFunctionReturn(0); 7745 } 7746 7747 /*@ 7748 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 7749 7750 Input Parameter: 7751 . dm - The DM object 7752 7753 Output Parameter: 7754 . cdm - The coarse DM 7755 7756 Level: intermediate 7757 7758 .seealso: DMSetCoarseDM() 7759 @*/ 7760 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 7761 { 7762 PetscFunctionBegin; 7763 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7764 PetscValidPointer(cdm, 2); 7765 *cdm = dm->coarseMesh; 7766 PetscFunctionReturn(0); 7767 } 7768 7769 /*@ 7770 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 7771 7772 Input Parameters: 7773 + dm - The DM object 7774 - cdm - The coarse DM 7775 7776 Level: intermediate 7777 7778 .seealso: DMGetCoarseDM() 7779 @*/ 7780 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 7781 { 7782 PetscErrorCode ierr; 7783 7784 PetscFunctionBegin; 7785 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7786 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 7787 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 7788 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 7789 dm->coarseMesh = cdm; 7790 PetscFunctionReturn(0); 7791 } 7792 7793 /*@ 7794 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 7795 7796 Input Parameter: 7797 . dm - The DM object 7798 7799 Output Parameter: 7800 . fdm - The fine DM 7801 7802 Level: intermediate 7803 7804 .seealso: DMSetFineDM() 7805 @*/ 7806 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 7807 { 7808 PetscFunctionBegin; 7809 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7810 PetscValidPointer(fdm, 2); 7811 *fdm = dm->fineMesh; 7812 PetscFunctionReturn(0); 7813 } 7814 7815 /*@ 7816 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 7817 7818 Input Parameters: 7819 + dm - The DM object 7820 - fdm - The fine DM 7821 7822 Level: intermediate 7823 7824 .seealso: DMGetFineDM() 7825 @*/ 7826 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 7827 { 7828 PetscErrorCode ierr; 7829 7830 PetscFunctionBegin; 7831 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7832 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 7833 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 7834 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 7835 dm->fineMesh = fdm; 7836 PetscFunctionReturn(0); 7837 } 7838 7839 /*=== DMBoundary code ===*/ 7840 7841 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 7842 { 7843 PetscInt d; 7844 PetscErrorCode ierr; 7845 7846 PetscFunctionBegin; 7847 for (d = 0; d < dm->Nds; ++d) { 7848 ierr = PetscDSCopyBoundary(dm->probs[d].ds, dmNew->probs[d].ds);CHKERRQ(ierr); 7849 } 7850 PetscFunctionReturn(0); 7851 } 7852 7853 /*@C 7854 DMAddBoundary - Add a boundary condition to the model 7855 7856 Collective on dm 7857 7858 Input Parameters: 7859 + dm - The DM, with a PetscDS that matches the problem being constrained 7860 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7861 . name - The BC name 7862 . labelname - The label defining constrained points 7863 . field - The field to constrain 7864 . numcomps - The number of constrained field components (0 will constrain all fields) 7865 . comps - An array of constrained component numbers 7866 . bcFunc - A pointwise function giving boundary values 7867 . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL 7868 . numids - The number of DMLabel ids for constrained points 7869 . ids - An array of ids for constrained points 7870 - ctx - An optional user context for bcFunc 7871 7872 Options Database Keys: 7873 + -bc_<boundary name> <num> - Overrides the boundary ids 7874 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7875 7876 Note: 7877 Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is: 7878 7879 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 7880 7881 If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is: 7882 7883 $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 7884 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 7885 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 7886 $ PetscReal time, const PetscReal x[], PetscScalar bcval[]) 7887 7888 + dim - the spatial dimension 7889 . Nf - the number of fields 7890 . uOff - the offset into u[] and u_t[] for each field 7891 . uOff_x - the offset into u_x[] for each field 7892 . u - each field evaluated at the current point 7893 . u_t - the time derivative of each field evaluated at the current point 7894 . u_x - the gradient of each field evaluated at the current point 7895 . aOff - the offset into a[] and a_t[] for each auxiliary field 7896 . aOff_x - the offset into a_x[] for each auxiliary field 7897 . a - each auxiliary field evaluated at the current point 7898 . a_t - the time derivative of each auxiliary field evaluated at the current point 7899 . a_x - the gradient of auxiliary each field evaluated at the current point 7900 . t - current time 7901 . x - coordinates of the current point 7902 . numConstants - number of constant parameters 7903 . constants - constant parameters 7904 - bcval - output values at the current point 7905 7906 Level: developer 7907 7908 .seealso: DMGetBoundary(), PetscDSAddBoundary() 7909 @*/ 7910 PetscErrorCode DMAddBoundary(DM dm, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), void (*bcFunc_t)(void), PetscInt numids, const PetscInt *ids, void *ctx) 7911 { 7912 PetscDS ds; 7913 PetscErrorCode ierr; 7914 7915 PetscFunctionBegin; 7916 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7917 PetscValidLogicalCollectiveEnum(dm, type, 2); 7918 PetscValidLogicalCollectiveInt(dm, field, 5); 7919 PetscValidLogicalCollectiveInt(dm, numcomps, 6); 7920 PetscValidLogicalCollectiveInt(dm, numids, 9); 7921 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7922 ierr = DMCompleteBoundaryLabel_Internal(dm, ds, field, PETSC_MAX_INT, labelname);CHKERRQ(ierr); 7923 ierr = PetscDSAddBoundary(ds, type,name, labelname, field, numcomps, comps, bcFunc, bcFunc_t, numids, ids, ctx);CHKERRQ(ierr); 7924 PetscFunctionReturn(0); 7925 } 7926 7927 /*@ 7928 DMGetNumBoundary - Get the number of registered BC 7929 7930 Input Parameters: 7931 . dm - The mesh object 7932 7933 Output Parameters: 7934 . numBd - The number of BC 7935 7936 Level: intermediate 7937 7938 .seealso: DMAddBoundary(), DMGetBoundary() 7939 @*/ 7940 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 7941 { 7942 PetscDS ds; 7943 PetscErrorCode ierr; 7944 7945 PetscFunctionBegin; 7946 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7947 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7948 ierr = PetscDSGetNumBoundary(ds, numBd);CHKERRQ(ierr); 7949 PetscFunctionReturn(0); 7950 } 7951 7952 /*@C 7953 DMGetBoundary - Get a model boundary condition 7954 7955 Input Parameters: 7956 + dm - The mesh object 7957 - bd - The BC number 7958 7959 Output Parameters: 7960 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7961 . name - The BC name 7962 . labelname - The label defining constrained points 7963 . field - The field to constrain 7964 . numcomps - The number of constrained field components 7965 . comps - An array of constrained component numbers 7966 . bcFunc - A pointwise function giving boundary values 7967 . bcFunc_t - A pointwise function giving the time derviative of the boundary values 7968 . numids - The number of DMLabel ids for constrained points 7969 . ids - An array of ids for constrained points 7970 - ctx - An optional user context for bcFunc 7971 7972 Options Database Keys: 7973 + -bc_<boundary name> <num> - Overrides the boundary ids 7974 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7975 7976 Level: developer 7977 7978 .seealso: DMAddBoundary() 7979 @*/ 7980 PetscErrorCode DMGetBoundary(DM dm, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), void (**func_t)(void), PetscInt *numids, const PetscInt **ids, void **ctx) 7981 { 7982 PetscDS ds; 7983 PetscErrorCode ierr; 7984 7985 PetscFunctionBegin; 7986 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7987 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7988 ierr = PetscDSGetBoundary(ds, bd, type, name, labelname, field, numcomps, comps, func, func_t, numids, ids, ctx);CHKERRQ(ierr); 7989 PetscFunctionReturn(0); 7990 } 7991 7992 static PetscErrorCode DMPopulateBoundary(DM dm) 7993 { 7994 PetscDS ds; 7995 DMBoundary *lastnext; 7996 DSBoundary dsbound; 7997 PetscErrorCode ierr; 7998 7999 PetscFunctionBegin; 8000 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 8001 dsbound = ds->boundary; 8002 if (dm->boundary) { 8003 DMBoundary next = dm->boundary; 8004 8005 /* quick check to see if the PetscDS has changed */ 8006 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 8007 /* the PetscDS has changed: tear down and rebuild */ 8008 while (next) { 8009 DMBoundary b = next; 8010 8011 next = b->next; 8012 ierr = PetscFree(b);CHKERRQ(ierr); 8013 } 8014 dm->boundary = NULL; 8015 } 8016 8017 lastnext = &(dm->boundary); 8018 while (dsbound) { 8019 DMBoundary dmbound; 8020 8021 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 8022 dmbound->dsboundary = dsbound; 8023 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 8024 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 8025 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 8026 *lastnext = dmbound; 8027 lastnext = &(dmbound->next); 8028 dsbound = dsbound->next; 8029 } 8030 PetscFunctionReturn(0); 8031 } 8032 8033 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 8034 { 8035 DMBoundary b; 8036 PetscErrorCode ierr; 8037 8038 PetscFunctionBegin; 8039 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8040 PetscValidBoolPointer(isBd, 3); 8041 *isBd = PETSC_FALSE; 8042 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 8043 b = dm->boundary; 8044 while (b && !(*isBd)) { 8045 DMLabel label = b->label; 8046 DSBoundary dsb = b->dsboundary; 8047 8048 if (label) { 8049 PetscInt i; 8050 8051 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 8052 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 8053 } 8054 } 8055 b = b->next; 8056 } 8057 PetscFunctionReturn(0); 8058 } 8059 8060 /*@C 8061 DMProjectFunction - This projects the given function into the function space provided, putting the coefficients in a global vector. 8062 8063 Collective on DM 8064 8065 Input Parameters: 8066 + dm - The DM 8067 . time - The time 8068 . funcs - The coordinate functions to evaluate, one per field 8069 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8070 - mode - The insertion mode for values 8071 8072 Output Parameter: 8073 . X - vector 8074 8075 Calling sequence of func: 8076 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8077 8078 + dim - The spatial dimension 8079 . x - The coordinates 8080 . Nf - The number of fields 8081 . u - The output field values 8082 - ctx - optional user-defined function context 8083 8084 Level: developer 8085 8086 .seealso: DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 8087 @*/ 8088 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 8089 { 8090 Vec localX; 8091 PetscErrorCode ierr; 8092 8093 PetscFunctionBegin; 8094 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8095 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 8096 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8097 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 8098 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 8099 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 8100 PetscFunctionReturn(0); 8101 } 8102 8103 /*@C 8104 DMProjectFunctionLocal - This projects the given function into the function space provided, putting the coefficients in a local vector. 8105 8106 Not collective 8107 8108 Input Parameters: 8109 + dm - The DM 8110 . time - The time 8111 . funcs - The coordinate functions to evaluate, one per field 8112 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8113 - mode - The insertion mode for values 8114 8115 Output Parameter: 8116 . localX - vector 8117 8118 Calling sequence of func: 8119 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8120 8121 + dim - The spatial dimension 8122 . x - The coordinates 8123 . Nf - The number of fields 8124 . u - The output field values 8125 - ctx - optional user-defined function context 8126 8127 Level: developer 8128 8129 .seealso: DMProjectFunction(), DMProjectFunctionLabel(), DMComputeL2Diff() 8130 @*/ 8131 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 8132 { 8133 PetscErrorCode ierr; 8134 8135 PetscFunctionBegin; 8136 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8137 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 8138 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 8139 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8140 PetscFunctionReturn(0); 8141 } 8142 8143 /*@C 8144 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. 8145 8146 Collective on DM 8147 8148 Input Parameters: 8149 + dm - The DM 8150 . time - The time 8151 . label - The DMLabel selecting the portion of the mesh for projection 8152 . funcs - The coordinate functions to evaluate, one per field 8153 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8154 - mode - The insertion mode for values 8155 8156 Output Parameter: 8157 . X - vector 8158 8159 Calling sequence of func: 8160 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8161 8162 + dim - The spatial dimension 8163 . x - The coordinates 8164 . Nf - The number of fields 8165 . u - The output field values 8166 - ctx - optional user-defined function context 8167 8168 Level: developer 8169 8170 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal(), DMComputeL2Diff() 8171 @*/ 8172 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) 8173 { 8174 Vec localX; 8175 PetscErrorCode ierr; 8176 8177 PetscFunctionBegin; 8178 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8179 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 8180 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8181 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 8182 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 8183 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 8184 PetscFunctionReturn(0); 8185 } 8186 8187 /*@C 8188 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. 8189 8190 Not collective 8191 8192 Input Parameters: 8193 + dm - The DM 8194 . time - The time 8195 . label - The DMLabel selecting the portion of the mesh for projection 8196 . funcs - The coordinate functions to evaluate, one per field 8197 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8198 - mode - The insertion mode for values 8199 8200 Output Parameter: 8201 . localX - vector 8202 8203 Calling sequence of func: 8204 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8205 8206 + dim - The spatial dimension 8207 . x - The coordinates 8208 . Nf - The number of fields 8209 . u - The output field values 8210 - ctx - optional user-defined function context 8211 8212 Level: developer 8213 8214 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 8215 @*/ 8216 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) 8217 { 8218 PetscErrorCode ierr; 8219 8220 PetscFunctionBegin; 8221 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8222 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 8223 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 8224 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8225 PetscFunctionReturn(0); 8226 } 8227 8228 /*@C 8229 DMProjectFieldLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector. 8230 8231 Not collective 8232 8233 Input Parameters: 8234 + dm - The DM 8235 . time - The time 8236 . localU - The input field vector 8237 . funcs - The functions to evaluate, one per field 8238 - mode - The insertion mode for values 8239 8240 Output Parameter: 8241 . localX - The output vector 8242 8243 Calling sequence of func: 8244 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8245 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8246 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8247 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8248 8249 + dim - The spatial dimension 8250 . Nf - The number of input fields 8251 . NfAux - The number of input auxiliary fields 8252 . uOff - The offset of each field in u[] 8253 . uOff_x - The offset of each field in u_x[] 8254 . u - The field values at this point in space 8255 . u_t - The field time derivative at this point in space (or NULL) 8256 . u_x - The field derivatives at this point in space 8257 . aOff - The offset of each auxiliary field in u[] 8258 . aOff_x - The offset of each auxiliary field in u_x[] 8259 . a - The auxiliary field values at this point in space 8260 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8261 . a_x - The auxiliary field derivatives at this point in space 8262 . t - The current time 8263 . x - The coordinates of this point 8264 . numConstants - The number of constants 8265 . constants - The value of each constant 8266 - f - The value of the function at this point in space 8267 8268 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. 8269 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 8270 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8271 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8272 8273 Level: intermediate 8274 8275 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8276 @*/ 8277 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 8278 void (**funcs)(PetscInt, PetscInt, PetscInt, 8279 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8280 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8281 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8282 InsertMode mode, Vec localX) 8283 { 8284 PetscErrorCode ierr; 8285 8286 PetscFunctionBegin; 8287 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8288 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 8289 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 8290 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 8291 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 8292 PetscFunctionReturn(0); 8293 } 8294 8295 /*@C 8296 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. 8297 8298 Not collective 8299 8300 Input Parameters: 8301 + dm - The DM 8302 . time - The time 8303 . label - The DMLabel marking the portion of the domain to output 8304 . numIds - The number of label ids to use 8305 . ids - The label ids to use for marking 8306 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 8307 . comps - The components to set in the output, or NULL for all components 8308 . localU - The input field vector 8309 . funcs - The functions to evaluate, one per field 8310 - mode - The insertion mode for values 8311 8312 Output Parameter: 8313 . localX - The output vector 8314 8315 Calling sequence of func: 8316 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8317 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8318 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8319 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8320 8321 + dim - The spatial dimension 8322 . Nf - The number of input fields 8323 . NfAux - The number of input auxiliary fields 8324 . uOff - The offset of each field in u[] 8325 . uOff_x - The offset of each field in u_x[] 8326 . u - The field values at this point in space 8327 . u_t - The field time derivative at this point in space (or NULL) 8328 . u_x - The field derivatives at this point in space 8329 . aOff - The offset of each auxiliary field in u[] 8330 . aOff_x - The offset of each auxiliary field in u_x[] 8331 . a - The auxiliary field values at this point in space 8332 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8333 . a_x - The auxiliary field derivatives at this point in space 8334 . t - The current time 8335 . x - The coordinates of this point 8336 . numConstants - The number of constants 8337 . constants - The value of each constant 8338 - f - The value of the function at this point in space 8339 8340 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. 8341 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 8342 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8343 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8344 8345 Level: intermediate 8346 8347 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8348 @*/ 8349 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 8350 void (**funcs)(PetscInt, PetscInt, PetscInt, 8351 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8352 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8353 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8354 InsertMode mode, Vec localX) 8355 { 8356 PetscErrorCode ierr; 8357 8358 PetscFunctionBegin; 8359 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8360 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 8361 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 8362 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLabelLocal",((PetscObject)dm)->type_name); 8363 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 8364 PetscFunctionReturn(0); 8365 } 8366 8367 /*@C 8368 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. 8369 8370 Not collective 8371 8372 Input Parameters: 8373 + dm - The DM 8374 . time - The time 8375 . label - The DMLabel marking the portion of the domain boundary to output 8376 . numIds - The number of label ids to use 8377 . ids - The label ids to use for marking 8378 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 8379 . comps - The components to set in the output, or NULL for all components 8380 . localU - The input field vector 8381 . funcs - The functions to evaluate, one per field 8382 - mode - The insertion mode for values 8383 8384 Output Parameter: 8385 . localX - The output vector 8386 8387 Calling sequence of func: 8388 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8389 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8390 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8391 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8392 8393 + dim - The spatial dimension 8394 . Nf - The number of input fields 8395 . NfAux - The number of input auxiliary fields 8396 . uOff - The offset of each field in u[] 8397 . uOff_x - The offset of each field in u_x[] 8398 . u - The field values at this point in space 8399 . u_t - The field time derivative at this point in space (or NULL) 8400 . u_x - The field derivatives at this point in space 8401 . aOff - The offset of each auxiliary field in u[] 8402 . aOff_x - The offset of each auxiliary field in u_x[] 8403 . a - The auxiliary field values at this point in space 8404 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8405 . a_x - The auxiliary field derivatives at this point in space 8406 . t - The current time 8407 . x - The coordinates of this point 8408 . n - The face normal 8409 . numConstants - The number of constants 8410 . constants - The value of each constant 8411 - f - The value of the function at this point in space 8412 8413 Note: 8414 There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 8415 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 8416 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8417 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8418 8419 Level: intermediate 8420 8421 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8422 @*/ 8423 PetscErrorCode DMProjectBdFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 8424 void (**funcs)(PetscInt, PetscInt, PetscInt, 8425 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8426 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8427 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8428 InsertMode mode, Vec localX) 8429 { 8430 PetscErrorCode ierr; 8431 8432 PetscFunctionBegin; 8433 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8434 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 8435 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 8436 if (!dm->ops->projectbdfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectBdFieldLabelLocal",((PetscObject)dm)->type_name); 8437 ierr = (dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 8438 PetscFunctionReturn(0); 8439 } 8440 8441 /*@C 8442 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 8443 8444 Input Parameters: 8445 + dm - The DM 8446 . time - The time 8447 . funcs - The functions to evaluate for each field component 8448 . ctxs - Optional array of contexts to pass to each function, or NULL. 8449 - X - The coefficient vector u_h, a global vector 8450 8451 Output Parameter: 8452 . diff - The diff ||u - u_h||_2 8453 8454 Level: developer 8455 8456 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 8457 @*/ 8458 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 8459 { 8460 PetscErrorCode ierr; 8461 8462 PetscFunctionBegin; 8463 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8464 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8465 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 8466 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 8467 PetscFunctionReturn(0); 8468 } 8469 8470 /*@C 8471 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 8472 8473 Collective on dm 8474 8475 Input Parameters: 8476 + dm - The DM 8477 , time - The time 8478 . funcs - The gradient functions to evaluate for each field component 8479 . ctxs - Optional array of contexts to pass to each function, or NULL. 8480 . X - The coefficient vector u_h, a global vector 8481 - n - The vector to project along 8482 8483 Output Parameter: 8484 . diff - The diff ||(grad u - grad u_h) . n||_2 8485 8486 Level: developer 8487 8488 .seealso: DMProjectFunction(), DMComputeL2Diff() 8489 @*/ 8490 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) 8491 { 8492 PetscErrorCode ierr; 8493 8494 PetscFunctionBegin; 8495 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8496 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8497 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 8498 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 8499 PetscFunctionReturn(0); 8500 } 8501 8502 /*@C 8503 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 8504 8505 Collective on dm 8506 8507 Input Parameters: 8508 + dm - The DM 8509 . time - The time 8510 . funcs - The functions to evaluate for each field component 8511 . ctxs - Optional array of contexts to pass to each function, or NULL. 8512 - X - The coefficient vector u_h, a global vector 8513 8514 Output Parameter: 8515 . diff - The array of differences, ||u^f - u^f_h||_2 8516 8517 Level: developer 8518 8519 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 8520 @*/ 8521 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 8522 { 8523 PetscErrorCode ierr; 8524 8525 PetscFunctionBegin; 8526 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8527 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8528 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 8529 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 8530 PetscFunctionReturn(0); 8531 } 8532 8533 /*@C 8534 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 8535 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 8536 8537 Collective on dm 8538 8539 Input parameters: 8540 + dm - the pre-adaptation DM object 8541 - label - label with the flags 8542 8543 Output parameters: 8544 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 8545 8546 Level: intermediate 8547 8548 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 8549 @*/ 8550 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 8551 { 8552 PetscErrorCode ierr; 8553 8554 PetscFunctionBegin; 8555 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8556 PetscValidPointer(label,2); 8557 PetscValidPointer(dmAdapt,3); 8558 *dmAdapt = NULL; 8559 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 8560 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 8561 PetscFunctionReturn(0); 8562 } 8563 8564 /*@C 8565 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 8566 8567 Input Parameters: 8568 + dm - The DM object 8569 . metric - The metric to which the mesh is adapted, defined vertex-wise. 8570 - 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_". 8571 8572 Output Parameter: 8573 . dmAdapt - Pointer to the DM object containing the adapted mesh 8574 8575 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 8576 8577 Level: advanced 8578 8579 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 8580 @*/ 8581 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 8582 { 8583 PetscErrorCode ierr; 8584 8585 PetscFunctionBegin; 8586 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8587 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 8588 if (bdLabel) PetscValidPointer(bdLabel, 3); 8589 PetscValidPointer(dmAdapt, 4); 8590 *dmAdapt = NULL; 8591 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 8592 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 8593 PetscFunctionReturn(0); 8594 } 8595 8596 /*@C 8597 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 8598 8599 Not Collective 8600 8601 Input Parameter: 8602 . dm - The DM 8603 8604 Output Parameters: 8605 + nranks - the number of neighbours 8606 - ranks - the neighbors ranks 8607 8608 Notes: 8609 Do not free the array, it is freed when the DM is destroyed. 8610 8611 Level: beginner 8612 8613 .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks() 8614 @*/ 8615 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 8616 { 8617 PetscErrorCode ierr; 8618 8619 PetscFunctionBegin; 8620 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8621 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 8622 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 8623 PetscFunctionReturn(0); 8624 } 8625 8626 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 8627 8628 /* 8629 Converts the input vector to a ghosted vector and then calls the standard coloring code. 8630 This has be a different function because it requires DM which is not defined in the Mat library 8631 */ 8632 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 8633 { 8634 PetscErrorCode ierr; 8635 8636 PetscFunctionBegin; 8637 if (coloring->ctype == IS_COLORING_LOCAL) { 8638 Vec x1local; 8639 DM dm; 8640 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 8641 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 8642 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 8643 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 8644 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 8645 x1 = x1local; 8646 } 8647 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 8648 if (coloring->ctype == IS_COLORING_LOCAL) { 8649 DM dm; 8650 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 8651 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 8652 } 8653 PetscFunctionReturn(0); 8654 } 8655 8656 /*@ 8657 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 8658 8659 Input Parameter: 8660 . coloring - the MatFDColoring object 8661 8662 Developer Notes: 8663 this routine exists because the PETSc Mat library does not know about the DM objects 8664 8665 Level: advanced 8666 8667 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 8668 @*/ 8669 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 8670 { 8671 PetscFunctionBegin; 8672 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 8673 PetscFunctionReturn(0); 8674 } 8675 8676 /*@ 8677 DMGetCompatibility - determine if two DMs are compatible 8678 8679 Collective 8680 8681 Input Parameters: 8682 + dm1 - the first DM 8683 - dm2 - the second DM 8684 8685 Output Parameters: 8686 + compatible - whether or not the two DMs are compatible 8687 - set - whether or not the compatible value was set 8688 8689 Notes: 8690 Two DMs are deemed compatible if they represent the same parallel decomposition 8691 of the same topology. This implies that the section (field data) on one 8692 "makes sense" with respect to the topology and parallel decomposition of the other. 8693 Loosely speaking, compatible DMs represent the same domain and parallel 8694 decomposition, but hold different data. 8695 8696 Typically, one would confirm compatibility if intending to simultaneously iterate 8697 over a pair of vectors obtained from different DMs. 8698 8699 For example, two DMDA objects are compatible if they have the same local 8700 and global sizes and the same stencil width. They can have different numbers 8701 of degrees of freedom per node. Thus, one could use the node numbering from 8702 either DM in bounds for a loop over vectors derived from either DM. 8703 8704 Consider the operation of summing data living on a 2-dof DMDA to data living 8705 on a 1-dof DMDA, which should be compatible, as in the following snippet. 8706 .vb 8707 ... 8708 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 8709 if (set && compatible) { 8710 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 8711 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 8712 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 8713 for (j=y; j<y+n; ++j) { 8714 for (i=x; i<x+m, ++i) { 8715 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 8716 } 8717 } 8718 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 8719 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 8720 } else { 8721 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 8722 } 8723 ... 8724 .ve 8725 8726 Checking compatibility might be expensive for a given implementation of DM, 8727 or might be impossible to unambiguously confirm or deny. For this reason, 8728 this function may decline to determine compatibility, and hence users should 8729 always check the "set" output parameter. 8730 8731 A DM is always compatible with itself. 8732 8733 In the current implementation, DMs which live on "unequal" communicators 8734 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 8735 incompatible. 8736 8737 This function is labeled "Collective," as information about all subdomains 8738 is required on each rank. However, in DM implementations which store all this 8739 information locally, this function may be merely "Logically Collective". 8740 8741 Developer Notes: 8742 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 8743 iff B is compatible with A. Thus, this function checks the implementations 8744 of both dm and dmc (if they are of different types), attempting to determine 8745 compatibility. It is left to DM implementers to ensure that symmetry is 8746 preserved. The simplest way to do this is, when implementing type-specific 8747 logic for this function, is to check for existing logic in the implementation 8748 of other DM types and let *set = PETSC_FALSE if found. 8749 8750 Level: advanced 8751 8752 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 8753 @*/ 8754 8755 PetscErrorCode DMGetCompatibility(DM dm1,DM dm2,PetscBool *compatible,PetscBool *set) 8756 { 8757 PetscErrorCode ierr; 8758 PetscMPIInt compareResult; 8759 DMType type,type2; 8760 PetscBool sameType; 8761 8762 PetscFunctionBegin; 8763 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 8764 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 8765 8766 /* Declare a DM compatible with itself */ 8767 if (dm1 == dm2) { 8768 *set = PETSC_TRUE; 8769 *compatible = PETSC_TRUE; 8770 PetscFunctionReturn(0); 8771 } 8772 8773 /* Declare a DM incompatible with a DM that lives on an "unequal" 8774 communicator. Note that this does not preclude compatibility with 8775 DMs living on "congruent" or "similar" communicators, but this must be 8776 determined by the implementation-specific logic */ 8777 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm1),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr); 8778 if (compareResult == MPI_UNEQUAL) { 8779 *set = PETSC_TRUE; 8780 *compatible = PETSC_FALSE; 8781 PetscFunctionReturn(0); 8782 } 8783 8784 /* Pass to the implementation-specific routine, if one exists. */ 8785 if (dm1->ops->getcompatibility) { 8786 ierr = (*dm1->ops->getcompatibility)(dm1,dm2,compatible,set);CHKERRQ(ierr); 8787 if (*set) PetscFunctionReturn(0); 8788 } 8789 8790 /* If dm1 and dm2 are of different types, then attempt to check compatibility 8791 with an implementation of this function from dm2 */ 8792 ierr = DMGetType(dm1,&type);CHKERRQ(ierr); 8793 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 8794 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 8795 if (!sameType && dm2->ops->getcompatibility) { 8796 ierr = (*dm2->ops->getcompatibility)(dm2,dm1,compatible,set);CHKERRQ(ierr); /* Note argument order */ 8797 } else { 8798 *set = PETSC_FALSE; 8799 } 8800 PetscFunctionReturn(0); 8801 } 8802 8803 /*@C 8804 DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance. 8805 8806 Logically Collective on DM 8807 8808 Input Parameters: 8809 + DM - the DM 8810 . f - the monitor function 8811 . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired) 8812 - monitordestroy - [optional] routine that frees monitor context (may be NULL) 8813 8814 Options Database Keys: 8815 - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but 8816 does not cancel those set via the options database. 8817 8818 Notes: 8819 Several different monitoring routines may be set by calling 8820 DMMonitorSet() multiple times; all will be called in the 8821 order in which they were set. 8822 8823 Fortran Notes: 8824 Only a single monitor function can be set for each DM object 8825 8826 Level: intermediate 8827 8828 .seealso: DMMonitorCancel() 8829 @*/ 8830 PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**)) 8831 { 8832 PetscInt m; 8833 PetscErrorCode ierr; 8834 8835 PetscFunctionBegin; 8836 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8837 for (m = 0; m < dm->numbermonitors; ++m) { 8838 PetscBool identical; 8839 8840 ierr = PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);CHKERRQ(ierr); 8841 if (identical) PetscFunctionReturn(0); 8842 } 8843 if (dm->numbermonitors >= MAXDMMONITORS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 8844 dm->monitor[dm->numbermonitors] = f; 8845 dm->monitordestroy[dm->numbermonitors] = monitordestroy; 8846 dm->monitorcontext[dm->numbermonitors++] = (void *) mctx; 8847 PetscFunctionReturn(0); 8848 } 8849 8850 /*@ 8851 DMMonitorCancel - Clears all the monitor functions for a DM object. 8852 8853 Logically Collective on DM 8854 8855 Input Parameter: 8856 . dm - the DM 8857 8858 Options Database Key: 8859 . -dm_monitor_cancel - cancels all monitors that have been hardwired 8860 into a code by calls to DMonitorSet(), but does not cancel those 8861 set via the options database 8862 8863 Notes: 8864 There is no way to clear one specific monitor from a DM object. 8865 8866 Level: intermediate 8867 8868 .seealso: DMMonitorSet() 8869 @*/ 8870 PetscErrorCode DMMonitorCancel(DM dm) 8871 { 8872 PetscErrorCode ierr; 8873 PetscInt m; 8874 8875 PetscFunctionBegin; 8876 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8877 for (m = 0; m < dm->numbermonitors; ++m) { 8878 if (dm->monitordestroy[m]) {ierr = (*dm->monitordestroy[m])(&dm->monitorcontext[m]);CHKERRQ(ierr);} 8879 } 8880 dm->numbermonitors = 0; 8881 PetscFunctionReturn(0); 8882 } 8883 8884 /*@C 8885 DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 8886 8887 Collective on DM 8888 8889 Input Parameters: 8890 + dm - DM object you wish to monitor 8891 . name - the monitor type one is seeking 8892 . help - message indicating what monitoring is done 8893 . manual - manual page for the monitor 8894 . monitor - the monitor function 8895 - 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 8896 8897 Output Parameter: 8898 . flg - Flag set if the monitor was created 8899 8900 Level: developer 8901 8902 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 8903 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 8904 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 8905 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 8906 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 8907 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 8908 PetscOptionsFList(), PetscOptionsEList() 8909 @*/ 8910 PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg) 8911 { 8912 PetscViewer viewer; 8913 PetscViewerFormat format; 8914 PetscErrorCode ierr; 8915 8916 PetscFunctionBegin; 8917 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8918 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);CHKERRQ(ierr); 8919 if (*flg) { 8920 PetscViewerAndFormat *vf; 8921 8922 ierr = PetscViewerAndFormatCreate(viewer, format, &vf);CHKERRQ(ierr); 8923 ierr = PetscObjectDereference((PetscObject) viewer);CHKERRQ(ierr); 8924 if (monitorsetup) {ierr = (*monitorsetup)(dm, vf);CHKERRQ(ierr);} 8925 ierr = DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr); 8926 } 8927 PetscFunctionReturn(0); 8928 } 8929 8930 /*@ 8931 DMMonitor - runs the user provided monitor routines, if they exist 8932 8933 Collective on DM 8934 8935 Input Parameters: 8936 . dm - The DM 8937 8938 Level: developer 8939 8940 .seealso: DMMonitorSet() 8941 @*/ 8942 PetscErrorCode DMMonitor(DM dm) 8943 { 8944 PetscInt m; 8945 PetscErrorCode ierr; 8946 8947 PetscFunctionBegin; 8948 if (!dm) PetscFunctionReturn(0); 8949 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8950 for (m = 0; m < dm->numbermonitors; ++m) { 8951 ierr = (*dm->monitor[m])(dm, dm->monitorcontext[m]);CHKERRQ(ierr); 8952 } 8953 PetscFunctionReturn(0); 8954 } 8955