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