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