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