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