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