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