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","INVALID","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) {ierr = PetscDSSetJetDegree(dm->probs[s].ds, 0, k);CHKERRQ(ierr);} 5672 } 5673 /* Setup DSes */ 5674 if (doSetup) { 5675 for (s = 0; s < dm->Nds; ++s) {ierr = PetscDSSetUp(dm->probs[s].ds);CHKERRQ(ierr);} 5676 } 5677 PetscFunctionReturn(0); 5678 } 5679 5680 /*@ 5681 DMComputeExactSolution - Compute the exact solution for a given DM, using the PetscDS information. 5682 5683 Collective on DM 5684 5685 Input Parameters: 5686 + dm - The DM 5687 - time - The time 5688 5689 Output Parameters: 5690 + u - The vector will be filled with exact solution values, or NULL 5691 - u_t - The vector will be filled with the time derivative of exact solution values, or NULL 5692 5693 Note: The user must call PetscDSSetExactSolution() beforehand 5694 5695 Level: developer 5696 5697 .seealso: PetscDSSetExactSolution() 5698 @*/ 5699 PetscErrorCode DMComputeExactSolution(DM dm, PetscReal time, Vec u, Vec u_t) 5700 { 5701 PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx); 5702 void **ectxs; 5703 PetscInt Nf, Nds, s; 5704 PetscErrorCode ierr; 5705 5706 PetscFunctionBegin; 5707 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5708 if (u) PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 5709 if (u_t) PetscValidHeaderSpecific(u_t, VEC_CLASSID, 4); 5710 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 5711 ierr = PetscMalloc2(Nf, &exacts, Nf, &ectxs);CHKERRQ(ierr); 5712 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5713 for (s = 0; s < Nds; ++s) { 5714 PetscDS ds; 5715 DMLabel label; 5716 IS fieldIS; 5717 const PetscInt *fields, id = 1; 5718 PetscInt dsNf, f; 5719 5720 ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 5721 ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 5722 ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr); 5723 ierr = PetscArrayzero(exacts, Nf);CHKERRQ(ierr); 5724 ierr = PetscArrayzero(ectxs, Nf);CHKERRQ(ierr); 5725 if (u) { 5726 for (f = 0; f < dsNf; ++f) { 5727 const PetscInt field = fields[f]; 5728 ierr = PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr); 5729 } 5730 ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 5731 if (label) { 5732 ierr = DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); 5733 } else { 5734 ierr = DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); 5735 } 5736 } 5737 if (u_t) { 5738 ierr = PetscArrayzero(exacts, Nf);CHKERRQ(ierr); 5739 ierr = PetscArrayzero(ectxs, Nf);CHKERRQ(ierr); 5740 for (f = 0; f < dsNf; ++f) { 5741 const PetscInt field = fields[f]; 5742 ierr = PetscDSGetExactSolutionTimeDerivative(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr); 5743 } 5744 ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 5745 if (label) { 5746 ierr = DMProjectFunctionLabel(dm, time, label, 1, &id, 0, NULL, exacts, ectxs, INSERT_ALL_VALUES, u_t);CHKERRQ(ierr); 5747 } else { 5748 ierr = DMProjectFunction(dm, time, exacts, ectxs, INSERT_ALL_VALUES, u_t);CHKERRQ(ierr); 5749 } 5750 } 5751 } 5752 if (u) { 5753 ierr = PetscObjectSetName((PetscObject) u, "Exact Solution");CHKERRQ(ierr); 5754 ierr = PetscObjectSetOptionsPrefix((PetscObject) u, "exact_");CHKERRQ(ierr); 5755 } 5756 if (u_t) { 5757 ierr = PetscObjectSetName((PetscObject) u, "Exact Solution Time Derivative");CHKERRQ(ierr); 5758 ierr = PetscObjectSetOptionsPrefix((PetscObject) u_t, "exact_t_");CHKERRQ(ierr); 5759 } 5760 ierr = PetscFree2(exacts, ectxs);CHKERRQ(ierr); 5761 PetscFunctionReturn(0); 5762 } 5763 5764 PetscErrorCode DMTransferDS_Internal(DM dm, DMLabel label, IS fields, PetscDS ds) 5765 { 5766 PetscDS dsNew; 5767 DSBoundary b; 5768 PetscInt cdim, Nf, f; 5769 void *ctx; 5770 PetscErrorCode ierr; 5771 5772 PetscFunctionBegin; 5773 ierr = PetscDSCreate(PetscObjectComm((PetscObject) ds), &dsNew);CHKERRQ(ierr); 5774 ierr = PetscDSCopyConstants(ds, dsNew);CHKERRQ(ierr); 5775 ierr = PetscDSCopyExactSolutions(ds, dsNew);CHKERRQ(ierr); 5776 ierr = PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, dsNew);CHKERRQ(ierr); 5777 ierr = PetscDSCopyEquations(ds, dsNew);CHKERRQ(ierr); 5778 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 5779 for (f = 0; f < Nf; ++f) { 5780 ierr = PetscDSGetContext(ds, f, &ctx);CHKERRQ(ierr); 5781 ierr = PetscDSSetContext(dsNew, f, ctx);CHKERRQ(ierr); 5782 } 5783 if (Nf) { 5784 ierr = PetscDSGetCoordinateDimension(ds, &cdim);CHKERRQ(ierr); 5785 ierr = PetscDSSetCoordinateDimension(dsNew, cdim);CHKERRQ(ierr); 5786 } 5787 ierr = PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew);CHKERRQ(ierr); 5788 for (b = dsNew->boundary; b; b = b->next) { 5789 ierr = DMGetLabel(dm, b->lname, &b->label);CHKERRQ(ierr); 5790 /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */ 5791 //if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name); 5792 } 5793 5794 ierr = DMSetRegionDS(dm, label, fields, dsNew);CHKERRQ(ierr); 5795 ierr = PetscDSDestroy(&dsNew);CHKERRQ(ierr); 5796 PetscFunctionReturn(0); 5797 } 5798 5799 /*@ 5800 DMCopyDS - Copy the discrete systems for the DM into another DM 5801 5802 Collective on dm 5803 5804 Input Parameter: 5805 . dm - The DM 5806 5807 Output Parameter: 5808 . newdm - The DM 5809 5810 Level: advanced 5811 5812 .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5813 @*/ 5814 PetscErrorCode DMCopyDS(DM dm, DM newdm) 5815 { 5816 PetscInt Nds, s; 5817 PetscErrorCode ierr; 5818 5819 PetscFunctionBegin; 5820 if (dm == newdm) PetscFunctionReturn(0); 5821 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5822 ierr = DMClearDS(newdm);CHKERRQ(ierr); 5823 for (s = 0; s < Nds; ++s) { 5824 DMLabel label; 5825 IS fields; 5826 PetscDS ds, newds; 5827 PetscInt Nbd, bd; 5828 5829 ierr = DMGetRegionNumDS(dm, s, &label, &fields, &ds);CHKERRQ(ierr); 5830 ierr = DMTransferDS_Internal(newdm, label, fields, ds);CHKERRQ(ierr); 5831 /* Commplete new labels in the new DS */ 5832 ierr = DMGetRegionDS(newdm, label, NULL, &newds);CHKERRQ(ierr); 5833 ierr = PetscDSGetNumBoundary(newds, &Nbd);CHKERRQ(ierr); 5834 for (bd = 0; bd < Nbd; ++bd) { 5835 DMLabel label; 5836 PetscInt field; 5837 5838 ierr = PetscDSGetBoundary(newds, bd, NULL, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5839 ierr = DMCompleteBoundaryLabel_Internal(newdm, newds, field, bd, label);CHKERRQ(ierr); 5840 } 5841 } 5842 PetscFunctionReturn(0); 5843 } 5844 5845 /*@ 5846 DMCopyDisc - Copy the fields and discrete systems for the DM into another DM 5847 5848 Collective on dm 5849 5850 Input Parameter: 5851 . dm - The DM 5852 5853 Output Parameter: 5854 . newdm - The DM 5855 5856 Level: advanced 5857 5858 .seealso: DMCopyFields(), DMCopyDS() 5859 @*/ 5860 PetscErrorCode DMCopyDisc(DM dm, DM newdm) 5861 { 5862 PetscErrorCode ierr; 5863 5864 PetscFunctionBegin; 5865 ierr = DMCopyFields(dm, newdm);CHKERRQ(ierr); 5866 ierr = DMCopyDS(dm, newdm);CHKERRQ(ierr); 5867 PetscFunctionReturn(0); 5868 } 5869 5870 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 5871 { 5872 DM dm_coord,dmc_coord; 5873 PetscErrorCode ierr; 5874 Vec coords,ccoords; 5875 Mat inject; 5876 PetscFunctionBegin; 5877 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5878 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 5879 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5880 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 5881 if (coords && !ccoords) { 5882 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 5883 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5884 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 5885 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 5886 ierr = MatDestroy(&inject);CHKERRQ(ierr); 5887 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 5888 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5889 } 5890 PetscFunctionReturn(0); 5891 } 5892 5893 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 5894 { 5895 DM dm_coord,subdm_coord; 5896 PetscErrorCode ierr; 5897 Vec coords,ccoords,clcoords; 5898 VecScatter *scat_i,*scat_g; 5899 PetscFunctionBegin; 5900 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5901 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 5902 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5903 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 5904 if (coords && !ccoords) { 5905 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 5906 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5907 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 5908 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 5909 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 5910 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5911 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5912 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5913 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5914 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 5915 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 5916 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 5917 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 5918 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5919 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 5920 ierr = PetscFree(scat_i);CHKERRQ(ierr); 5921 ierr = PetscFree(scat_g);CHKERRQ(ierr); 5922 } 5923 PetscFunctionReturn(0); 5924 } 5925 5926 /*@ 5927 DMGetDimension - Return the topological dimension of the DM 5928 5929 Not collective 5930 5931 Input Parameter: 5932 . dm - The DM 5933 5934 Output Parameter: 5935 . dim - The topological dimension 5936 5937 Level: beginner 5938 5939 .seealso: DMSetDimension(), DMCreate() 5940 @*/ 5941 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 5942 { 5943 PetscFunctionBegin; 5944 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5945 PetscValidIntPointer(dim, 2); 5946 *dim = dm->dim; 5947 PetscFunctionReturn(0); 5948 } 5949 5950 /*@ 5951 DMSetDimension - Set the topological dimension of the DM 5952 5953 Collective on dm 5954 5955 Input Parameters: 5956 + dm - The DM 5957 - dim - The topological dimension 5958 5959 Level: beginner 5960 5961 .seealso: DMGetDimension(), DMCreate() 5962 @*/ 5963 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 5964 { 5965 PetscDS ds; 5966 PetscInt Nds, n; 5967 PetscErrorCode ierr; 5968 5969 PetscFunctionBegin; 5970 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5971 PetscValidLogicalCollectiveInt(dm, dim, 2); 5972 dm->dim = dim; 5973 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5974 for (n = 0; n < Nds; ++n) { 5975 ierr = DMGetRegionNumDS(dm, n, NULL, NULL, &ds);CHKERRQ(ierr); 5976 if (ds->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr);} 5977 } 5978 PetscFunctionReturn(0); 5979 } 5980 5981 /*@ 5982 DMGetDimPoints - Get the half-open interval for all points of a given dimension 5983 5984 Collective on dm 5985 5986 Input Parameters: 5987 + dm - the DM 5988 - dim - the dimension 5989 5990 Output Parameters: 5991 + pStart - The first point of the given dimension 5992 - pEnd - The first point following points of the given dimension 5993 5994 Note: 5995 The points are vertices in the Hasse diagram encoding the topology. This is explained in 5996 https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme, 5997 then the interval is empty. 5998 5999 Level: intermediate 6000 6001 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 6002 @*/ 6003 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 6004 { 6005 PetscInt d; 6006 PetscErrorCode ierr; 6007 6008 PetscFunctionBegin; 6009 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6010 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 6011 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 6012 if (!dm->ops->getdimpoints) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DM type %s does not implement DMGetDimPoints",((PetscObject)dm)->type_name); 6013 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 6014 PetscFunctionReturn(0); 6015 } 6016 6017 /*@ 6018 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 6019 6020 Collective on dm 6021 6022 Input Parameters: 6023 + dm - the DM 6024 - c - coordinate vector 6025 6026 Notes: 6027 The coordinates do include those for ghost points, which are in the local vector. 6028 6029 The vector c should be destroyed by the caller. 6030 6031 Level: intermediate 6032 6033 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMDASetUniformCoordinates() 6034 @*/ 6035 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 6036 { 6037 PetscErrorCode ierr; 6038 6039 PetscFunctionBegin; 6040 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6041 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 6042 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 6043 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 6044 dm->coordinates = c; 6045 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 6046 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 6047 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 6048 PetscFunctionReturn(0); 6049 } 6050 6051 /*@ 6052 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 6053 6054 Not collective 6055 6056 Input Parameters: 6057 + dm - the DM 6058 - c - coordinate vector 6059 6060 Notes: 6061 The coordinates of ghost points can be set using DMSetCoordinates() 6062 followed by DMGetCoordinatesLocal(). This is intended to enable the 6063 setting of ghost coordinates outside of the domain. 6064 6065 The vector c should be destroyed by the caller. 6066 6067 Level: intermediate 6068 6069 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 6070 @*/ 6071 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 6072 { 6073 PetscErrorCode ierr; 6074 6075 PetscFunctionBegin; 6076 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6077 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 6078 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 6079 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 6080 6081 dm->coordinatesLocal = c; 6082 6083 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 6084 PetscFunctionReturn(0); 6085 } 6086 6087 /*@ 6088 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 6089 6090 Collective on dm 6091 6092 Input Parameter: 6093 . dm - the DM 6094 6095 Output Parameter: 6096 . c - global coordinate vector 6097 6098 Note: 6099 This is a borrowed reference, so the user should NOT destroy this vector. When the DM is 6100 destroyed the array will no longer be valid. 6101 6102 Each process has only the locally-owned portion of the global coordinates (does NOT have the ghost coordinates). 6103 6104 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6105 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6106 6107 Level: intermediate 6108 6109 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMDASetUniformCoordinates() 6110 @*/ 6111 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 6112 { 6113 PetscErrorCode ierr; 6114 6115 PetscFunctionBegin; 6116 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6117 PetscValidPointer(c,2); 6118 if (!dm->coordinates && dm->coordinatesLocal) { 6119 DM cdm = NULL; 6120 PetscBool localized; 6121 6122 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6123 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 6124 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 6125 /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */ 6126 if (localized) { 6127 PetscInt cdim; 6128 6129 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 6130 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 6131 } 6132 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 6133 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 6134 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 6135 } 6136 *c = dm->coordinates; 6137 PetscFunctionReturn(0); 6138 } 6139 6140 /*@ 6141 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 6142 6143 Collective on dm 6144 6145 Input Parameter: 6146 . dm - the DM 6147 6148 Level: advanced 6149 6150 .seealso: DMGetCoordinatesLocalNoncollective() 6151 @*/ 6152 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 6153 { 6154 PetscErrorCode ierr; 6155 6156 PetscFunctionBegin; 6157 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6158 if (!dm->coordinatesLocal && dm->coordinates) { 6159 DM cdm = NULL; 6160 PetscBool localized; 6161 6162 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6163 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 6164 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 6165 /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */ 6166 if (localized) { 6167 PetscInt cdim; 6168 6169 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 6170 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 6171 } 6172 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 6173 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 6174 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 6175 } 6176 PetscFunctionReturn(0); 6177 } 6178 6179 /*@ 6180 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 6181 6182 Collective on dm 6183 6184 Input Parameter: 6185 . dm - the DM 6186 6187 Output Parameter: 6188 . c - coordinate vector 6189 6190 Note: 6191 This is a borrowed reference, so the user should NOT destroy this vector 6192 6193 Each process has the local and ghost coordinates 6194 6195 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6196 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6197 6198 Level: intermediate 6199 6200 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 6201 @*/ 6202 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 6203 { 6204 PetscErrorCode ierr; 6205 6206 PetscFunctionBegin; 6207 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6208 PetscValidPointer(c,2); 6209 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 6210 *c = dm->coordinatesLocal; 6211 PetscFunctionReturn(0); 6212 } 6213 6214 /*@ 6215 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 6216 6217 Not collective 6218 6219 Input Parameter: 6220 . dm - the DM 6221 6222 Output Parameter: 6223 . c - coordinate vector 6224 6225 Level: advanced 6226 6227 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 6228 @*/ 6229 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 6230 { 6231 PetscFunctionBegin; 6232 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6233 PetscValidPointer(c,2); 6234 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 6235 *c = dm->coordinatesLocal; 6236 PetscFunctionReturn(0); 6237 } 6238 6239 /*@ 6240 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 6241 6242 Not collective 6243 6244 Input Parameter: 6245 + dm - the DM 6246 - p - the IS of points whose coordinates will be returned 6247 6248 Output Parameter: 6249 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 6250 - pCoord - the Vec with coordinates of points in p 6251 6252 Note: 6253 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 6254 6255 This creates a new vector, so the user SHOULD destroy this vector 6256 6257 Each process has the local and ghost coordinates 6258 6259 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6260 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6261 6262 Level: advanced 6263 6264 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 6265 @*/ 6266 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 6267 { 6268 PetscSection cs, newcs; 6269 Vec coords; 6270 const PetscScalar *arr; 6271 PetscScalar *newarr=NULL; 6272 PetscInt n; 6273 PetscErrorCode ierr; 6274 6275 PetscFunctionBegin; 6276 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6277 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 6278 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 6279 if (pCoord) PetscValidPointer(pCoord, 4); 6280 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 6281 if (!dm->coordinateDM || !dm->coordinateDM->localSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 6282 cs = dm->coordinateDM->localSection; 6283 coords = dm->coordinatesLocal; 6284 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 6285 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 6286 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 6287 if (pCoord) { 6288 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 6289 /* set array in two steps to mimic PETSC_OWN_POINTER */ 6290 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 6291 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 6292 } else { 6293 ierr = PetscFree(newarr);CHKERRQ(ierr); 6294 } 6295 if (pCoordSection) {*pCoordSection = newcs;} 6296 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 6297 PetscFunctionReturn(0); 6298 } 6299 6300 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 6301 { 6302 PetscErrorCode ierr; 6303 6304 PetscFunctionBegin; 6305 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6306 PetscValidPointer(field,2); 6307 if (!dm->coordinateField) { 6308 if (dm->ops->createcoordinatefield) { 6309 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 6310 } 6311 } 6312 *field = dm->coordinateField; 6313 PetscFunctionReturn(0); 6314 } 6315 6316 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 6317 { 6318 PetscErrorCode ierr; 6319 6320 PetscFunctionBegin; 6321 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6322 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 6323 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 6324 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 6325 dm->coordinateField = field; 6326 PetscFunctionReturn(0); 6327 } 6328 6329 /*@ 6330 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 6331 6332 Collective on dm 6333 6334 Input Parameter: 6335 . dm - the DM 6336 6337 Output Parameter: 6338 . cdm - coordinate DM 6339 6340 Level: intermediate 6341 6342 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 6343 @*/ 6344 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 6345 { 6346 PetscErrorCode ierr; 6347 6348 PetscFunctionBegin; 6349 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6350 PetscValidPointer(cdm,2); 6351 if (!dm->coordinateDM) { 6352 DM cdm; 6353 6354 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 6355 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 6356 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 6357 * until the call to CreateCoordinateDM) */ 6358 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 6359 dm->coordinateDM = cdm; 6360 } 6361 *cdm = dm->coordinateDM; 6362 PetscFunctionReturn(0); 6363 } 6364 6365 /*@ 6366 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 6367 6368 Logically Collective on dm 6369 6370 Input Parameters: 6371 + dm - the DM 6372 - cdm - coordinate DM 6373 6374 Level: intermediate 6375 6376 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 6377 @*/ 6378 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 6379 { 6380 PetscErrorCode ierr; 6381 6382 PetscFunctionBegin; 6383 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6384 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 6385 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 6386 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 6387 dm->coordinateDM = cdm; 6388 PetscFunctionReturn(0); 6389 } 6390 6391 /*@ 6392 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 6393 6394 Not Collective 6395 6396 Input Parameter: 6397 . dm - The DM object 6398 6399 Output Parameter: 6400 . dim - The embedding dimension 6401 6402 Level: intermediate 6403 6404 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 6405 @*/ 6406 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 6407 { 6408 PetscFunctionBegin; 6409 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6410 PetscValidIntPointer(dim, 2); 6411 if (dm->dimEmbed == PETSC_DEFAULT) { 6412 dm->dimEmbed = dm->dim; 6413 } 6414 *dim = dm->dimEmbed; 6415 PetscFunctionReturn(0); 6416 } 6417 6418 /*@ 6419 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 6420 6421 Not Collective 6422 6423 Input Parameters: 6424 + dm - The DM object 6425 - dim - The embedding dimension 6426 6427 Level: intermediate 6428 6429 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 6430 @*/ 6431 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 6432 { 6433 PetscDS ds; 6434 PetscInt Nds, n; 6435 PetscErrorCode ierr; 6436 6437 PetscFunctionBegin; 6438 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6439 dm->dimEmbed = dim; 6440 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 6441 for (n = 0; n < Nds; ++n) { 6442 ierr = DMGetRegionNumDS(dm, n, NULL, NULL, &ds);CHKERRQ(ierr); 6443 ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr); 6444 } 6445 PetscFunctionReturn(0); 6446 } 6447 6448 /*@ 6449 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 6450 6451 Collective on dm 6452 6453 Input Parameter: 6454 . dm - The DM object 6455 6456 Output Parameter: 6457 . section - The PetscSection object 6458 6459 Level: intermediate 6460 6461 .seealso: DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 6462 @*/ 6463 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 6464 { 6465 DM cdm; 6466 PetscErrorCode ierr; 6467 6468 PetscFunctionBegin; 6469 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6470 PetscValidPointer(section, 2); 6471 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6472 ierr = DMGetLocalSection(cdm, section);CHKERRQ(ierr); 6473 PetscFunctionReturn(0); 6474 } 6475 6476 /*@ 6477 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 6478 6479 Not Collective 6480 6481 Input Parameters: 6482 + dm - The DM object 6483 . dim - The embedding dimension, or PETSC_DETERMINE 6484 - section - The PetscSection object 6485 6486 Level: intermediate 6487 6488 .seealso: DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 6489 @*/ 6490 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 6491 { 6492 DM cdm; 6493 PetscErrorCode ierr; 6494 6495 PetscFunctionBegin; 6496 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6497 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 6498 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6499 ierr = DMSetLocalSection(cdm, section);CHKERRQ(ierr); 6500 if (dim == PETSC_DETERMINE) { 6501 PetscInt d = PETSC_DEFAULT; 6502 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 6503 6504 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6505 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6506 pStart = PetscMax(vStart, pStart); 6507 pEnd = PetscMin(vEnd, pEnd); 6508 for (v = pStart; v < pEnd; ++v) { 6509 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 6510 if (dd) {d = dd; break;} 6511 } 6512 if (d >= 0) {ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);} 6513 } 6514 PetscFunctionReturn(0); 6515 } 6516 6517 /*@ 6518 DMProjectCoordinates - Project coordinates to a different space 6519 6520 Input Parameters: 6521 + dm - The DM object 6522 - disc - The new coordinate discretization 6523 6524 Level: intermediate 6525 6526 .seealso: DMGetCoordinateField() 6527 @*/ 6528 PetscErrorCode DMProjectCoordinates(DM dm, PetscFE disc) 6529 { 6530 PetscObject discOld; 6531 PetscClassId classid; 6532 DM cdmOld,cdmNew; 6533 Vec coordsOld,coordsNew; 6534 Mat matInterp; 6535 PetscErrorCode ierr; 6536 6537 PetscFunctionBegin; 6538 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6539 PetscValidHeaderSpecific(disc,PETSCFE_CLASSID,2); 6540 6541 ierr = DMGetCoordinateDM(dm, &cdmOld);CHKERRQ(ierr); 6542 /* Check current discretization is compatible */ 6543 ierr = DMGetField(cdmOld, 0, NULL, &discOld);CHKERRQ(ierr); 6544 ierr = PetscObjectGetClassId(discOld, &classid);CHKERRQ(ierr); 6545 if (classid != PETSCFE_CLASSID) { 6546 if (classid == PETSC_CONTAINER_CLASSID) { 6547 PetscFE feLinear; 6548 DMPolytopeType ct; 6549 PetscInt dim, dE, cStart; 6550 PetscBool simplex; 6551 6552 /* Assume linear vertex coordinates */ 6553 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6554 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 6555 ierr = DMPlexGetHeightStratum(cdmOld, 0, &cStart, NULL);CHKERRQ(ierr); 6556 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 6557 switch (ct) { 6558 case DM_POLYTOPE_TRI_PRISM: 6559 case DM_POLYTOPE_TRI_PRISM_TENSOR: 6560 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot autoamtically create coordinate space for prisms"); 6561 default: break; 6562 } 6563 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 6564 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, 1, -1, &feLinear);CHKERRQ(ierr); 6565 ierr = DMSetField(cdmOld, 0, NULL, (PetscObject) feLinear);CHKERRQ(ierr); 6566 ierr = PetscFEDestroy(&feLinear);CHKERRQ(ierr); 6567 ierr = DMCreateDS(cdmOld);CHKERRQ(ierr); 6568 } else { 6569 const char *discname; 6570 6571 ierr = PetscObjectGetType(discOld, &discname);CHKERRQ(ierr); 6572 SETERRQ1(PetscObjectComm(discOld), PETSC_ERR_SUP, "Discretization type %s not supported", discname); 6573 } 6574 } 6575 /* Make a fresh clone of the coordinate DM */ 6576 ierr = DMClone(cdmOld, &cdmNew);CHKERRQ(ierr); 6577 ierr = DMSetField(cdmNew, 0, NULL, (PetscObject) disc);CHKERRQ(ierr); 6578 ierr = DMCreateDS(cdmNew);CHKERRQ(ierr); 6579 /* Project the coordinate vector from old to new space */ 6580 ierr = DMGetCoordinates(dm, &coordsOld);CHKERRQ(ierr); 6581 ierr = DMCreateGlobalVector(cdmNew, &coordsNew);CHKERRQ(ierr); 6582 ierr = DMCreateInterpolation(cdmOld, cdmNew, &matInterp, NULL);CHKERRQ(ierr); 6583 ierr = MatInterpolate(matInterp, coordsOld, coordsNew);CHKERRQ(ierr); 6584 ierr = MatDestroy(&matInterp);CHKERRQ(ierr); 6585 /* Set new coordinate structures */ 6586 ierr = DMSetCoordinateField(dm, NULL);CHKERRQ(ierr); 6587 ierr = DMSetCoordinateDM(dm, cdmNew);CHKERRQ(ierr); 6588 ierr = DMSetCoordinates(dm, coordsNew);CHKERRQ(ierr); 6589 ierr = VecDestroy(&coordsNew);CHKERRQ(ierr); 6590 ierr = DMDestroy(&cdmNew);CHKERRQ(ierr); 6591 PetscFunctionReturn(0); 6592 } 6593 6594 /*@C 6595 DMGetPeriodicity - Get the description of mesh periodicity 6596 6597 Input Parameters: 6598 . dm - The DM object 6599 6600 Output Parameters: 6601 + per - Whether the DM is periodic or not 6602 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 6603 . L - If we assume the mesh is a torus, this is the length of each coordinate 6604 - bd - This describes the type of periodicity in each topological dimension 6605 6606 Level: developer 6607 6608 .seealso: DMGetPeriodicity() 6609 @*/ 6610 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 6611 { 6612 PetscFunctionBegin; 6613 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6614 if (per) *per = dm->periodic; 6615 if (L) *L = dm->L; 6616 if (maxCell) *maxCell = dm->maxCell; 6617 if (bd) *bd = dm->bdtype; 6618 PetscFunctionReturn(0); 6619 } 6620 6621 /*@C 6622 DMSetPeriodicity - Set the description of mesh periodicity 6623 6624 Input Parameters: 6625 + dm - The DM object 6626 . per - Whether the DM is periodic or not. 6627 . 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. 6628 . L - If we assume the mesh is a torus, this is the length of each coordinate 6629 - bd - This describes the type of periodicity in each topological dimension 6630 6631 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. 6632 6633 Level: developer 6634 6635 .seealso: DMGetPeriodicity() 6636 @*/ 6637 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 6638 { 6639 PetscInt dim, d; 6640 PetscErrorCode ierr; 6641 6642 PetscFunctionBegin; 6643 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6644 PetscValidLogicalCollectiveBool(dm,per,2); 6645 if (maxCell) {PetscValidRealPointer(maxCell,3);} 6646 if (L) {PetscValidRealPointer(L,4);} 6647 if (bd) {PetscValidPointer(bd,5);} 6648 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6649 if (maxCell) { 6650 if (!dm->maxCell) {ierr = PetscMalloc1(dim, &dm->maxCell);CHKERRQ(ierr);} 6651 for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d]; 6652 } else { /* remove maxCell information to disable automatic computation of localized vertices */ 6653 ierr = PetscFree(dm->maxCell);CHKERRQ(ierr); 6654 } 6655 6656 if (L) { 6657 if (!dm->L) {ierr = PetscMalloc1(dim, &dm->L);CHKERRQ(ierr);} 6658 for (d = 0; d < dim; ++d) dm->L[d] = L[d]; 6659 } 6660 if (bd) { 6661 if (!dm->bdtype) {ierr = PetscMalloc1(dim, &dm->bdtype);CHKERRQ(ierr);} 6662 for (d = 0; d < dim; ++d) dm->bdtype[d] = bd[d]; 6663 } 6664 dm->periodic = per; 6665 PetscFunctionReturn(0); 6666 } 6667 6668 /*@ 6669 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. 6670 6671 Input Parameters: 6672 + dm - The DM 6673 . in - The input coordinate point (dim numbers) 6674 - endpoint - Include the endpoint L_i 6675 6676 Output Parameter: 6677 . out - The localized coordinate point 6678 6679 Level: developer 6680 6681 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6682 @*/ 6683 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 6684 { 6685 PetscInt dim, d; 6686 PetscErrorCode ierr; 6687 6688 PetscFunctionBegin; 6689 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 6690 if (!dm->maxCell) { 6691 for (d = 0; d < dim; ++d) out[d] = in[d]; 6692 } else { 6693 if (endpoint) { 6694 for (d = 0; d < dim; ++d) { 6695 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)) { 6696 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 6697 } else { 6698 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6699 } 6700 } 6701 } else { 6702 for (d = 0; d < dim; ++d) { 6703 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6704 } 6705 } 6706 } 6707 PetscFunctionReturn(0); 6708 } 6709 6710 /* 6711 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. 6712 6713 Input Parameters: 6714 + dm - The DM 6715 . dim - The spatial dimension 6716 . anchor - The anchor point, the input point can be no more than maxCell away from it 6717 - in - The input coordinate point (dim numbers) 6718 6719 Output Parameter: 6720 . out - The localized coordinate point 6721 6722 Level: developer 6723 6724 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 6725 6726 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6727 */ 6728 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6729 { 6730 PetscInt d; 6731 6732 PetscFunctionBegin; 6733 if (!dm->maxCell) { 6734 for (d = 0; d < dim; ++d) out[d] = in[d]; 6735 } else { 6736 for (d = 0; d < dim; ++d) { 6737 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 6738 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6739 } else { 6740 out[d] = in[d]; 6741 } 6742 } 6743 } 6744 PetscFunctionReturn(0); 6745 } 6746 6747 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 6748 { 6749 PetscInt d; 6750 6751 PetscFunctionBegin; 6752 if (!dm->maxCell) { 6753 for (d = 0; d < dim; ++d) out[d] = in[d]; 6754 } else { 6755 for (d = 0; d < dim; ++d) { 6756 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 6757 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6758 } else { 6759 out[d] = in[d]; 6760 } 6761 } 6762 } 6763 PetscFunctionReturn(0); 6764 } 6765 6766 /* 6767 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. 6768 6769 Input Parameters: 6770 + dm - The DM 6771 . dim - The spatial dimension 6772 . anchor - The anchor point, the input point can be no more than maxCell away from it 6773 . in - The input coordinate delta (dim numbers) 6774 - out - The input coordinate point (dim numbers) 6775 6776 Output Parameter: 6777 . out - The localized coordinate in + out 6778 6779 Level: developer 6780 6781 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 6782 6783 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 6784 */ 6785 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6786 { 6787 PetscInt d; 6788 6789 PetscFunctionBegin; 6790 if (!dm->maxCell) { 6791 for (d = 0; d < dim; ++d) out[d] += in[d]; 6792 } else { 6793 for (d = 0; d < dim; ++d) { 6794 const PetscReal maxC = dm->maxCell[d]; 6795 6796 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) { 6797 const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6798 6799 if (PetscAbsScalar(newCoord - anchor[d]) > maxC) 6800 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])); 6801 out[d] += newCoord; 6802 } else { 6803 out[d] += in[d]; 6804 } 6805 } 6806 } 6807 PetscFunctionReturn(0); 6808 } 6809 6810 /*@ 6811 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 6812 6813 Not collective 6814 6815 Input Parameter: 6816 . dm - The DM 6817 6818 Output Parameter: 6819 areLocalized - True if localized 6820 6821 Level: developer 6822 6823 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 6824 @*/ 6825 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 6826 { 6827 DM cdm; 6828 PetscSection coordSection; 6829 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 6830 PetscBool isPlex, alreadyLocalized; 6831 PetscErrorCode ierr; 6832 6833 PetscFunctionBegin; 6834 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6835 PetscValidBoolPointer(areLocalized, 2); 6836 *areLocalized = PETSC_FALSE; 6837 6838 /* We need some generic way of refering to cells/vertices */ 6839 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6840 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 6841 if (!isPlex) PetscFunctionReturn(0); 6842 6843 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6844 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6845 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 6846 alreadyLocalized = PETSC_FALSE; 6847 for (c = cStart; c < cEnd; ++c) { 6848 if (c < sStart || c >= sEnd) continue; 6849 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 6850 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 6851 } 6852 *areLocalized = alreadyLocalized; 6853 PetscFunctionReturn(0); 6854 } 6855 6856 /*@ 6857 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 6858 6859 Collective on dm 6860 6861 Input Parameter: 6862 . dm - The DM 6863 6864 Output Parameter: 6865 areLocalized - True if localized 6866 6867 Level: developer 6868 6869 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 6870 @*/ 6871 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 6872 { 6873 PetscBool localized; 6874 PetscErrorCode ierr; 6875 6876 PetscFunctionBegin; 6877 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6878 PetscValidBoolPointer(areLocalized, 2); 6879 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 6880 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 6881 PetscFunctionReturn(0); 6882 } 6883 6884 /*@ 6885 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 6886 6887 Collective on dm 6888 6889 Input Parameter: 6890 . dm - The DM 6891 6892 Level: developer 6893 6894 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 6895 @*/ 6896 PetscErrorCode DMLocalizeCoordinates(DM dm) 6897 { 6898 DM cdm; 6899 PetscSection coordSection, cSection; 6900 Vec coordinates, cVec; 6901 PetscScalar *coords, *coords2, *anchor, *localized; 6902 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 6903 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 6904 PetscInt maxHeight = 0, h; 6905 PetscInt *pStart = NULL, *pEnd = NULL; 6906 PetscErrorCode ierr; 6907 6908 PetscFunctionBegin; 6909 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6910 if (!dm->periodic) PetscFunctionReturn(0); 6911 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 6912 if (alreadyLocalized) PetscFunctionReturn(0); 6913 6914 /* We need some generic way of refering to cells/vertices */ 6915 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6916 { 6917 PetscBool isplex; 6918 6919 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 6920 if (isplex) { 6921 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6922 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 6923 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6924 pEnd = &pStart[maxHeight + 1]; 6925 newStart = vStart; 6926 newEnd = vEnd; 6927 for (h = 0; h <= maxHeight; h++) { 6928 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 6929 newStart = PetscMin(newStart,pStart[h]); 6930 newEnd = PetscMax(newEnd,pEnd[h]); 6931 } 6932 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 6933 } 6934 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6935 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 6936 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6937 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 6938 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 6939 6940 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 6941 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 6942 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 6943 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 6944 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 6945 6946 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6947 localized = &anchor[bs]; 6948 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 6949 for (h = 0; h <= maxHeight; h++) { 6950 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6951 6952 for (c = cStart; c < cEnd; ++c) { 6953 PetscScalar *cellCoords = NULL; 6954 PetscInt b; 6955 6956 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 6957 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6958 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6959 for (d = 0; d < dof/bs; ++d) { 6960 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 6961 for (b = 0; b < bs; b++) { 6962 if (cellCoords[d*bs + b] != localized[b]) break; 6963 } 6964 if (b < bs) break; 6965 } 6966 if (d < dof/bs) { 6967 if (c >= sStart && c < sEnd) { 6968 PetscInt cdof; 6969 6970 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 6971 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 6972 } 6973 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 6974 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 6975 } 6976 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6977 } 6978 } 6979 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 6980 if (alreadyLocalizedGlobal) { 6981 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6982 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6983 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6984 PetscFunctionReturn(0); 6985 } 6986 for (v = vStart; v < vEnd; ++v) { 6987 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6988 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 6989 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 6990 } 6991 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 6992 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 6993 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 6994 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 6995 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 6996 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 6997 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 6998 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6999 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 7000 for (v = vStart; v < vEnd; ++v) { 7001 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 7002 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 7003 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 7004 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 7005 } 7006 for (h = 0; h <= maxHeight; h++) { 7007 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 7008 7009 for (c = cStart; c < cEnd; ++c) { 7010 PetscScalar *cellCoords = NULL; 7011 PetscInt b, cdof; 7012 7013 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 7014 if (!cdof) continue; 7015 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7016 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 7017 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 7018 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 7019 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7020 } 7021 } 7022 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7023 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7024 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 7025 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 7026 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 7027 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 7028 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 7029 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 7030 PetscFunctionReturn(0); 7031 } 7032 7033 /*@ 7034 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 7035 7036 Collective on v (see explanation below) 7037 7038 Input Parameters: 7039 + dm - The DM 7040 . v - The Vec of points 7041 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 7042 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 7043 7044 Output Parameter: 7045 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 7046 - cells - The PetscSF containing the ranks and local indices of the containing points. 7047 7048 7049 Level: developer 7050 7051 Notes: 7052 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 7053 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 7054 7055 If *cellSF is NULL on input, a PetscSF will be created. 7056 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 7057 7058 An array that maps each point to its containing cell can be obtained with 7059 7060 $ const PetscSFNode *cells; 7061 $ PetscInt nFound; 7062 $ const PetscInt *found; 7063 $ 7064 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 7065 7066 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 7067 the index of the cell in its rank's local numbering. 7068 7069 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 7070 @*/ 7071 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 7072 { 7073 PetscErrorCode ierr; 7074 7075 PetscFunctionBegin; 7076 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7077 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 7078 PetscValidPointer(cellSF,4); 7079 if (*cellSF) { 7080 PetscMPIInt result; 7081 7082 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 7083 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRMPI(ierr); 7084 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 7085 } else { 7086 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 7087 } 7088 if (!dm->ops->locatepoints) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 7089 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 7090 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 7091 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 7092 PetscFunctionReturn(0); 7093 } 7094 7095 /*@ 7096 DMGetOutputDM - Retrieve the DM associated with the layout for output 7097 7098 Collective on dm 7099 7100 Input Parameter: 7101 . dm - The original DM 7102 7103 Output Parameter: 7104 . odm - The DM which provides the layout for output 7105 7106 Level: intermediate 7107 7108 .seealso: VecView(), DMGetGlobalSection() 7109 @*/ 7110 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 7111 { 7112 PetscSection section; 7113 PetscBool hasConstraints, ghasConstraints; 7114 PetscErrorCode ierr; 7115 7116 PetscFunctionBegin; 7117 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7118 PetscValidPointer(odm,2); 7119 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 7120 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 7121 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 7122 if (!ghasConstraints) { 7123 *odm = dm; 7124 PetscFunctionReturn(0); 7125 } 7126 if (!dm->dmBC) { 7127 PetscSection newSection, gsection; 7128 PetscSF sf; 7129 7130 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 7131 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 7132 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 7133 ierr = DMSetLocalSection(dm->dmBC, newSection);CHKERRQ(ierr); 7134 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 7135 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 7136 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 7137 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 7138 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 7139 } 7140 *odm = dm->dmBC; 7141 PetscFunctionReturn(0); 7142 } 7143 7144 /*@ 7145 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 7146 7147 Input Parameter: 7148 . dm - The original DM 7149 7150 Output Parameters: 7151 + num - The output sequence number 7152 - val - The output sequence value 7153 7154 Level: intermediate 7155 7156 Note: This is intended for output that should appear in sequence, for instance 7157 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7158 7159 .seealso: VecView() 7160 @*/ 7161 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 7162 { 7163 PetscFunctionBegin; 7164 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7165 if (num) {PetscValidIntPointer(num,2); *num = dm->outputSequenceNum;} 7166 if (val) {PetscValidRealPointer(val,3);*val = dm->outputSequenceVal;} 7167 PetscFunctionReturn(0); 7168 } 7169 7170 /*@ 7171 DMSetOutputSequenceNumber - Set the sequence number/value for output 7172 7173 Input Parameters: 7174 + dm - The original DM 7175 . num - The output sequence number 7176 - val - The output sequence value 7177 7178 Level: intermediate 7179 7180 Note: This is intended for output that should appear in sequence, for instance 7181 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7182 7183 .seealso: VecView() 7184 @*/ 7185 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 7186 { 7187 PetscFunctionBegin; 7188 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7189 dm->outputSequenceNum = num; 7190 dm->outputSequenceVal = val; 7191 PetscFunctionReturn(0); 7192 } 7193 7194 /*@C 7195 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 7196 7197 Input Parameters: 7198 + dm - The original DM 7199 . name - The sequence name 7200 - num - The output sequence number 7201 7202 Output Parameter: 7203 . val - The output sequence value 7204 7205 Level: intermediate 7206 7207 Note: This is intended for output that should appear in sequence, for instance 7208 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7209 7210 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 7211 @*/ 7212 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 7213 { 7214 PetscBool ishdf5; 7215 PetscErrorCode ierr; 7216 7217 PetscFunctionBegin; 7218 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7219 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 7220 PetscValidRealPointer(val,4); 7221 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 7222 if (ishdf5) { 7223 #if defined(PETSC_HAVE_HDF5) 7224 PetscScalar value; 7225 7226 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 7227 *val = PetscRealPart(value); 7228 #endif 7229 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 7230 PetscFunctionReturn(0); 7231 } 7232 7233 /*@ 7234 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 7235 7236 Not collective 7237 7238 Input Parameter: 7239 . dm - The DM 7240 7241 Output Parameter: 7242 . useNatural - The flag to build the mapping to a natural order during distribution 7243 7244 Level: beginner 7245 7246 .seealso: DMSetUseNatural(), DMCreate() 7247 @*/ 7248 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 7249 { 7250 PetscFunctionBegin; 7251 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7252 PetscValidBoolPointer(useNatural, 2); 7253 *useNatural = dm->useNatural; 7254 PetscFunctionReturn(0); 7255 } 7256 7257 /*@ 7258 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 7259 7260 Collective on dm 7261 7262 Input Parameters: 7263 + dm - The DM 7264 - useNatural - The flag to build the mapping to a natural order during distribution 7265 7266 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 7267 7268 Level: beginner 7269 7270 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 7271 @*/ 7272 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 7273 { 7274 PetscFunctionBegin; 7275 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7276 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 7277 dm->useNatural = useNatural; 7278 PetscFunctionReturn(0); 7279 } 7280 7281 7282 /*@C 7283 DMCreateLabel - Create a label of the given name if it does not already exist 7284 7285 Not Collective 7286 7287 Input Parameters: 7288 + dm - The DM object 7289 - name - The label name 7290 7291 Level: intermediate 7292 7293 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7294 @*/ 7295 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 7296 { 7297 PetscBool flg; 7298 DMLabel label; 7299 PetscErrorCode ierr; 7300 7301 PetscFunctionBegin; 7302 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7303 PetscValidCharPointer(name, 2); 7304 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 7305 if (!flg) { 7306 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 7307 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 7308 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 7309 } 7310 PetscFunctionReturn(0); 7311 } 7312 7313 /*@C 7314 DMCreateLabelAtIndex - Create a label of the given name at the iven index. If it already exists, move it to this index. 7315 7316 Not Collective 7317 7318 Input Parameters: 7319 + dm - The DM object 7320 . l - The index for the label 7321 - name - The label name 7322 7323 Level: intermediate 7324 7325 .seealso: DMCreateLabel(), DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7326 @*/ 7327 PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[]) 7328 { 7329 DMLabelLink orig, prev = NULL; 7330 DMLabel label; 7331 PetscInt Nl, m; 7332 PetscBool flg, match; 7333 const char *lname; 7334 PetscErrorCode ierr; 7335 7336 PetscFunctionBegin; 7337 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7338 PetscValidCharPointer(name, 2); 7339 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 7340 if (!flg) { 7341 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 7342 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 7343 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 7344 } 7345 ierr = DMGetNumLabels(dm, &Nl);CHKERRQ(ierr); 7346 if (l >= Nl) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %D must be in [0, %D)", l, Nl); 7347 for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) { 7348 ierr = PetscObjectGetName((PetscObject) orig->label, &lname);CHKERRQ(ierr); 7349 ierr = PetscStrcmp(name, lname, &match);CHKERRQ(ierr); 7350 if (match) break; 7351 } 7352 if (m == l) PetscFunctionReturn(0); 7353 if (!m) dm->labels = orig->next; 7354 else prev->next = orig->next; 7355 if (!l) { 7356 orig->next = dm->labels; 7357 dm->labels = orig; 7358 } else { 7359 for (m = 0, prev = dm->labels; m < l-1; ++m, prev = prev->next); 7360 orig->next = prev->next; 7361 prev->next = orig; 7362 } 7363 PetscFunctionReturn(0); 7364 } 7365 7366 /*@C 7367 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 7368 7369 Not Collective 7370 7371 Input Parameters: 7372 + dm - The DM object 7373 . name - The label name 7374 - point - The mesh point 7375 7376 Output Parameter: 7377 . value - The label value for this point, or -1 if the point is not in the label 7378 7379 Level: beginner 7380 7381 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 7382 @*/ 7383 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 7384 { 7385 DMLabel label; 7386 PetscErrorCode ierr; 7387 7388 PetscFunctionBegin; 7389 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7390 PetscValidCharPointer(name, 2); 7391 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7392 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 7393 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 7394 PetscFunctionReturn(0); 7395 } 7396 7397 /*@C 7398 DMSetLabelValue - Add a point to a Sieve Label with given value 7399 7400 Not Collective 7401 7402 Input Parameters: 7403 + dm - The DM object 7404 . name - The label name 7405 . point - The mesh point 7406 - value - The label value for this point 7407 7408 Output Parameter: 7409 7410 Level: beginner 7411 7412 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 7413 @*/ 7414 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7415 { 7416 DMLabel label; 7417 PetscErrorCode ierr; 7418 7419 PetscFunctionBegin; 7420 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7421 PetscValidCharPointer(name, 2); 7422 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7423 if (!label) { 7424 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 7425 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7426 } 7427 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 7428 PetscFunctionReturn(0); 7429 } 7430 7431 /*@C 7432 DMClearLabelValue - Remove a point from a Sieve Label with given value 7433 7434 Not Collective 7435 7436 Input Parameters: 7437 + dm - The DM object 7438 . name - The label name 7439 . point - The mesh point 7440 - value - The label value for this point 7441 7442 Output Parameter: 7443 7444 Level: beginner 7445 7446 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 7447 @*/ 7448 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7449 { 7450 DMLabel label; 7451 PetscErrorCode ierr; 7452 7453 PetscFunctionBegin; 7454 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7455 PetscValidCharPointer(name, 2); 7456 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7457 if (!label) PetscFunctionReturn(0); 7458 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 7459 PetscFunctionReturn(0); 7460 } 7461 7462 /*@C 7463 DMGetLabelSize - Get the number of different integer ids in a Label 7464 7465 Not Collective 7466 7467 Input Parameters: 7468 + dm - The DM object 7469 - name - The label name 7470 7471 Output Parameter: 7472 . size - The number of different integer ids, or 0 if the label does not exist 7473 7474 Level: beginner 7475 7476 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 7477 @*/ 7478 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 7479 { 7480 DMLabel label; 7481 PetscErrorCode ierr; 7482 7483 PetscFunctionBegin; 7484 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7485 PetscValidCharPointer(name, 2); 7486 PetscValidIntPointer(size, 3); 7487 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7488 *size = 0; 7489 if (!label) PetscFunctionReturn(0); 7490 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 7491 PetscFunctionReturn(0); 7492 } 7493 7494 /*@C 7495 DMGetLabelIdIS - Get the integer ids in a label 7496 7497 Not Collective 7498 7499 Input Parameters: 7500 + mesh - The DM object 7501 - name - The label name 7502 7503 Output Parameter: 7504 . ids - The integer ids, or NULL if the label does not exist 7505 7506 Level: beginner 7507 7508 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 7509 @*/ 7510 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 7511 { 7512 DMLabel label; 7513 PetscErrorCode ierr; 7514 7515 PetscFunctionBegin; 7516 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7517 PetscValidCharPointer(name, 2); 7518 PetscValidPointer(ids, 3); 7519 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7520 *ids = NULL; 7521 if (label) { 7522 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 7523 } else { 7524 /* returning an empty IS */ 7525 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 7526 } 7527 PetscFunctionReturn(0); 7528 } 7529 7530 /*@C 7531 DMGetStratumSize - Get the number of points in a label stratum 7532 7533 Not Collective 7534 7535 Input Parameters: 7536 + dm - The DM object 7537 . name - The label name 7538 - value - The stratum value 7539 7540 Output Parameter: 7541 . size - The stratum size 7542 7543 Level: beginner 7544 7545 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 7546 @*/ 7547 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 7548 { 7549 DMLabel label; 7550 PetscErrorCode ierr; 7551 7552 PetscFunctionBegin; 7553 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7554 PetscValidCharPointer(name, 2); 7555 PetscValidIntPointer(size, 4); 7556 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7557 *size = 0; 7558 if (!label) PetscFunctionReturn(0); 7559 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 7560 PetscFunctionReturn(0); 7561 } 7562 7563 /*@C 7564 DMGetStratumIS - Get the points in a label stratum 7565 7566 Not Collective 7567 7568 Input Parameters: 7569 + dm - The DM object 7570 . name - The label name 7571 - value - The stratum value 7572 7573 Output Parameter: 7574 . points - The stratum points, or NULL if the label does not exist or does not have that value 7575 7576 Level: beginner 7577 7578 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 7579 @*/ 7580 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 7581 { 7582 DMLabel label; 7583 PetscErrorCode ierr; 7584 7585 PetscFunctionBegin; 7586 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7587 PetscValidCharPointer(name, 2); 7588 PetscValidPointer(points, 4); 7589 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7590 *points = NULL; 7591 if (!label) PetscFunctionReturn(0); 7592 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 7593 PetscFunctionReturn(0); 7594 } 7595 7596 /*@C 7597 DMSetStratumIS - Set the points in a label stratum 7598 7599 Not Collective 7600 7601 Input Parameters: 7602 + dm - The DM object 7603 . name - The label name 7604 . value - The stratum value 7605 - points - The stratum points 7606 7607 Level: beginner 7608 7609 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 7610 @*/ 7611 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 7612 { 7613 DMLabel label; 7614 PetscErrorCode ierr; 7615 7616 PetscFunctionBegin; 7617 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7618 PetscValidCharPointer(name, 2); 7619 PetscValidPointer(points, 4); 7620 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7621 if (!label) PetscFunctionReturn(0); 7622 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 7623 PetscFunctionReturn(0); 7624 } 7625 7626 /*@C 7627 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 7628 7629 Not Collective 7630 7631 Input Parameters: 7632 + dm - The DM object 7633 . name - The label name 7634 - value - The label value for this point 7635 7636 Output Parameter: 7637 7638 Level: beginner 7639 7640 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 7641 @*/ 7642 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 7643 { 7644 DMLabel label; 7645 PetscErrorCode ierr; 7646 7647 PetscFunctionBegin; 7648 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7649 PetscValidCharPointer(name, 2); 7650 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7651 if (!label) PetscFunctionReturn(0); 7652 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 7653 PetscFunctionReturn(0); 7654 } 7655 7656 /*@ 7657 DMGetNumLabels - Return the number of labels defined by the mesh 7658 7659 Not Collective 7660 7661 Input Parameter: 7662 . dm - The DM object 7663 7664 Output Parameter: 7665 . numLabels - the number of Labels 7666 7667 Level: intermediate 7668 7669 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7670 @*/ 7671 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 7672 { 7673 DMLabelLink next = dm->labels; 7674 PetscInt n = 0; 7675 7676 PetscFunctionBegin; 7677 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7678 PetscValidIntPointer(numLabels, 2); 7679 while (next) {++n; next = next->next;} 7680 *numLabels = n; 7681 PetscFunctionReturn(0); 7682 } 7683 7684 /*@C 7685 DMGetLabelName - Return the name of nth label 7686 7687 Not Collective 7688 7689 Input Parameters: 7690 + dm - The DM object 7691 - n - the label number 7692 7693 Output Parameter: 7694 . name - the label name 7695 7696 Level: intermediate 7697 7698 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7699 @*/ 7700 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 7701 { 7702 DMLabelLink next = dm->labels; 7703 PetscInt l = 0; 7704 PetscErrorCode ierr; 7705 7706 PetscFunctionBegin; 7707 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7708 PetscValidPointer(name, 3); 7709 while (next) { 7710 if (l == n) { 7711 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 7712 PetscFunctionReturn(0); 7713 } 7714 ++l; 7715 next = next->next; 7716 } 7717 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7718 } 7719 7720 /*@C 7721 DMHasLabel - Determine whether the mesh has a label of a given name 7722 7723 Not Collective 7724 7725 Input Parameters: 7726 + dm - The DM object 7727 - name - The label name 7728 7729 Output Parameter: 7730 . hasLabel - PETSC_TRUE if the label is present 7731 7732 Level: intermediate 7733 7734 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7735 @*/ 7736 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 7737 { 7738 DMLabelLink next = dm->labels; 7739 const char *lname; 7740 PetscErrorCode ierr; 7741 7742 PetscFunctionBegin; 7743 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7744 PetscValidCharPointer(name, 2); 7745 PetscValidBoolPointer(hasLabel, 3); 7746 *hasLabel = PETSC_FALSE; 7747 while (next) { 7748 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7749 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 7750 if (*hasLabel) break; 7751 next = next->next; 7752 } 7753 PetscFunctionReturn(0); 7754 } 7755 7756 /*@C 7757 DMGetLabel - Return the label of a given name, or NULL 7758 7759 Not Collective 7760 7761 Input Parameters: 7762 + dm - The DM object 7763 - name - The label name 7764 7765 Output Parameter: 7766 . label - The DMLabel, or NULL if the label is absent 7767 7768 Note: Some of the default labels in a DMPlex will be 7769 $ "depth" - Holds the depth (co-dimension) of each mesh point 7770 $ "celltype" - Holds the topological type of each cell 7771 $ "ghost" - If the DM is distributed with overlap, this marks the cells and faces in the overlap 7772 $ "Cell Sets" - Mirrors the cell sets defined by GMsh and ExodusII 7773 $ "Face Sets" - Mirrors the face sets defined by GMsh and ExodusII 7774 $ "Vertex Sets" - Mirrors the vertex sets defined by GMsh 7775 7776 Level: intermediate 7777 7778 .seealso: DMCreateLabel(), DMHasLabel(), DMPlexGetDepthLabel(), DMPlexGetCellType() 7779 @*/ 7780 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 7781 { 7782 DMLabelLink next = dm->labels; 7783 PetscBool hasLabel; 7784 const char *lname; 7785 PetscErrorCode ierr; 7786 7787 PetscFunctionBegin; 7788 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7789 PetscValidCharPointer(name, 2); 7790 PetscValidPointer(label, 3); 7791 *label = NULL; 7792 while (next) { 7793 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7794 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7795 if (hasLabel) { 7796 *label = next->label; 7797 break; 7798 } 7799 next = next->next; 7800 } 7801 PetscFunctionReturn(0); 7802 } 7803 7804 /*@C 7805 DMGetLabelByNum - Return the nth label 7806 7807 Not Collective 7808 7809 Input Parameters: 7810 + dm - The DM object 7811 - n - the label number 7812 7813 Output Parameter: 7814 . label - the label 7815 7816 Level: intermediate 7817 7818 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7819 @*/ 7820 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 7821 { 7822 DMLabelLink next = dm->labels; 7823 PetscInt l = 0; 7824 7825 PetscFunctionBegin; 7826 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7827 PetscValidPointer(label, 3); 7828 while (next) { 7829 if (l == n) { 7830 *label = next->label; 7831 PetscFunctionReturn(0); 7832 } 7833 ++l; 7834 next = next->next; 7835 } 7836 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7837 } 7838 7839 /*@C 7840 DMAddLabel - Add the label to this mesh 7841 7842 Not Collective 7843 7844 Input Parameters: 7845 + dm - The DM object 7846 - label - The DMLabel 7847 7848 Level: developer 7849 7850 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7851 @*/ 7852 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 7853 { 7854 DMLabelLink l, *p, tmpLabel; 7855 PetscBool hasLabel; 7856 const char *lname; 7857 PetscBool flg; 7858 PetscErrorCode ierr; 7859 7860 PetscFunctionBegin; 7861 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7862 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 7863 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 7864 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 7865 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 7866 tmpLabel->label = label; 7867 tmpLabel->output = PETSC_TRUE; 7868 for (p=&dm->labels; (l=*p); p=&l->next) {} 7869 *p = tmpLabel; 7870 ierr = PetscObjectReference((PetscObject)label);CHKERRQ(ierr); 7871 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 7872 if (flg) dm->depthLabel = label; 7873 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 7874 if (flg) dm->celltypeLabel = label; 7875 PetscFunctionReturn(0); 7876 } 7877 7878 /*@C 7879 DMRemoveLabel - Remove the label given by name from this mesh 7880 7881 Not Collective 7882 7883 Input Parameters: 7884 + dm - The DM object 7885 - name - The label name 7886 7887 Output Parameter: 7888 . label - The DMLabel, or NULL if the label is absent 7889 7890 Level: developer 7891 7892 Notes: 7893 DMRemoveLabel(dm,name,NULL) removes the label from dm and calls 7894 DMLabelDestroy() on the label. 7895 7896 DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT 7897 call DMLabelDestroy(). Instead, the label is returned and the user is 7898 responsible of calling DMLabelDestroy() at some point. 7899 7900 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf() 7901 @*/ 7902 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 7903 { 7904 DMLabelLink link, *pnext; 7905 PetscBool hasLabel; 7906 const char *lname; 7907 PetscErrorCode ierr; 7908 7909 PetscFunctionBegin; 7910 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7911 PetscValidCharPointer(name, 2); 7912 if (label) { 7913 PetscValidPointer(label, 3); 7914 *label = NULL; 7915 } 7916 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7917 ierr = PetscObjectGetName((PetscObject) link->label, &lname);CHKERRQ(ierr); 7918 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7919 if (hasLabel) { 7920 *pnext = link->next; /* Remove from list */ 7921 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 7922 if (hasLabel) dm->depthLabel = NULL; 7923 ierr = PetscStrcmp(name, "celltype", &hasLabel);CHKERRQ(ierr); 7924 if (hasLabel) dm->celltypeLabel = NULL; 7925 if (label) *label = link->label; 7926 else {ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);} 7927 ierr = PetscFree(link);CHKERRQ(ierr); 7928 break; 7929 } 7930 } 7931 PetscFunctionReturn(0); 7932 } 7933 7934 /*@ 7935 DMRemoveLabelBySelf - Remove the label from this mesh 7936 7937 Not Collective 7938 7939 Input Parameters: 7940 + dm - The DM object 7941 . label - (Optional) The DMLabel to be removed from the DM 7942 - failNotFound - Should it fail if the label is not found in the DM? 7943 7944 Level: developer 7945 7946 Notes: 7947 Only exactly the same instance is removed if found, name match is ignored. 7948 If the DM has an exclusive reference to the label, it gets destroyed and 7949 *label nullified. 7950 7951 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel() 7952 @*/ 7953 PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound) 7954 { 7955 DMLabelLink link, *pnext; 7956 PetscBool hasLabel = PETSC_FALSE; 7957 PetscErrorCode ierr; 7958 7959 PetscFunctionBegin; 7960 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7961 PetscValidPointer(label, 2); 7962 if (!*label && !failNotFound) PetscFunctionReturn(0); 7963 PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2); 7964 PetscValidLogicalCollectiveBool(dm,failNotFound,3); 7965 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 7966 if (*label == link->label) { 7967 hasLabel = PETSC_TRUE; 7968 *pnext = link->next; /* Remove from list */ 7969 if (*label == dm->depthLabel) dm->depthLabel = NULL; 7970 if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL; 7971 if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */ 7972 ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr); 7973 ierr = PetscFree(link);CHKERRQ(ierr); 7974 break; 7975 } 7976 } 7977 if (!hasLabel && failNotFound) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM"); 7978 PetscFunctionReturn(0); 7979 } 7980 7981 /*@C 7982 DMGetLabelOutput - Get the output flag for a given label 7983 7984 Not Collective 7985 7986 Input Parameters: 7987 + dm - The DM object 7988 - name - The label name 7989 7990 Output Parameter: 7991 . output - The flag for output 7992 7993 Level: developer 7994 7995 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7996 @*/ 7997 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 7998 { 7999 DMLabelLink next = dm->labels; 8000 const char *lname; 8001 PetscErrorCode ierr; 8002 8003 PetscFunctionBegin; 8004 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8005 PetscValidPointer(name, 2); 8006 PetscValidPointer(output, 3); 8007 while (next) { 8008 PetscBool flg; 8009 8010 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8011 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 8012 if (flg) {*output = next->output; PetscFunctionReturn(0);} 8013 next = next->next; 8014 } 8015 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 8016 } 8017 8018 /*@C 8019 DMSetLabelOutput - Set the output flag for a given label 8020 8021 Not Collective 8022 8023 Input Parameters: 8024 + dm - The DM object 8025 . name - The label name 8026 - output - The flag for output 8027 8028 Level: developer 8029 8030 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8031 @*/ 8032 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 8033 { 8034 DMLabelLink next = dm->labels; 8035 const char *lname; 8036 PetscErrorCode ierr; 8037 8038 PetscFunctionBegin; 8039 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8040 PetscValidCharPointer(name, 2); 8041 while (next) { 8042 PetscBool flg; 8043 8044 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8045 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 8046 if (flg) {next->output = output; PetscFunctionReturn(0);} 8047 next = next->next; 8048 } 8049 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 8050 } 8051 8052 /*@ 8053 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 8054 8055 Collective on dmA 8056 8057 Input Parameter: 8058 + dmA - The DM object with initial labels 8059 . dmB - The DM object with copied labels 8060 . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES) 8061 - all - Copy all labels including "depth", "dim", and "celltype" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE) 8062 8063 Level: intermediate 8064 8065 Note: This is typically used when interpolating or otherwise adding to a mesh 8066 8067 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection(), DMShareLabels() 8068 @*/ 8069 PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all) 8070 { 8071 DMLabel label, labelNew; 8072 const char *name; 8073 PetscBool flg; 8074 DMLabelLink link; 8075 PetscErrorCode ierr; 8076 8077 PetscFunctionBegin; 8078 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 8079 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 8080 PetscValidLogicalCollectiveEnum(dmA, mode,3); 8081 PetscValidLogicalCollectiveBool(dmA, all, 4); 8082 if (mode==PETSC_USE_POINTER) SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects"); 8083 if (dmA == dmB) PetscFunctionReturn(0); 8084 for (link=dmA->labels; link; link=link->next) { 8085 label=link->label; 8086 ierr = PetscObjectGetName((PetscObject)label, &name);CHKERRQ(ierr); 8087 if (!all) { 8088 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 8089 if (flg) continue; 8090 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 8091 if (flg) continue; 8092 ierr = PetscStrcmp(name, "celltype", &flg);CHKERRQ(ierr); 8093 if (flg) continue; 8094 } 8095 if (mode==PETSC_COPY_VALUES) { 8096 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 8097 } else { 8098 labelNew = label; 8099 } 8100 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 8101 if (mode==PETSC_COPY_VALUES) {ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);} 8102 } 8103 PetscFunctionReturn(0); 8104 } 8105 /* 8106 Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would 8107 like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every 8108 (label, id) pair in the DM. 8109 8110 However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to 8111 each label. 8112 */ 8113 PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal) 8114 { 8115 DMUniversalLabel ul; 8116 PetscBool *active; 8117 PetscInt pStart, pEnd, p, Nl, l, m; 8118 PetscErrorCode ierr; 8119 8120 PetscFunctionBegin; 8121 ierr = PetscMalloc1(1, &ul);CHKERRQ(ierr); 8122 ierr = DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label);CHKERRQ(ierr); 8123 ierr = DMGetNumLabels(dm, &Nl);CHKERRQ(ierr); 8124 ierr = PetscCalloc1(Nl, &active);CHKERRQ(ierr); 8125 ul->Nl = 0; 8126 for (l = 0; l < Nl; ++l) { 8127 PetscBool isdepth, iscelltype; 8128 const char *name; 8129 8130 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 8131 ierr = PetscStrncmp(name, "depth", 6, &isdepth);CHKERRQ(ierr); 8132 ierr = PetscStrncmp(name, "celltype", 9, &iscelltype);CHKERRQ(ierr); 8133 active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE; 8134 if (active[l]) ++ul->Nl; 8135 } 8136 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); 8137 ul->Nv = 0; 8138 for (l = 0, m = 0; l < Nl; ++l) { 8139 DMLabel label; 8140 PetscInt nv; 8141 const char *name; 8142 8143 if (!active[l]) continue; 8144 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 8145 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8146 ierr = DMLabelGetNumValues(label, &nv);CHKERRQ(ierr); 8147 ierr = PetscStrallocpy(name, &ul->names[m]);CHKERRQ(ierr); 8148 ul->indices[m] = l; 8149 ul->Nv += nv; 8150 ul->offsets[m+1] = nv; 8151 ul->bits[m+1] = PetscCeilReal(PetscLog2Real(nv+1)); 8152 ++m; 8153 } 8154 for (l = 1; l <= ul->Nl; ++l) { 8155 ul->offsets[l] = ul->offsets[l-1] + ul->offsets[l]; 8156 ul->bits[l] = ul->bits[l-1] + ul->bits[l]; 8157 } 8158 for (l = 0; l < ul->Nl; ++l) { 8159 PetscInt b; 8160 8161 ul->masks[l] = 0; 8162 for (b = ul->bits[l]; b < ul->bits[l+1]; ++b) ul->masks[l] |= 1 << b; 8163 } 8164 ierr = PetscMalloc1(ul->Nv, &ul->values);CHKERRQ(ierr); 8165 for (l = 0, m = 0; l < Nl; ++l) { 8166 DMLabel label; 8167 IS valueIS; 8168 const PetscInt *varr; 8169 PetscInt nv, v; 8170 8171 if (!active[l]) continue; 8172 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8173 ierr = DMLabelGetNumValues(label, &nv);CHKERRQ(ierr); 8174 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 8175 ierr = ISGetIndices(valueIS, &varr);CHKERRQ(ierr); 8176 for (v = 0; v < nv; ++v) { 8177 ul->values[ul->offsets[m]+v] = varr[v]; 8178 } 8179 ierr = ISRestoreIndices(valueIS, &varr);CHKERRQ(ierr); 8180 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 8181 ierr = PetscSortInt(nv, &ul->values[ul->offsets[m]]);CHKERRQ(ierr); 8182 ++m; 8183 } 8184 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8185 for (p = pStart; p < pEnd; ++p) { 8186 PetscInt uval = 0; 8187 PetscBool marked = PETSC_FALSE; 8188 8189 for (l = 0, m = 0; l < Nl; ++l) { 8190 DMLabel label; 8191 PetscInt val, defval, loc, nv; 8192 8193 if (!active[l]) continue; 8194 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8195 ierr = DMLabelGetValue(label, p, &val);CHKERRQ(ierr); 8196 ierr = DMLabelGetDefaultValue(label, &defval);CHKERRQ(ierr); 8197 if (val == defval) {++m; continue;} 8198 nv = ul->offsets[m+1]-ul->offsets[m]; 8199 marked = PETSC_TRUE; 8200 ierr = PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc);CHKERRQ(ierr); 8201 if (loc < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %D not found in compression array", val); 8202 uval += (loc+1) << ul->bits[m]; 8203 ++m; 8204 } 8205 if (marked) {ierr = DMLabelSetValue(ul->label, p, uval);CHKERRQ(ierr);} 8206 } 8207 ierr = PetscFree(active);CHKERRQ(ierr); 8208 *universal = ul; 8209 PetscFunctionReturn(0); 8210 } 8211 8212 PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal) 8213 { 8214 PetscInt l; 8215 PetscErrorCode ierr; 8216 8217 PetscFunctionBegin; 8218 for (l = 0; l < (*universal)->Nl; ++l) {ierr = PetscFree((*universal)->names[l]);CHKERRQ(ierr);} 8219 ierr = DMLabelDestroy(&(*universal)->label);CHKERRQ(ierr); 8220 ierr = PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks);CHKERRQ(ierr); 8221 ierr = PetscFree((*universal)->values);CHKERRQ(ierr); 8222 ierr = PetscFree(*universal);CHKERRQ(ierr); 8223 *universal = NULL; 8224 PetscFunctionReturn(0); 8225 } 8226 8227 PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel) 8228 { 8229 PetscFunctionBegin; 8230 PetscValidPointer(ulabel, 2); 8231 *ulabel = ul->label; 8232 PetscFunctionReturn(0); 8233 } 8234 8235 PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm) 8236 { 8237 PetscInt Nl = ul->Nl, l; 8238 PetscErrorCode ierr; 8239 8240 PetscFunctionBegin; 8241 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 8242 for (l = 0; l < Nl; ++l) { 8243 if (preserveOrder) {ierr = DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]);CHKERRQ(ierr);} 8244 else {ierr = DMCreateLabel(dm, ul->names[l]);CHKERRQ(ierr);} 8245 } 8246 if (preserveOrder) { 8247 for (l = 0; l < ul->Nl; ++l) { 8248 const char *name; 8249 PetscBool match; 8250 8251 ierr = DMGetLabelName(dm, ul->indices[l], &name);CHKERRQ(ierr); 8252 ierr = PetscStrcmp(name, ul->names[l], &match);CHKERRQ(ierr); 8253 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]); 8254 } 8255 } 8256 PetscFunctionReturn(0); 8257 } 8258 8259 PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value) 8260 { 8261 PetscInt l; 8262 PetscErrorCode ierr; 8263 8264 PetscFunctionBegin; 8265 for (l = 0; l < ul->Nl; ++l) { 8266 DMLabel label; 8267 PetscInt lval = (value & ul->masks[l]) >> ul->bits[l]; 8268 8269 if (lval) { 8270 if (useIndex) {ierr = DMGetLabelByNum(dm, ul->indices[l], &label);CHKERRQ(ierr);} 8271 else {ierr = DMGetLabel(dm, ul->names[l], &label);CHKERRQ(ierr);} 8272 ierr = DMLabelSetValue(label, p, ul->values[ul->offsets[l]+lval-1]);CHKERRQ(ierr); 8273 } 8274 } 8275 PetscFunctionReturn(0); 8276 } 8277 8278 /*@ 8279 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 8280 8281 Input Parameter: 8282 . dm - The DM object 8283 8284 Output Parameter: 8285 . cdm - The coarse DM 8286 8287 Level: intermediate 8288 8289 .seealso: DMSetCoarseDM() 8290 @*/ 8291 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 8292 { 8293 PetscFunctionBegin; 8294 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8295 PetscValidPointer(cdm, 2); 8296 *cdm = dm->coarseMesh; 8297 PetscFunctionReturn(0); 8298 } 8299 8300 /*@ 8301 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 8302 8303 Input Parameters: 8304 + dm - The DM object 8305 - cdm - The coarse DM 8306 8307 Level: intermediate 8308 8309 .seealso: DMGetCoarseDM() 8310 @*/ 8311 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 8312 { 8313 PetscErrorCode ierr; 8314 8315 PetscFunctionBegin; 8316 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8317 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 8318 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 8319 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 8320 dm->coarseMesh = cdm; 8321 PetscFunctionReturn(0); 8322 } 8323 8324 /*@ 8325 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 8326 8327 Input Parameter: 8328 . dm - The DM object 8329 8330 Output Parameter: 8331 . fdm - The fine DM 8332 8333 Level: intermediate 8334 8335 .seealso: DMSetFineDM() 8336 @*/ 8337 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 8338 { 8339 PetscFunctionBegin; 8340 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8341 PetscValidPointer(fdm, 2); 8342 *fdm = dm->fineMesh; 8343 PetscFunctionReturn(0); 8344 } 8345 8346 /*@ 8347 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 8348 8349 Input Parameters: 8350 + dm - The DM object 8351 - fdm - The fine DM 8352 8353 Level: intermediate 8354 8355 .seealso: DMGetFineDM() 8356 @*/ 8357 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 8358 { 8359 PetscErrorCode ierr; 8360 8361 PetscFunctionBegin; 8362 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8363 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 8364 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 8365 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 8366 dm->fineMesh = fdm; 8367 PetscFunctionReturn(0); 8368 } 8369 8370 /*=== DMBoundary code ===*/ 8371 8372 /*@C 8373 DMAddBoundary - Add a boundary condition to the model 8374 8375 Collective on dm 8376 8377 Input Parameters: 8378 + dm - The DM, with a PetscDS that matches the problem being constrained 8379 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 8380 . name - The BC name 8381 . label - The label defining constrained points 8382 . Nv - The number of DMLabel values for constrained points 8383 . values - An array of values for constrained points 8384 . field - The field to constrain 8385 . Nc - The number of constrained field components (0 will constrain all fields) 8386 . comps - An array of constrained component numbers 8387 . bcFunc - A pointwise function giving boundary values 8388 . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL 8389 - ctx - An optional user context for bcFunc 8390 8391 Output Parameter: 8392 . bd - (Optional) Boundary number 8393 8394 Options Database Keys: 8395 + -bc_<boundary name> <num> - Overrides the boundary ids 8396 - -bc_<boundary name>_comp <num> - Overrides the boundary components 8397 8398 Note: 8399 Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is: 8400 8401 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 8402 8403 If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is: 8404 8405 $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8406 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8407 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8408 $ PetscReal time, const PetscReal x[], PetscScalar bcval[]) 8409 8410 + dim - the spatial dimension 8411 . Nf - the number of fields 8412 . uOff - the offset into u[] and u_t[] for each field 8413 . uOff_x - the offset into u_x[] for each field 8414 . u - each field evaluated at the current point 8415 . u_t - the time derivative of each field evaluated at the current point 8416 . u_x - the gradient of each field evaluated at the current point 8417 . aOff - the offset into a[] and a_t[] for each auxiliary field 8418 . aOff_x - the offset into a_x[] for each auxiliary field 8419 . a - each auxiliary field evaluated at the current point 8420 . a_t - the time derivative of each auxiliary field evaluated at the current point 8421 . a_x - the gradient of auxiliary each field evaluated at the current point 8422 . t - current time 8423 . x - coordinates of the current point 8424 . numConstants - number of constant parameters 8425 . constants - constant parameters 8426 - bcval - output values at the current point 8427 8428 Level: developer 8429 8430 .seealso: DSGetBoundary(), PetscDSAddBoundary() 8431 @*/ 8432 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) 8433 { 8434 PetscDS ds; 8435 PetscErrorCode ierr; 8436 8437 PetscFunctionBegin; 8438 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8439 PetscValidLogicalCollectiveEnum(dm, type, 2); 8440 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4); 8441 PetscValidLogicalCollectiveInt(dm, Nv, 5); 8442 PetscValidLogicalCollectiveInt(dm, field, 7); 8443 PetscValidLogicalCollectiveInt(dm, Nc, 8); 8444 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 8445 ierr = DMCompleteBoundaryLabel_Internal(dm, ds, field, PETSC_MAX_INT, label);CHKERRQ(ierr); 8446 ierr = PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd);CHKERRQ(ierr); 8447 PetscFunctionReturn(0); 8448 } 8449 8450 /* TODO Remove this since now the structures are the same */ 8451 static PetscErrorCode DMPopulateBoundary(DM dm) 8452 { 8453 PetscDS ds; 8454 DMBoundary *lastnext; 8455 DSBoundary dsbound; 8456 PetscErrorCode ierr; 8457 8458 PetscFunctionBegin; 8459 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 8460 dsbound = ds->boundary; 8461 if (dm->boundary) { 8462 DMBoundary next = dm->boundary; 8463 8464 /* quick check to see if the PetscDS has changed */ 8465 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 8466 /* the PetscDS has changed: tear down and rebuild */ 8467 while (next) { 8468 DMBoundary b = next; 8469 8470 next = b->next; 8471 ierr = PetscFree(b);CHKERRQ(ierr); 8472 } 8473 dm->boundary = NULL; 8474 } 8475 8476 lastnext = &(dm->boundary); 8477 while (dsbound) { 8478 DMBoundary dmbound; 8479 8480 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 8481 dmbound->dsboundary = dsbound; 8482 dmbound->label = dsbound->label; 8483 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 8484 *lastnext = dmbound; 8485 lastnext = &(dmbound->next); 8486 dsbound = dsbound->next; 8487 } 8488 PetscFunctionReturn(0); 8489 } 8490 8491 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 8492 { 8493 DMBoundary b; 8494 PetscErrorCode ierr; 8495 8496 PetscFunctionBegin; 8497 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8498 PetscValidBoolPointer(isBd, 3); 8499 *isBd = PETSC_FALSE; 8500 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 8501 b = dm->boundary; 8502 while (b && !(*isBd)) { 8503 DMLabel label = b->label; 8504 DSBoundary dsb = b->dsboundary; 8505 PetscInt i; 8506 8507 if (label) { 8508 for (i = 0; i < dsb->Nv && !(*isBd); ++i) {ierr = DMLabelStratumHasPoint(label, dsb->values[i], point, isBd);CHKERRQ(ierr);} 8509 } 8510 b = b->next; 8511 } 8512 PetscFunctionReturn(0); 8513 } 8514 8515 /*@C 8516 DMProjectFunction - This projects the given function into the function space provided, putting the coefficients in a global vector. 8517 8518 Collective on DM 8519 8520 Input Parameters: 8521 + dm - The DM 8522 . time - The time 8523 . funcs - The coordinate functions to evaluate, one per field 8524 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8525 - mode - The insertion mode for values 8526 8527 Output Parameter: 8528 . X - vector 8529 8530 Calling sequence of func: 8531 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8532 8533 + dim - The spatial dimension 8534 . time - The time at which to sample 8535 . x - The coordinates 8536 . Nf - The number of fields 8537 . u - The output field values 8538 - ctx - optional user-defined function context 8539 8540 Level: developer 8541 8542 .seealso: DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 8543 @*/ 8544 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 8545 { 8546 Vec localX; 8547 PetscErrorCode ierr; 8548 8549 PetscFunctionBegin; 8550 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8551 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 8552 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8553 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 8554 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 8555 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 8556 PetscFunctionReturn(0); 8557 } 8558 8559 /*@C 8560 DMProjectFunctionLocal - This projects the given function into the function space provided, putting the coefficients in a local vector. 8561 8562 Not collective 8563 8564 Input Parameters: 8565 + dm - The DM 8566 . time - The time 8567 . funcs - The coordinate functions to evaluate, one per field 8568 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8569 - mode - The insertion mode for values 8570 8571 Output Parameter: 8572 . localX - vector 8573 8574 Calling sequence of func: 8575 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8576 8577 + dim - The spatial dimension 8578 . x - The coordinates 8579 . Nf - The number of fields 8580 . u - The output field values 8581 - ctx - optional user-defined function context 8582 8583 Level: developer 8584 8585 .seealso: DMProjectFunction(), DMProjectFunctionLabel(), DMComputeL2Diff() 8586 @*/ 8587 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 8588 { 8589 PetscErrorCode ierr; 8590 8591 PetscFunctionBegin; 8592 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8593 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 8594 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 8595 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8596 PetscFunctionReturn(0); 8597 } 8598 8599 /*@C 8600 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. 8601 8602 Collective on DM 8603 8604 Input Parameters: 8605 + dm - The DM 8606 . time - The time 8607 . label - The DMLabel selecting the portion of the mesh for projection 8608 . funcs - The coordinate functions to evaluate, one per field 8609 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8610 - mode - The insertion mode for values 8611 8612 Output Parameter: 8613 . X - vector 8614 8615 Calling sequence of func: 8616 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8617 8618 + dim - The spatial dimension 8619 . x - The coordinates 8620 . Nf - The number of fields 8621 . u - The output field values 8622 - ctx - optional user-defined function context 8623 8624 Level: developer 8625 8626 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal(), DMComputeL2Diff() 8627 @*/ 8628 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) 8629 { 8630 Vec localX; 8631 PetscErrorCode ierr; 8632 8633 PetscFunctionBegin; 8634 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8635 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 8636 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8637 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 8638 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 8639 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 8640 PetscFunctionReturn(0); 8641 } 8642 8643 /*@C 8644 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. 8645 8646 Not collective 8647 8648 Input Parameters: 8649 + dm - The DM 8650 . time - The time 8651 . label - The DMLabel selecting the portion of the mesh for projection 8652 . funcs - The coordinate functions to evaluate, one per field 8653 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8654 - mode - The insertion mode for values 8655 8656 Output Parameter: 8657 . localX - vector 8658 8659 Calling sequence of func: 8660 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8661 8662 + dim - The spatial dimension 8663 . x - The coordinates 8664 . Nf - The number of fields 8665 . u - The output field values 8666 - ctx - optional user-defined function context 8667 8668 Level: developer 8669 8670 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 8671 @*/ 8672 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) 8673 { 8674 PetscErrorCode ierr; 8675 8676 PetscFunctionBegin; 8677 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8678 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 8679 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 8680 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8681 PetscFunctionReturn(0); 8682 } 8683 8684 /*@C 8685 DMProjectFieldLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector. 8686 8687 Not collective 8688 8689 Input Parameters: 8690 + dm - The DM 8691 . time - The time 8692 . localU - The input field vector 8693 . funcs - The functions to evaluate, one per field 8694 - mode - The insertion mode for values 8695 8696 Output Parameter: 8697 . localX - The output vector 8698 8699 Calling sequence of func: 8700 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8701 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8702 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8703 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8704 8705 + dim - The spatial dimension 8706 . Nf - The number of input fields 8707 . NfAux - The number of input auxiliary fields 8708 . uOff - The offset of each field in u[] 8709 . uOff_x - The offset of each field in u_x[] 8710 . u - The field values at this point in space 8711 . u_t - The field time derivative at this point in space (or NULL) 8712 . u_x - The field derivatives at this point in space 8713 . aOff - The offset of each auxiliary field in u[] 8714 . aOff_x - The offset of each auxiliary field in u_x[] 8715 . a - The auxiliary field values at this point in space 8716 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8717 . a_x - The auxiliary field derivatives at this point in space 8718 . t - The current time 8719 . x - The coordinates of this point 8720 . numConstants - The number of constants 8721 . constants - The value of each constant 8722 - f - The value of the function at this point in space 8723 8724 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. 8725 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 8726 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8727 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8728 8729 Level: intermediate 8730 8731 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8732 @*/ 8733 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 8734 void (**funcs)(PetscInt, PetscInt, PetscInt, 8735 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8736 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8737 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8738 InsertMode mode, Vec localX) 8739 { 8740 PetscErrorCode ierr; 8741 8742 PetscFunctionBegin; 8743 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8744 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 8745 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 8746 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 8747 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 8748 PetscFunctionReturn(0); 8749 } 8750 8751 /*@C 8752 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. 8753 8754 Not collective 8755 8756 Input Parameters: 8757 + dm - The DM 8758 . time - The time 8759 . label - The DMLabel marking the portion of the domain to output 8760 . numIds - The number of label ids to use 8761 . ids - The label ids to use for marking 8762 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 8763 . comps - The components to set in the output, or NULL for all components 8764 . localU - The input field vector 8765 . funcs - The functions to evaluate, one per field 8766 - mode - The insertion mode for values 8767 8768 Output Parameter: 8769 . localX - The output vector 8770 8771 Calling sequence of func: 8772 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8773 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8774 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8775 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8776 8777 + dim - The spatial dimension 8778 . Nf - The number of input fields 8779 . NfAux - The number of input auxiliary fields 8780 . uOff - The offset of each field in u[] 8781 . uOff_x - The offset of each field in u_x[] 8782 . u - The field values at this point in space 8783 . u_t - The field time derivative at this point in space (or NULL) 8784 . u_x - The field derivatives at this point in space 8785 . aOff - The offset of each auxiliary field in u[] 8786 . aOff_x - The offset of each auxiliary field in u_x[] 8787 . a - The auxiliary field values at this point in space 8788 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8789 . a_x - The auxiliary field derivatives at this point in space 8790 . t - The current time 8791 . x - The coordinates of this point 8792 . numConstants - The number of constants 8793 . constants - The value of each constant 8794 - f - The value of the function at this point in space 8795 8796 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. 8797 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 8798 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8799 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8800 8801 Level: intermediate 8802 8803 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8804 @*/ 8805 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 8806 void (**funcs)(PetscInt, PetscInt, PetscInt, 8807 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8808 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8809 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8810 InsertMode mode, Vec localX) 8811 { 8812 PetscErrorCode ierr; 8813 8814 PetscFunctionBegin; 8815 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8816 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 8817 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 8818 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLabelLocal",((PetscObject)dm)->type_name); 8819 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 8820 PetscFunctionReturn(0); 8821 } 8822 8823 /*@C 8824 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. 8825 8826 Not collective 8827 8828 Input Parameters: 8829 + dm - The DM 8830 . time - The time 8831 . label - The DMLabel marking the portion of the domain boundary to output 8832 . numIds - The number of label ids to use 8833 . ids - The label ids to use for marking 8834 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 8835 . comps - The components to set in the output, or NULL for all components 8836 . localU - The input field vector 8837 . funcs - The functions to evaluate, one per field 8838 - mode - The insertion mode for values 8839 8840 Output Parameter: 8841 . localX - The output vector 8842 8843 Calling sequence of func: 8844 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8845 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8846 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8847 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8848 8849 + dim - The spatial dimension 8850 . Nf - The number of input fields 8851 . NfAux - The number of input auxiliary fields 8852 . uOff - The offset of each field in u[] 8853 . uOff_x - The offset of each field in u_x[] 8854 . u - The field values at this point in space 8855 . u_t - The field time derivative at this point in space (or NULL) 8856 . u_x - The field derivatives at this point in space 8857 . aOff - The offset of each auxiliary field in u[] 8858 . aOff_x - The offset of each auxiliary field in u_x[] 8859 . a - The auxiliary field values at this point in space 8860 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8861 . a_x - The auxiliary field derivatives at this point in space 8862 . t - The current time 8863 . x - The coordinates of this point 8864 . n - The face normal 8865 . numConstants - The number of constants 8866 . constants - The value of each constant 8867 - f - The value of the function at this point in space 8868 8869 Note: 8870 There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 8871 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 8872 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8873 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8874 8875 Level: intermediate 8876 8877 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8878 @*/ 8879 PetscErrorCode DMProjectBdFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 8880 void (**funcs)(PetscInt, PetscInt, PetscInt, 8881 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8882 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8883 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8884 InsertMode mode, Vec localX) 8885 { 8886 PetscErrorCode ierr; 8887 8888 PetscFunctionBegin; 8889 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8890 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 8891 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 8892 if (!dm->ops->projectbdfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectBdFieldLabelLocal",((PetscObject)dm)->type_name); 8893 ierr = (dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 8894 PetscFunctionReturn(0); 8895 } 8896 8897 /*@C 8898 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 8899 8900 Input Parameters: 8901 + dm - The DM 8902 . time - The time 8903 . funcs - The functions to evaluate for each field component 8904 . ctxs - Optional array of contexts to pass to each function, or NULL. 8905 - X - The coefficient vector u_h, a global vector 8906 8907 Output Parameter: 8908 . diff - The diff ||u - u_h||_2 8909 8910 Level: developer 8911 8912 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 8913 @*/ 8914 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 8915 { 8916 PetscErrorCode ierr; 8917 8918 PetscFunctionBegin; 8919 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8920 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8921 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 8922 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 8923 PetscFunctionReturn(0); 8924 } 8925 8926 /*@C 8927 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 8928 8929 Collective on dm 8930 8931 Input Parameters: 8932 + dm - The DM 8933 , time - The time 8934 . funcs - The gradient functions to evaluate for each field component 8935 . ctxs - Optional array of contexts to pass to each function, or NULL. 8936 . X - The coefficient vector u_h, a global vector 8937 - n - The vector to project along 8938 8939 Output Parameter: 8940 . diff - The diff ||(grad u - grad u_h) . n||_2 8941 8942 Level: developer 8943 8944 .seealso: DMProjectFunction(), DMComputeL2Diff() 8945 @*/ 8946 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) 8947 { 8948 PetscErrorCode ierr; 8949 8950 PetscFunctionBegin; 8951 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8952 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8953 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 8954 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 8955 PetscFunctionReturn(0); 8956 } 8957 8958 /*@C 8959 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 8960 8961 Collective on dm 8962 8963 Input Parameters: 8964 + dm - The DM 8965 . time - The time 8966 . funcs - The functions to evaluate for each field component 8967 . ctxs - Optional array of contexts to pass to each function, or NULL. 8968 - X - The coefficient vector u_h, a global vector 8969 8970 Output Parameter: 8971 . diff - The array of differences, ||u^f - u^f_h||_2 8972 8973 Level: developer 8974 8975 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 8976 @*/ 8977 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 8978 { 8979 PetscErrorCode ierr; 8980 8981 PetscFunctionBegin; 8982 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8983 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 8984 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 8985 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 8986 PetscFunctionReturn(0); 8987 } 8988 8989 /*@C 8990 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 8991 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 8992 8993 Collective on dm 8994 8995 Input parameters: 8996 + dm - the pre-adaptation DM object 8997 - label - label with the flags 8998 8999 Output parameters: 9000 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 9001 9002 Level: intermediate 9003 9004 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 9005 @*/ 9006 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 9007 { 9008 PetscErrorCode ierr; 9009 9010 PetscFunctionBegin; 9011 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9012 PetscValidPointer(label,2); 9013 PetscValidPointer(dmAdapt,3); 9014 *dmAdapt = NULL; 9015 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 9016 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 9017 if (*dmAdapt) { 9018 (*dmAdapt)->prealloc_only = dm->prealloc_only; /* maybe this should go .... */ 9019 ierr = PetscFree((*dmAdapt)->vectype);CHKERRQ(ierr); 9020 ierr = PetscStrallocpy(dm->vectype,(char**)&(*dmAdapt)->vectype);CHKERRQ(ierr); 9021 ierr = PetscFree((*dmAdapt)->mattype);CHKERRQ(ierr); 9022 ierr = PetscStrallocpy(dm->mattype,(char**)&(*dmAdapt)->mattype);CHKERRQ(ierr); 9023 } 9024 PetscFunctionReturn(0); 9025 } 9026 9027 /*@C 9028 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 9029 9030 Input Parameters: 9031 + dm - The DM object 9032 . metric - The metric to which the mesh is adapted, defined vertex-wise. 9033 - 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_". 9034 9035 Output Parameter: 9036 . dmAdapt - Pointer to the DM object containing the adapted mesh 9037 9038 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 9039 9040 Level: advanced 9041 9042 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 9043 @*/ 9044 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 9045 { 9046 PetscErrorCode ierr; 9047 9048 PetscFunctionBegin; 9049 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9050 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 9051 if (bdLabel) PetscValidPointer(bdLabel, 3); 9052 PetscValidPointer(dmAdapt, 4); 9053 *dmAdapt = NULL; 9054 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 9055 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 9056 PetscFunctionReturn(0); 9057 } 9058 9059 /*@C 9060 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 9061 9062 Not Collective 9063 9064 Input Parameter: 9065 . dm - The DM 9066 9067 Output Parameters: 9068 + nranks - the number of neighbours 9069 - ranks - the neighbors ranks 9070 9071 Notes: 9072 Do not free the array, it is freed when the DM is destroyed. 9073 9074 Level: beginner 9075 9076 .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks() 9077 @*/ 9078 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 9079 { 9080 PetscErrorCode ierr; 9081 9082 PetscFunctionBegin; 9083 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9084 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 9085 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 9086 PetscFunctionReturn(0); 9087 } 9088 9089 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 9090 9091 /* 9092 Converts the input vector to a ghosted vector and then calls the standard coloring code. 9093 This has be a different function because it requires DM which is not defined in the Mat library 9094 */ 9095 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 9096 { 9097 PetscErrorCode ierr; 9098 9099 PetscFunctionBegin; 9100 if (coloring->ctype == IS_COLORING_LOCAL) { 9101 Vec x1local; 9102 DM dm; 9103 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 9104 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 9105 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 9106 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 9107 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 9108 x1 = x1local; 9109 } 9110 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 9111 if (coloring->ctype == IS_COLORING_LOCAL) { 9112 DM dm; 9113 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 9114 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 9115 } 9116 PetscFunctionReturn(0); 9117 } 9118 9119 /*@ 9120 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 9121 9122 Input Parameter: 9123 . coloring - the MatFDColoring object 9124 9125 Developer Notes: 9126 this routine exists because the PETSc Mat library does not know about the DM objects 9127 9128 Level: advanced 9129 9130 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 9131 @*/ 9132 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 9133 { 9134 PetscFunctionBegin; 9135 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 9136 PetscFunctionReturn(0); 9137 } 9138 9139 /*@ 9140 DMGetCompatibility - determine if two DMs are compatible 9141 9142 Collective 9143 9144 Input Parameters: 9145 + dm1 - the first DM 9146 - dm2 - the second DM 9147 9148 Output Parameters: 9149 + compatible - whether or not the two DMs are compatible 9150 - set - whether or not the compatible value was set 9151 9152 Notes: 9153 Two DMs are deemed compatible if they represent the same parallel decomposition 9154 of the same topology. This implies that the section (field data) on one 9155 "makes sense" with respect to the topology and parallel decomposition of the other. 9156 Loosely speaking, compatible DMs represent the same domain and parallel 9157 decomposition, but hold different data. 9158 9159 Typically, one would confirm compatibility if intending to simultaneously iterate 9160 over a pair of vectors obtained from different DMs. 9161 9162 For example, two DMDA objects are compatible if they have the same local 9163 and global sizes and the same stencil width. They can have different numbers 9164 of degrees of freedom per node. Thus, one could use the node numbering from 9165 either DM in bounds for a loop over vectors derived from either DM. 9166 9167 Consider the operation of summing data living on a 2-dof DMDA to data living 9168 on a 1-dof DMDA, which should be compatible, as in the following snippet. 9169 .vb 9170 ... 9171 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 9172 if (set && compatible) { 9173 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 9174 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 9175 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 9176 for (j=y; j<y+n; ++j) { 9177 for (i=x; i<x+m, ++i) { 9178 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 9179 } 9180 } 9181 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 9182 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 9183 } else { 9184 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 9185 } 9186 ... 9187 .ve 9188 9189 Checking compatibility might be expensive for a given implementation of DM, 9190 or might be impossible to unambiguously confirm or deny. For this reason, 9191 this function may decline to determine compatibility, and hence users should 9192 always check the "set" output parameter. 9193 9194 A DM is always compatible with itself. 9195 9196 In the current implementation, DMs which live on "unequal" communicators 9197 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 9198 incompatible. 9199 9200 This function is labeled "Collective," as information about all subdomains 9201 is required on each rank. However, in DM implementations which store all this 9202 information locally, this function may be merely "Logically Collective". 9203 9204 Developer Notes: 9205 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 9206 iff B is compatible with A. Thus, this function checks the implementations 9207 of both dm and dmc (if they are of different types), attempting to determine 9208 compatibility. It is left to DM implementers to ensure that symmetry is 9209 preserved. The simplest way to do this is, when implementing type-specific 9210 logic for this function, is to check for existing logic in the implementation 9211 of other DM types and let *set = PETSC_FALSE if found. 9212 9213 Level: advanced 9214 9215 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 9216 @*/ 9217 9218 PetscErrorCode DMGetCompatibility(DM dm1,DM dm2,PetscBool *compatible,PetscBool *set) 9219 { 9220 PetscErrorCode ierr; 9221 PetscMPIInt compareResult; 9222 DMType type,type2; 9223 PetscBool sameType; 9224 9225 PetscFunctionBegin; 9226 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 9227 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 9228 9229 /* Declare a DM compatible with itself */ 9230 if (dm1 == dm2) { 9231 *set = PETSC_TRUE; 9232 *compatible = PETSC_TRUE; 9233 PetscFunctionReturn(0); 9234 } 9235 9236 /* Declare a DM incompatible with a DM that lives on an "unequal" 9237 communicator. Note that this does not preclude compatibility with 9238 DMs living on "congruent" or "similar" communicators, but this must be 9239 determined by the implementation-specific logic */ 9240 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm1),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRMPI(ierr); 9241 if (compareResult == MPI_UNEQUAL) { 9242 *set = PETSC_TRUE; 9243 *compatible = PETSC_FALSE; 9244 PetscFunctionReturn(0); 9245 } 9246 9247 /* Pass to the implementation-specific routine, if one exists. */ 9248 if (dm1->ops->getcompatibility) { 9249 ierr = (*dm1->ops->getcompatibility)(dm1,dm2,compatible,set);CHKERRQ(ierr); 9250 if (*set) PetscFunctionReturn(0); 9251 } 9252 9253 /* If dm1 and dm2 are of different types, then attempt to check compatibility 9254 with an implementation of this function from dm2 */ 9255 ierr = DMGetType(dm1,&type);CHKERRQ(ierr); 9256 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 9257 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 9258 if (!sameType && dm2->ops->getcompatibility) { 9259 ierr = (*dm2->ops->getcompatibility)(dm2,dm1,compatible,set);CHKERRQ(ierr); /* Note argument order */ 9260 } else { 9261 *set = PETSC_FALSE; 9262 } 9263 PetscFunctionReturn(0); 9264 } 9265 9266 /*@C 9267 DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance. 9268 9269 Logically Collective on DM 9270 9271 Input Parameters: 9272 + DM - the DM 9273 . f - the monitor function 9274 . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired) 9275 - monitordestroy - [optional] routine that frees monitor context (may be NULL) 9276 9277 Options Database Keys: 9278 - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but 9279 does not cancel those set via the options database. 9280 9281 Notes: 9282 Several different monitoring routines may be set by calling 9283 DMMonitorSet() multiple times; all will be called in the 9284 order in which they were set. 9285 9286 Fortran Notes: 9287 Only a single monitor function can be set for each DM object 9288 9289 Level: intermediate 9290 9291 .seealso: DMMonitorCancel() 9292 @*/ 9293 PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**)) 9294 { 9295 PetscInt m; 9296 PetscErrorCode ierr; 9297 9298 PetscFunctionBegin; 9299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9300 for (m = 0; m < dm->numbermonitors; ++m) { 9301 PetscBool identical; 9302 9303 ierr = PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);CHKERRQ(ierr); 9304 if (identical) PetscFunctionReturn(0); 9305 } 9306 if (dm->numbermonitors >= MAXDMMONITORS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 9307 dm->monitor[dm->numbermonitors] = f; 9308 dm->monitordestroy[dm->numbermonitors] = monitordestroy; 9309 dm->monitorcontext[dm->numbermonitors++] = (void *) mctx; 9310 PetscFunctionReturn(0); 9311 } 9312 9313 /*@ 9314 DMMonitorCancel - Clears all the monitor functions for a DM object. 9315 9316 Logically Collective on DM 9317 9318 Input Parameter: 9319 . dm - the DM 9320 9321 Options Database Key: 9322 . -dm_monitor_cancel - cancels all monitors that have been hardwired 9323 into a code by calls to DMonitorSet(), but does not cancel those 9324 set via the options database 9325 9326 Notes: 9327 There is no way to clear one specific monitor from a DM object. 9328 9329 Level: intermediate 9330 9331 .seealso: DMMonitorSet() 9332 @*/ 9333 PetscErrorCode DMMonitorCancel(DM dm) 9334 { 9335 PetscErrorCode ierr; 9336 PetscInt m; 9337 9338 PetscFunctionBegin; 9339 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9340 for (m = 0; m < dm->numbermonitors; ++m) { 9341 if (dm->monitordestroy[m]) {ierr = (*dm->monitordestroy[m])(&dm->monitorcontext[m]);CHKERRQ(ierr);} 9342 } 9343 dm->numbermonitors = 0; 9344 PetscFunctionReturn(0); 9345 } 9346 9347 /*@C 9348 DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 9349 9350 Collective on DM 9351 9352 Input Parameters: 9353 + dm - DM object you wish to monitor 9354 . name - the monitor type one is seeking 9355 . help - message indicating what monitoring is done 9356 . manual - manual page for the monitor 9357 . monitor - the monitor function 9358 - 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 9359 9360 Output Parameter: 9361 . flg - Flag set if the monitor was created 9362 9363 Level: developer 9364 9365 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 9366 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 9367 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 9368 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 9369 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 9370 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 9371 PetscOptionsFList(), PetscOptionsEList() 9372 @*/ 9373 PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg) 9374 { 9375 PetscViewer viewer; 9376 PetscViewerFormat format; 9377 PetscErrorCode ierr; 9378 9379 PetscFunctionBegin; 9380 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9381 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);CHKERRQ(ierr); 9382 if (*flg) { 9383 PetscViewerAndFormat *vf; 9384 9385 ierr = PetscViewerAndFormatCreate(viewer, format, &vf);CHKERRQ(ierr); 9386 ierr = PetscObjectDereference((PetscObject) viewer);CHKERRQ(ierr); 9387 if (monitorsetup) {ierr = (*monitorsetup)(dm, vf);CHKERRQ(ierr);} 9388 ierr = DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr); 9389 } 9390 PetscFunctionReturn(0); 9391 } 9392 9393 /*@ 9394 DMMonitor - runs the user provided monitor routines, if they exist 9395 9396 Collective on DM 9397 9398 Input Parameters: 9399 . dm - The DM 9400 9401 Level: developer 9402 9403 .seealso: DMMonitorSet() 9404 @*/ 9405 PetscErrorCode DMMonitor(DM dm) 9406 { 9407 PetscInt m; 9408 PetscErrorCode ierr; 9409 9410 PetscFunctionBegin; 9411 if (!dm) PetscFunctionReturn(0); 9412 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9413 for (m = 0; m < dm->numbermonitors; ++m) { 9414 ierr = (*dm->monitor[m])(dm, dm->monitorcontext[m]);CHKERRQ(ierr); 9415 } 9416 PetscFunctionReturn(0); 9417 } 9418 9419 /*@ 9420 DMComputeError - Computes the error assuming the user has given exact solution functions 9421 9422 Collective on DM 9423 9424 Input Parameters: 9425 + dm - The DM 9426 . sol - The solution vector 9427 . errors - An array of length Nf, the number of fields, or NULL for no output 9428 - errorVec - A Vec pointer, or NULL for no output 9429 9430 Output Parameters: 9431 + errors - The error in each field 9432 - errorVec - Creates a vector to hold the cellwise error 9433 9434 Note: The exact solutions come from the PetscDS object, and the time comes from DMGetOutputSequenceNumber(). 9435 9436 Level: developer 9437 9438 .seealso: DMMonitorSet(), DMGetRegionNumDS(), PetscDSGetExactSolution(), DMGetOutputSequenceNumber() 9439 @*/ 9440 PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec) 9441 { 9442 PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 9443 void **ctxs; 9444 PetscReal time; 9445 PetscInt Nf, f, Nds, s; 9446 PetscErrorCode ierr; 9447 9448 PetscFunctionBegin; 9449 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9450 ierr = PetscCalloc2(Nf, &exactSol, Nf, &ctxs);CHKERRQ(ierr); 9451 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 9452 for (s = 0; s < Nds; ++s) { 9453 PetscDS ds; 9454 DMLabel label; 9455 IS fieldIS; 9456 const PetscInt *fields; 9457 PetscInt dsNf; 9458 9459 ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 9460 ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 9461 if (fieldIS) {ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr);} 9462 for (f = 0; f < dsNf; ++f) { 9463 const PetscInt field = fields[f]; 9464 ierr = PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]);CHKERRQ(ierr); 9465 } 9466 if (fieldIS) {ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr);} 9467 } 9468 for (f = 0; f < Nf; ++f) { 9469 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); 9470 } 9471 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 9472 if (errors) {ierr = DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors);CHKERRQ(ierr);} 9473 if (errorVec) { 9474 DM edm; 9475 DMPolytopeType ct; 9476 PetscBool simplex; 9477 PetscInt dim, cStart, Nf; 9478 9479 ierr = DMClone(dm, &edm);CHKERRQ(ierr); 9480 ierr = DMGetDimension(edm, &dim);CHKERRQ(ierr); 9481 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 9482 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 9483 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 9484 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9485 for (f = 0; f < Nf; ++f) { 9486 PetscFE fe, efe; 9487 PetscQuadrature q; 9488 const char *name; 9489 9490 ierr = DMGetField(dm, f, NULL, (PetscObject *) &fe);CHKERRQ(ierr); 9491 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe);CHKERRQ(ierr); 9492 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 9493 ierr = PetscObjectSetName((PetscObject) efe, name);CHKERRQ(ierr); 9494 ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 9495 ierr = PetscFESetQuadrature(efe, q);CHKERRQ(ierr); 9496 ierr = DMSetField(edm, f, NULL, (PetscObject) efe);CHKERRQ(ierr); 9497 ierr = PetscFEDestroy(&efe);CHKERRQ(ierr); 9498 } 9499 ierr = DMCreateDS(edm);CHKERRQ(ierr); 9500 9501 ierr = DMCreateGlobalVector(edm, errorVec); 9502 ierr = PetscObjectSetName((PetscObject) *errorVec, "Error");CHKERRQ(ierr); 9503 ierr = DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec);CHKERRQ(ierr); 9504 ierr = DMDestroy(&edm);CHKERRQ(ierr); 9505 } 9506 ierr = PetscFree2(exactSol, ctxs);CHKERRQ(ierr); 9507 PetscFunctionReturn(0); 9508 } 9509 9510 /*@ 9511 DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this DM 9512 9513 Not collective 9514 9515 Input Parameter: 9516 . dm - The DM 9517 9518 Output Parameter: 9519 . numAux - The nubmer of auxiliary data vectors 9520 9521 Level: advanced 9522 9523 .seealso: DMGetAuxiliaryLabels(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 9524 @*/ 9525 PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux) 9526 { 9527 PetscErrorCode ierr; 9528 9529 PetscFunctionBegin; 9530 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9531 ierr = PetscHMapAuxGetSize(dm->auxData, numAux);CHKERRQ(ierr); 9532 PetscFunctionReturn(0); 9533 } 9534 9535 /*@ 9536 DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value 9537 9538 Not collective 9539 9540 Input Parameters: 9541 + dm - The DM 9542 . label - The DMLabel 9543 - value - The label value indicating the region 9544 9545 Output Parameter: 9546 . aux - The Vec holding auxiliary field data 9547 9548 Level: advanced 9549 9550 .seealso: DMSetAuxiliaryVec(), DMGetNumAuxiliaryVec() 9551 @*/ 9552 PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, Vec *aux) 9553 { 9554 PetscHashAuxKey key; 9555 PetscErrorCode ierr; 9556 9557 PetscFunctionBegin; 9558 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9559 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 9560 key.label = label; 9561 key.value = value; 9562 ierr = PetscHMapAuxGet(dm->auxData, key, aux);CHKERRQ(ierr); 9563 PetscFunctionReturn(0); 9564 } 9565 9566 /*@ 9567 DMSetAuxiliaryVec - Set the auxiliary vector for region specified by the given label and value 9568 9569 Not collective 9570 9571 Input Parameters: 9572 + dm - The DM 9573 . label - The DMLabel 9574 . value - The label value indicating the region 9575 - aux - The Vec holding auxiliary field data 9576 9577 Level: advanced 9578 9579 .seealso: DMGetAuxiliaryVec() 9580 @*/ 9581 PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, Vec aux) 9582 { 9583 Vec old; 9584 PetscHashAuxKey key; 9585 PetscErrorCode ierr; 9586 9587 PetscFunctionBegin; 9588 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9589 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 9590 key.label = label; 9591 key.value = value; 9592 ierr = PetscHMapAuxGet(dm->auxData, key, &old);CHKERRQ(ierr); 9593 ierr = PetscObjectReference((PetscObject) aux);CHKERRQ(ierr); 9594 ierr = PetscObjectDereference((PetscObject) old);CHKERRQ(ierr); 9595 if (!aux) {ierr = PetscHMapAuxDel(dm->auxData, key);CHKERRQ(ierr);} 9596 else {ierr = PetscHMapAuxSet(dm->auxData, key, aux);CHKERRQ(ierr);} 9597 PetscFunctionReturn(0); 9598 } 9599 9600 /*@C 9601 DMGetAuxiliaryLabels - Get the labels and values for all auxiliary vectors in this DM 9602 9603 Not collective 9604 9605 Input Parameter: 9606 . dm - The DM 9607 9608 Output Parameters: 9609 + labels - The DMLabels for each Vec 9610 - values - The label values for each Vec 9611 9612 Note: The arrays passed in must be at least as large as DMGetNumAuxiliaryVec(). 9613 9614 Level: advanced 9615 9616 .seealso: DMGetNumAuxiliaryVec(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 9617 @*/ 9618 PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[]) 9619 { 9620 PetscHashAuxKey *keys; 9621 PetscInt n, i, off = 0; 9622 PetscErrorCode ierr; 9623 9624 PetscFunctionBegin; 9625 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9626 PetscValidPointer(labels, 2); 9627 PetscValidPointer(values, 3); 9628 ierr = DMGetNumAuxiliaryVec(dm, &n);CHKERRQ(ierr); 9629 ierr = PetscMalloc1(n, &keys);CHKERRQ(ierr); 9630 ierr = PetscHMapAuxGetKeys(dm->auxData, &off, keys);CHKERRQ(ierr); 9631 for (i = 0; i < n; ++i) {labels[i] = keys[i].label; values[i] = keys[i].value;} 9632 ierr = PetscFree(keys);CHKERRQ(ierr); 9633 PetscFunctionReturn(0); 9634 } 9635 9636 /*@ 9637 DMCopyAuxiliaryVec - Copy the auxiliary data to a new DM 9638 9639 Not collective 9640 9641 Input Parameter: 9642 . dm - The DM 9643 9644 Output Parameter: 9645 . dmNew - The new DM, now with the same auxiliary data 9646 9647 Level: advanced 9648 9649 .seealso: DMGetNumAuxiliaryVec(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 9650 @*/ 9651 PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew) 9652 { 9653 PetscErrorCode ierr; 9654 9655 PetscFunctionBegin; 9656 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9657 ierr = PetscHMapAuxDestroy(&dmNew->auxData);CHKERRQ(ierr); 9658 ierr = PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData);CHKERRQ(ierr); 9659 PetscFunctionReturn(0); 9660 } 9661