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