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