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