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