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