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