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