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