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