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