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