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