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