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 PetscBool isHybrid; 5811 void *ctx; 5812 PetscErrorCode ierr; 5813 5814 PetscFunctionBegin; 5815 ierr = PetscDSCreate(PetscObjectComm((PetscObject) ds), &dsNew);CHKERRQ(ierr); 5816 ierr = PetscDSCopyConstants(ds, dsNew);CHKERRQ(ierr); 5817 ierr = PetscDSCopyExactSolutions(ds, dsNew);CHKERRQ(ierr); 5818 ierr = PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, dsNew);CHKERRQ(ierr); 5819 ierr = PetscDSCopyEquations(ds, dsNew);CHKERRQ(ierr); 5820 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 5821 for (f = 0; f < Nf; ++f) { 5822 ierr = PetscDSGetContext(ds, f, &ctx);CHKERRQ(ierr); 5823 ierr = PetscDSSetContext(dsNew, f, ctx);CHKERRQ(ierr); 5824 } 5825 if (Nf) { 5826 ierr = PetscDSGetCoordinateDimension(ds, &cdim);CHKERRQ(ierr); 5827 ierr = PetscDSSetCoordinateDimension(dsNew, cdim);CHKERRQ(ierr); 5828 } 5829 ierr = PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew);CHKERRQ(ierr); 5830 for (b = dsNew->boundary; b; b = b->next) { 5831 ierr = DMGetLabel(dm, b->lname, &b->label);CHKERRQ(ierr); 5832 /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */ 5833 //if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name); 5834 } 5835 ierr = PetscDSGetHybrid(ds, &isHybrid);CHKERRQ(ierr); 5836 ierr = PetscDSSetHybrid(dsNew, isHybrid);CHKERRQ(ierr); 5837 5838 ierr = DMSetRegionDS(dm, label, fields, dsNew);CHKERRQ(ierr); 5839 ierr = PetscDSDestroy(&dsNew);CHKERRQ(ierr); 5840 PetscFunctionReturn(0); 5841 } 5842 5843 /*@ 5844 DMCopyDS - Copy the discrete systems for the DM into another DM 5845 5846 Collective on dm 5847 5848 Input Parameter: 5849 . dm - The DM 5850 5851 Output Parameter: 5852 . newdm - The DM 5853 5854 Level: advanced 5855 5856 .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5857 @*/ 5858 PetscErrorCode DMCopyDS(DM dm, DM newdm) 5859 { 5860 PetscInt Nds, s; 5861 PetscErrorCode ierr; 5862 5863 PetscFunctionBegin; 5864 if (dm == newdm) PetscFunctionReturn(0); 5865 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5866 ierr = DMClearDS(newdm);CHKERRQ(ierr); 5867 for (s = 0; s < Nds; ++s) { 5868 DMLabel label; 5869 IS fields; 5870 PetscDS ds, newds; 5871 PetscInt Nbd, bd; 5872 5873 ierr = DMGetRegionNumDS(dm, s, &label, &fields, &ds);CHKERRQ(ierr); 5874 ierr = DMTransferDS_Internal(newdm, label, fields, ds);CHKERRQ(ierr); 5875 /* Commplete new labels in the new DS */ 5876 ierr = DMGetRegionDS(newdm, label, NULL, &newds);CHKERRQ(ierr); 5877 ierr = PetscDSGetNumBoundary(newds, &Nbd);CHKERRQ(ierr); 5878 for (bd = 0; bd < Nbd; ++bd) { 5879 DMLabel label; 5880 PetscInt field; 5881 5882 ierr = PetscDSGetBoundary(newds, bd, NULL, NULL, NULL, &label, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5883 ierr = DMCompleteBoundaryLabel_Internal(newdm, newds, field, bd, label);CHKERRQ(ierr); 5884 } 5885 } 5886 PetscFunctionReturn(0); 5887 } 5888 5889 /*@ 5890 DMCopyDisc - Copy the fields and discrete systems for the DM into another DM 5891 5892 Collective on dm 5893 5894 Input Parameter: 5895 . dm - The DM 5896 5897 Output Parameter: 5898 . newdm - The DM 5899 5900 Level: advanced 5901 5902 .seealso: DMCopyFields(), DMCopyDS() 5903 @*/ 5904 PetscErrorCode DMCopyDisc(DM dm, DM newdm) 5905 { 5906 PetscErrorCode ierr; 5907 5908 PetscFunctionBegin; 5909 ierr = DMCopyFields(dm, newdm);CHKERRQ(ierr); 5910 ierr = DMCopyDS(dm, newdm);CHKERRQ(ierr); 5911 PetscFunctionReturn(0); 5912 } 5913 5914 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 5915 { 5916 DM dm_coord,dmc_coord; 5917 PetscErrorCode ierr; 5918 Vec coords,ccoords; 5919 Mat inject; 5920 PetscFunctionBegin; 5921 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5922 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 5923 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5924 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 5925 if (coords && !ccoords) { 5926 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 5927 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5928 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 5929 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 5930 ierr = MatDestroy(&inject);CHKERRQ(ierr); 5931 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 5932 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5933 } 5934 PetscFunctionReturn(0); 5935 } 5936 5937 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 5938 { 5939 DM dm_coord,subdm_coord; 5940 PetscErrorCode ierr; 5941 Vec coords,ccoords,clcoords; 5942 VecScatter *scat_i,*scat_g; 5943 PetscFunctionBegin; 5944 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5945 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 5946 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5947 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 5948 if (coords && !ccoords) { 5949 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 5950 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5951 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 5952 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 5953 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 5954 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5955 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5956 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5957 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5958 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 5959 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 5960 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 5961 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 5962 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5963 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 5964 ierr = PetscFree(scat_i);CHKERRQ(ierr); 5965 ierr = PetscFree(scat_g);CHKERRQ(ierr); 5966 } 5967 PetscFunctionReturn(0); 5968 } 5969 5970 /*@ 5971 DMGetDimension - Return the topological dimension of the DM 5972 5973 Not collective 5974 5975 Input Parameter: 5976 . dm - The DM 5977 5978 Output Parameter: 5979 . dim - The topological dimension 5980 5981 Level: beginner 5982 5983 .seealso: DMSetDimension(), DMCreate() 5984 @*/ 5985 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 5986 { 5987 PetscFunctionBegin; 5988 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5989 PetscValidIntPointer(dim, 2); 5990 *dim = dm->dim; 5991 PetscFunctionReturn(0); 5992 } 5993 5994 /*@ 5995 DMSetDimension - Set the topological dimension of the DM 5996 5997 Collective on dm 5998 5999 Input Parameters: 6000 + dm - The DM 6001 - dim - The topological dimension 6002 6003 Level: beginner 6004 6005 .seealso: DMGetDimension(), DMCreate() 6006 @*/ 6007 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 6008 { 6009 PetscDS ds; 6010 PetscInt Nds, n; 6011 PetscErrorCode ierr; 6012 6013 PetscFunctionBegin; 6014 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6015 PetscValidLogicalCollectiveInt(dm, dim, 2); 6016 dm->dim = dim; 6017 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 6018 for (n = 0; n < Nds; ++n) { 6019 ierr = DMGetRegionNumDS(dm, n, NULL, NULL, &ds);CHKERRQ(ierr); 6020 if (ds->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr);} 6021 } 6022 PetscFunctionReturn(0); 6023 } 6024 6025 /*@ 6026 DMGetDimPoints - Get the half-open interval for all points of a given dimension 6027 6028 Collective on dm 6029 6030 Input Parameters: 6031 + dm - the DM 6032 - dim - the dimension 6033 6034 Output Parameters: 6035 + pStart - The first point of the given dimension 6036 - pEnd - The first point following points of the given dimension 6037 6038 Note: 6039 The points are vertices in the Hasse diagram encoding the topology. This is explained in 6040 https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme, 6041 then the interval is empty. 6042 6043 Level: intermediate 6044 6045 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 6046 @*/ 6047 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 6048 { 6049 PetscInt d; 6050 PetscErrorCode ierr; 6051 6052 PetscFunctionBegin; 6053 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6054 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 6055 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 6056 if (!dm->ops->getdimpoints) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DM type %s does not implement DMGetDimPoints",((PetscObject)dm)->type_name); 6057 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 6058 PetscFunctionReturn(0); 6059 } 6060 6061 /*@ 6062 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 6063 6064 Collective on dm 6065 6066 Input Parameters: 6067 + dm - the DM 6068 - c - coordinate vector 6069 6070 Notes: 6071 The coordinates do include those for ghost points, which are in the local vector. 6072 6073 The vector c should be destroyed by the caller. 6074 6075 Level: intermediate 6076 6077 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMDASetUniformCoordinates() 6078 @*/ 6079 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 6080 { 6081 PetscErrorCode ierr; 6082 6083 PetscFunctionBegin; 6084 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6085 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 6086 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 6087 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 6088 dm->coordinates = c; 6089 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 6090 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 6091 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 6092 PetscFunctionReturn(0); 6093 } 6094 6095 /*@ 6096 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 6097 6098 Not collective 6099 6100 Input Parameters: 6101 + dm - the DM 6102 - c - coordinate vector 6103 6104 Notes: 6105 The coordinates of ghost points can be set using DMSetCoordinates() 6106 followed by DMGetCoordinatesLocal(). This is intended to enable the 6107 setting of ghost coordinates outside of the domain. 6108 6109 The vector c should be destroyed by the caller. 6110 6111 Level: intermediate 6112 6113 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 6114 @*/ 6115 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 6116 { 6117 PetscErrorCode ierr; 6118 6119 PetscFunctionBegin; 6120 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6121 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 6122 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 6123 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 6124 6125 dm->coordinatesLocal = c; 6126 6127 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 6128 PetscFunctionReturn(0); 6129 } 6130 6131 /*@ 6132 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 6133 6134 Collective on dm 6135 6136 Input Parameter: 6137 . dm - the DM 6138 6139 Output Parameter: 6140 . c - global coordinate vector 6141 6142 Note: 6143 This is a borrowed reference, so the user should NOT destroy this vector. When the DM is 6144 destroyed the array will no longer be valid. 6145 6146 Each process has only the locally-owned portion of the global coordinates (does NOT have the ghost coordinates). 6147 6148 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6149 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6150 6151 Level: intermediate 6152 6153 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMDASetUniformCoordinates() 6154 @*/ 6155 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 6156 { 6157 PetscErrorCode ierr; 6158 6159 PetscFunctionBegin; 6160 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6161 PetscValidPointer(c,2); 6162 if (!dm->coordinates && dm->coordinatesLocal) { 6163 DM cdm = NULL; 6164 PetscBool localized; 6165 6166 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6167 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 6168 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 6169 /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */ 6170 if (localized) { 6171 PetscInt cdim; 6172 6173 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 6174 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 6175 } 6176 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 6177 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 6178 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 6179 } 6180 *c = dm->coordinates; 6181 PetscFunctionReturn(0); 6182 } 6183 6184 /*@ 6185 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 6186 6187 Collective on dm 6188 6189 Input Parameter: 6190 . dm - the DM 6191 6192 Level: advanced 6193 6194 .seealso: DMGetCoordinatesLocalNoncollective() 6195 @*/ 6196 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 6197 { 6198 PetscErrorCode ierr; 6199 6200 PetscFunctionBegin; 6201 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6202 if (!dm->coordinatesLocal && dm->coordinates) { 6203 DM cdm = NULL; 6204 PetscBool localized; 6205 6206 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6207 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 6208 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 6209 /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */ 6210 if (localized) { 6211 PetscInt cdim; 6212 6213 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 6214 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 6215 } 6216 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 6217 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 6218 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 6219 } 6220 PetscFunctionReturn(0); 6221 } 6222 6223 /*@ 6224 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 6225 6226 Collective on dm 6227 6228 Input Parameter: 6229 . dm - the DM 6230 6231 Output Parameter: 6232 . c - coordinate vector 6233 6234 Note: 6235 This is a borrowed reference, so the user should NOT destroy this vector 6236 6237 Each process has the local and ghost coordinates 6238 6239 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6240 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6241 6242 Level: intermediate 6243 6244 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 6245 @*/ 6246 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 6247 { 6248 PetscErrorCode ierr; 6249 6250 PetscFunctionBegin; 6251 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6252 PetscValidPointer(c,2); 6253 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 6254 *c = dm->coordinatesLocal; 6255 PetscFunctionReturn(0); 6256 } 6257 6258 /*@ 6259 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 6260 6261 Not collective 6262 6263 Input Parameter: 6264 . dm - the DM 6265 6266 Output Parameter: 6267 . c - coordinate vector 6268 6269 Level: advanced 6270 6271 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 6272 @*/ 6273 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 6274 { 6275 PetscFunctionBegin; 6276 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6277 PetscValidPointer(c,2); 6278 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 6279 *c = dm->coordinatesLocal; 6280 PetscFunctionReturn(0); 6281 } 6282 6283 /*@ 6284 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 6285 6286 Not collective 6287 6288 Input Parameter: 6289 + dm - the DM 6290 - p - the IS of points whose coordinates will be returned 6291 6292 Output Parameter: 6293 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 6294 - pCoord - the Vec with coordinates of points in p 6295 6296 Note: 6297 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 6298 6299 This creates a new vector, so the user SHOULD destroy this vector 6300 6301 Each process has the local and ghost coordinates 6302 6303 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 6304 and (x_0,y_0,z_0,x_1,y_1,z_1...) 6305 6306 Level: advanced 6307 6308 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 6309 @*/ 6310 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 6311 { 6312 PetscSection cs, newcs; 6313 Vec coords; 6314 const PetscScalar *arr; 6315 PetscScalar *newarr=NULL; 6316 PetscInt n; 6317 PetscErrorCode ierr; 6318 6319 PetscFunctionBegin; 6320 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6321 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 6322 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 6323 if (pCoord) PetscValidPointer(pCoord, 4); 6324 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 6325 if (!dm->coordinateDM || !dm->coordinateDM->localSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 6326 cs = dm->coordinateDM->localSection; 6327 coords = dm->coordinatesLocal; 6328 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 6329 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 6330 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 6331 if (pCoord) { 6332 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 6333 /* set array in two steps to mimic PETSC_OWN_POINTER */ 6334 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 6335 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 6336 } else { 6337 ierr = PetscFree(newarr);CHKERRQ(ierr); 6338 } 6339 if (pCoordSection) {*pCoordSection = newcs;} 6340 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 6341 PetscFunctionReturn(0); 6342 } 6343 6344 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 6345 { 6346 PetscErrorCode ierr; 6347 6348 PetscFunctionBegin; 6349 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6350 PetscValidPointer(field,2); 6351 if (!dm->coordinateField) { 6352 if (dm->ops->createcoordinatefield) { 6353 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 6354 } 6355 } 6356 *field = dm->coordinateField; 6357 PetscFunctionReturn(0); 6358 } 6359 6360 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 6361 { 6362 PetscErrorCode ierr; 6363 6364 PetscFunctionBegin; 6365 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6366 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 6367 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 6368 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 6369 dm->coordinateField = field; 6370 PetscFunctionReturn(0); 6371 } 6372 6373 /*@ 6374 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 6375 6376 Collective on dm 6377 6378 Input Parameter: 6379 . dm - the DM 6380 6381 Output Parameter: 6382 . cdm - coordinate DM 6383 6384 Level: intermediate 6385 6386 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 6387 @*/ 6388 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 6389 { 6390 PetscErrorCode ierr; 6391 6392 PetscFunctionBegin; 6393 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6394 PetscValidPointer(cdm,2); 6395 if (!dm->coordinateDM) { 6396 DM cdm; 6397 6398 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 6399 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 6400 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 6401 * until the call to CreateCoordinateDM) */ 6402 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 6403 dm->coordinateDM = cdm; 6404 } 6405 *cdm = dm->coordinateDM; 6406 PetscFunctionReturn(0); 6407 } 6408 6409 /*@ 6410 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 6411 6412 Logically Collective on dm 6413 6414 Input Parameters: 6415 + dm - the DM 6416 - cdm - coordinate DM 6417 6418 Level: intermediate 6419 6420 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 6421 @*/ 6422 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 6423 { 6424 PetscErrorCode ierr; 6425 6426 PetscFunctionBegin; 6427 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6428 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 6429 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 6430 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 6431 dm->coordinateDM = cdm; 6432 PetscFunctionReturn(0); 6433 } 6434 6435 /*@ 6436 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 6437 6438 Not Collective 6439 6440 Input Parameter: 6441 . dm - The DM object 6442 6443 Output Parameter: 6444 . dim - The embedding dimension 6445 6446 Level: intermediate 6447 6448 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 6449 @*/ 6450 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 6451 { 6452 PetscFunctionBegin; 6453 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6454 PetscValidIntPointer(dim, 2); 6455 if (dm->dimEmbed == PETSC_DEFAULT) { 6456 dm->dimEmbed = dm->dim; 6457 } 6458 *dim = dm->dimEmbed; 6459 PetscFunctionReturn(0); 6460 } 6461 6462 /*@ 6463 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 6464 6465 Not Collective 6466 6467 Input Parameters: 6468 + dm - The DM object 6469 - dim - The embedding dimension 6470 6471 Level: intermediate 6472 6473 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 6474 @*/ 6475 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 6476 { 6477 PetscDS ds; 6478 PetscInt Nds, n; 6479 PetscErrorCode ierr; 6480 6481 PetscFunctionBegin; 6482 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6483 dm->dimEmbed = dim; 6484 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 6485 for (n = 0; n < Nds; ++n) { 6486 ierr = DMGetRegionNumDS(dm, n, NULL, NULL, &ds);CHKERRQ(ierr); 6487 ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr); 6488 } 6489 PetscFunctionReturn(0); 6490 } 6491 6492 /*@ 6493 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 6494 6495 Collective on dm 6496 6497 Input Parameter: 6498 . dm - The DM object 6499 6500 Output Parameter: 6501 . section - The PetscSection object 6502 6503 Level: intermediate 6504 6505 .seealso: DMGetCoordinateDM(), DMGetLocalSection(), DMSetLocalSection() 6506 @*/ 6507 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 6508 { 6509 DM cdm; 6510 PetscErrorCode ierr; 6511 6512 PetscFunctionBegin; 6513 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6514 PetscValidPointer(section, 2); 6515 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6516 ierr = DMGetLocalSection(cdm, section);CHKERRQ(ierr); 6517 PetscFunctionReturn(0); 6518 } 6519 6520 /*@ 6521 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 6522 6523 Not Collective 6524 6525 Input Parameters: 6526 + dm - The DM object 6527 . dim - The embedding dimension, or PETSC_DETERMINE 6528 - section - The PetscSection object 6529 6530 Level: intermediate 6531 6532 .seealso: DMGetCoordinateSection(), DMGetLocalSection(), DMSetLocalSection() 6533 @*/ 6534 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 6535 { 6536 DM cdm; 6537 PetscErrorCode ierr; 6538 6539 PetscFunctionBegin; 6540 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6541 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 6542 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6543 ierr = DMSetLocalSection(cdm, section);CHKERRQ(ierr); 6544 if (dim == PETSC_DETERMINE) { 6545 PetscInt d = PETSC_DEFAULT; 6546 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 6547 6548 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6549 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6550 pStart = PetscMax(vStart, pStart); 6551 pEnd = PetscMin(vEnd, pEnd); 6552 for (v = pStart; v < pEnd; ++v) { 6553 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 6554 if (dd) {d = dd; break;} 6555 } 6556 if (d >= 0) {ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);} 6557 } 6558 PetscFunctionReturn(0); 6559 } 6560 6561 /*@ 6562 DMProjectCoordinates - Project coordinates to a different space 6563 6564 Input Parameters: 6565 + dm - The DM object 6566 - disc - The new coordinate discretization 6567 6568 Level: intermediate 6569 6570 .seealso: DMGetCoordinateField() 6571 @*/ 6572 PetscErrorCode DMProjectCoordinates(DM dm, PetscFE disc) 6573 { 6574 PetscObject discOld; 6575 PetscClassId classid; 6576 DM cdmOld,cdmNew; 6577 Vec coordsOld,coordsNew; 6578 Mat matInterp; 6579 PetscErrorCode ierr; 6580 6581 PetscFunctionBegin; 6582 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6583 PetscValidHeaderSpecific(disc,PETSCFE_CLASSID,2); 6584 6585 ierr = DMGetCoordinateDM(dm, &cdmOld);CHKERRQ(ierr); 6586 /* Check current discretization is compatible */ 6587 ierr = DMGetField(cdmOld, 0, NULL, &discOld);CHKERRQ(ierr); 6588 ierr = PetscObjectGetClassId(discOld, &classid);CHKERRQ(ierr); 6589 if (classid != PETSCFE_CLASSID) { 6590 if (classid == PETSC_CONTAINER_CLASSID) { 6591 PetscFE feLinear; 6592 DMPolytopeType ct; 6593 PetscInt dim, dE, cStart; 6594 PetscBool simplex; 6595 6596 /* Assume linear vertex coordinates */ 6597 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6598 ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr); 6599 ierr = DMPlexGetHeightStratum(cdmOld, 0, &cStart, NULL);CHKERRQ(ierr); 6600 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 6601 switch (ct) { 6602 case DM_POLYTOPE_TRI_PRISM: 6603 case DM_POLYTOPE_TRI_PRISM_TENSOR: 6604 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot autoamtically create coordinate space for prisms"); 6605 default: break; 6606 } 6607 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 6608 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, 1, -1, &feLinear);CHKERRQ(ierr); 6609 ierr = DMSetField(cdmOld, 0, NULL, (PetscObject) feLinear);CHKERRQ(ierr); 6610 ierr = PetscFEDestroy(&feLinear);CHKERRQ(ierr); 6611 ierr = DMCreateDS(cdmOld);CHKERRQ(ierr); 6612 } else { 6613 const char *discname; 6614 6615 ierr = PetscObjectGetType(discOld, &discname);CHKERRQ(ierr); 6616 SETERRQ1(PetscObjectComm(discOld), PETSC_ERR_SUP, "Discretization type %s not supported", discname); 6617 } 6618 } 6619 /* Make a fresh clone of the coordinate DM */ 6620 ierr = DMClone(cdmOld, &cdmNew);CHKERRQ(ierr); 6621 ierr = DMSetField(cdmNew, 0, NULL, (PetscObject) disc);CHKERRQ(ierr); 6622 ierr = DMCreateDS(cdmNew);CHKERRQ(ierr); 6623 /* Project the coordinate vector from old to new space */ 6624 ierr = DMGetCoordinates(dm, &coordsOld);CHKERRQ(ierr); 6625 ierr = DMCreateGlobalVector(cdmNew, &coordsNew);CHKERRQ(ierr); 6626 ierr = DMCreateInterpolation(cdmOld, cdmNew, &matInterp, NULL);CHKERRQ(ierr); 6627 ierr = MatInterpolate(matInterp, coordsOld, coordsNew);CHKERRQ(ierr); 6628 ierr = MatDestroy(&matInterp);CHKERRQ(ierr); 6629 /* Set new coordinate structures */ 6630 ierr = DMSetCoordinateField(dm, NULL);CHKERRQ(ierr); 6631 ierr = DMSetCoordinateDM(dm, cdmNew);CHKERRQ(ierr); 6632 ierr = DMSetCoordinates(dm, coordsNew);CHKERRQ(ierr); 6633 ierr = VecDestroy(&coordsNew);CHKERRQ(ierr); 6634 ierr = DMDestroy(&cdmNew);CHKERRQ(ierr); 6635 PetscFunctionReturn(0); 6636 } 6637 6638 /*@C 6639 DMGetPeriodicity - Get the description of mesh periodicity 6640 6641 Input Parameters: 6642 . dm - The DM object 6643 6644 Output Parameters: 6645 + per - Whether the DM is periodic or not 6646 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 6647 . L - If we assume the mesh is a torus, this is the length of each coordinate 6648 - bd - This describes the type of periodicity in each topological dimension 6649 6650 Level: developer 6651 6652 .seealso: DMGetPeriodicity() 6653 @*/ 6654 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 6655 { 6656 PetscFunctionBegin; 6657 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6658 if (per) *per = dm->periodic; 6659 if (L) *L = dm->L; 6660 if (maxCell) *maxCell = dm->maxCell; 6661 if (bd) *bd = dm->bdtype; 6662 PetscFunctionReturn(0); 6663 } 6664 6665 /*@C 6666 DMSetPeriodicity - Set the description of mesh periodicity 6667 6668 Input Parameters: 6669 + dm - The DM object 6670 . per - Whether the DM is periodic or not. 6671 . 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. 6672 . L - If we assume the mesh is a torus, this is the length of each coordinate 6673 - bd - This describes the type of periodicity in each topological dimension 6674 6675 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. 6676 6677 Level: developer 6678 6679 .seealso: DMGetPeriodicity() 6680 @*/ 6681 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 6682 { 6683 PetscInt dim, d; 6684 PetscErrorCode ierr; 6685 6686 PetscFunctionBegin; 6687 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6688 PetscValidLogicalCollectiveBool(dm,per,2); 6689 if (maxCell) {PetscValidRealPointer(maxCell,3);} 6690 if (L) {PetscValidRealPointer(L,4);} 6691 if (bd) {PetscValidPointer(bd,5);} 6692 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 6693 if (maxCell) { 6694 if (!dm->maxCell) {ierr = PetscMalloc1(dim, &dm->maxCell);CHKERRQ(ierr);} 6695 for (d = 0; d < dim; ++d) dm->maxCell[d] = maxCell[d]; 6696 } else { /* remove maxCell information to disable automatic computation of localized vertices */ 6697 ierr = PetscFree(dm->maxCell);CHKERRQ(ierr); 6698 } 6699 6700 if (L) { 6701 if (!dm->L) {ierr = PetscMalloc1(dim, &dm->L);CHKERRQ(ierr);} 6702 for (d = 0; d < dim; ++d) dm->L[d] = L[d]; 6703 } 6704 if (bd) { 6705 if (!dm->bdtype) {ierr = PetscMalloc1(dim, &dm->bdtype);CHKERRQ(ierr);} 6706 for (d = 0; d < dim; ++d) dm->bdtype[d] = bd[d]; 6707 } 6708 dm->periodic = per; 6709 PetscFunctionReturn(0); 6710 } 6711 6712 /*@ 6713 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. 6714 6715 Input Parameters: 6716 + dm - The DM 6717 . in - The input coordinate point (dim numbers) 6718 - endpoint - Include the endpoint L_i 6719 6720 Output Parameter: 6721 . out - The localized coordinate point 6722 6723 Level: developer 6724 6725 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6726 @*/ 6727 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 6728 { 6729 PetscInt dim, d; 6730 PetscErrorCode ierr; 6731 6732 PetscFunctionBegin; 6733 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 6734 if (!dm->maxCell) { 6735 for (d = 0; d < dim; ++d) out[d] = in[d]; 6736 } else { 6737 if (endpoint) { 6738 for (d = 0; d < dim; ++d) { 6739 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)) { 6740 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 6741 } else { 6742 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6743 } 6744 } 6745 } else { 6746 for (d = 0; d < dim; ++d) { 6747 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 6748 } 6749 } 6750 } 6751 PetscFunctionReturn(0); 6752 } 6753 6754 /* 6755 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. 6756 6757 Input Parameters: 6758 + dm - The DM 6759 . dim - The spatial dimension 6760 . anchor - The anchor point, the input point can be no more than maxCell away from it 6761 - in - The input coordinate point (dim numbers) 6762 6763 Output Parameter: 6764 . out - The localized coordinate point 6765 6766 Level: developer 6767 6768 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 6769 6770 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 6771 */ 6772 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6773 { 6774 PetscInt d; 6775 6776 PetscFunctionBegin; 6777 if (!dm->maxCell) { 6778 for (d = 0; d < dim; ++d) out[d] = in[d]; 6779 } else { 6780 for (d = 0; d < dim; ++d) { 6781 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 6782 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6783 } else { 6784 out[d] = in[d]; 6785 } 6786 } 6787 } 6788 PetscFunctionReturn(0); 6789 } 6790 6791 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 6792 { 6793 PetscInt d; 6794 6795 PetscFunctionBegin; 6796 if (!dm->maxCell) { 6797 for (d = 0; d < dim; ++d) out[d] = in[d]; 6798 } else { 6799 for (d = 0; d < dim; ++d) { 6800 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 6801 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6802 } else { 6803 out[d] = in[d]; 6804 } 6805 } 6806 } 6807 PetscFunctionReturn(0); 6808 } 6809 6810 /* 6811 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. 6812 6813 Input Parameters: 6814 + dm - The DM 6815 . dim - The spatial dimension 6816 . anchor - The anchor point, the input point can be no more than maxCell away from it 6817 . in - The input coordinate delta (dim numbers) 6818 - out - The input coordinate point (dim numbers) 6819 6820 Output Parameter: 6821 . out - The localized coordinate in + out 6822 6823 Level: developer 6824 6825 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 6826 6827 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 6828 */ 6829 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 6830 { 6831 PetscInt d; 6832 6833 PetscFunctionBegin; 6834 if (!dm->maxCell) { 6835 for (d = 0; d < dim; ++d) out[d] += in[d]; 6836 } else { 6837 for (d = 0; d < dim; ++d) { 6838 const PetscReal maxC = dm->maxCell[d]; 6839 6840 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > maxC)) { 6841 const PetscScalar newCoord = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 6842 6843 if (PetscAbsScalar(newCoord - anchor[d]) > maxC) 6844 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])); 6845 out[d] += newCoord; 6846 } else { 6847 out[d] += in[d]; 6848 } 6849 } 6850 } 6851 PetscFunctionReturn(0); 6852 } 6853 6854 /*@ 6855 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 6856 6857 Not collective 6858 6859 Input Parameter: 6860 . dm - The DM 6861 6862 Output Parameter: 6863 areLocalized - True if localized 6864 6865 Level: developer 6866 6867 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 6868 @*/ 6869 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 6870 { 6871 DM cdm; 6872 PetscSection coordSection; 6873 PetscInt depth, cStart, cEnd, sStart, sEnd, c, dof; 6874 PetscBool isPlex, alreadyLocalized; 6875 PetscErrorCode ierr; 6876 6877 PetscFunctionBegin; 6878 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6879 PetscValidBoolPointer(areLocalized, 2); 6880 *areLocalized = PETSC_FALSE; 6881 6882 /* We need some generic way of refering to cells/vertices */ 6883 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6884 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 6885 if (!isPlex) PetscFunctionReturn(0); 6886 ierr = DMPlexGetDepth(cdm, &depth);CHKERRQ(ierr); 6887 if (!depth) PetscFunctionReturn(0); 6888 6889 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6890 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6891 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 6892 alreadyLocalized = PETSC_FALSE; 6893 for (c = cStart; c < cEnd; ++c) { 6894 if (c < sStart || c >= sEnd) continue; 6895 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 6896 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 6897 } 6898 *areLocalized = alreadyLocalized; 6899 PetscFunctionReturn(0); 6900 } 6901 6902 /*@ 6903 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 6904 6905 Collective on dm 6906 6907 Input Parameter: 6908 . dm - The DM 6909 6910 Output Parameter: 6911 areLocalized - True if localized 6912 6913 Level: developer 6914 6915 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 6916 @*/ 6917 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 6918 { 6919 PetscBool localized; 6920 PetscErrorCode ierr; 6921 6922 PetscFunctionBegin; 6923 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6924 PetscValidBoolPointer(areLocalized, 2); 6925 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 6926 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 6927 PetscFunctionReturn(0); 6928 } 6929 6930 /*@ 6931 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 6932 6933 Collective on dm 6934 6935 Input Parameter: 6936 . dm - The DM 6937 6938 Level: developer 6939 6940 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 6941 @*/ 6942 PetscErrorCode DMLocalizeCoordinates(DM dm) 6943 { 6944 DM cdm; 6945 PetscSection coordSection, cSection; 6946 Vec coordinates, cVec; 6947 PetscScalar *coords, *coords2, *anchor, *localized; 6948 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 6949 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 6950 PetscInt maxHeight = 0, h; 6951 PetscInt *pStart = NULL, *pEnd = NULL; 6952 PetscErrorCode ierr; 6953 6954 PetscFunctionBegin; 6955 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6956 if (!dm->periodic) PetscFunctionReturn(0); 6957 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 6958 if (alreadyLocalized) PetscFunctionReturn(0); 6959 6960 /* We need some generic way of refering to cells/vertices */ 6961 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6962 { 6963 PetscBool isplex; 6964 6965 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 6966 if (isplex) { 6967 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6968 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 6969 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6970 pEnd = &pStart[maxHeight + 1]; 6971 newStart = vStart; 6972 newEnd = vEnd; 6973 for (h = 0; h <= maxHeight; h++) { 6974 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 6975 newStart = PetscMin(newStart,pStart[h]); 6976 newEnd = PetscMax(newEnd,pEnd[h]); 6977 } 6978 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 6979 } 6980 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6981 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 6982 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6983 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 6984 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 6985 6986 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 6987 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 6988 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 6989 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 6990 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 6991 6992 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6993 localized = &anchor[bs]; 6994 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 6995 for (h = 0; h <= maxHeight; h++) { 6996 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6997 6998 for (c = cStart; c < cEnd; ++c) { 6999 PetscScalar *cellCoords = NULL; 7000 PetscInt b; 7001 7002 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 7003 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7004 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 7005 for (d = 0; d < dof/bs; ++d) { 7006 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 7007 for (b = 0; b < bs; b++) { 7008 if (cellCoords[d*bs + b] != localized[b]) break; 7009 } 7010 if (b < bs) break; 7011 } 7012 if (d < dof/bs) { 7013 if (c >= sStart && c < sEnd) { 7014 PetscInt cdof; 7015 7016 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 7017 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 7018 } 7019 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 7020 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 7021 } 7022 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7023 } 7024 } 7025 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr); 7026 if (alreadyLocalizedGlobal) { 7027 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7028 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 7029 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7030 PetscFunctionReturn(0); 7031 } 7032 for (v = vStart; v < vEnd; ++v) { 7033 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 7034 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 7035 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 7036 } 7037 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 7038 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 7039 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 7040 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 7041 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 7042 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 7043 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 7044 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 7045 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 7046 for (v = vStart; v < vEnd; ++v) { 7047 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 7048 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 7049 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 7050 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 7051 } 7052 for (h = 0; h <= maxHeight; h++) { 7053 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 7054 7055 for (c = cStart; c < cEnd; ++c) { 7056 PetscScalar *cellCoords = NULL; 7057 PetscInt b, cdof; 7058 7059 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 7060 if (!cdof) continue; 7061 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7062 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 7063 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 7064 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 7065 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 7066 } 7067 } 7068 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 7069 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 7070 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 7071 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 7072 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 7073 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 7074 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 7075 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 7076 PetscFunctionReturn(0); 7077 } 7078 7079 /*@ 7080 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 7081 7082 Collective on v (see explanation below) 7083 7084 Input Parameters: 7085 + dm - The DM 7086 . v - The Vec of points 7087 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 7088 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 7089 7090 Output Parameter: 7091 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 7092 - cells - The PetscSF containing the ranks and local indices of the containing points. 7093 7094 Level: developer 7095 7096 Notes: 7097 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 7098 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 7099 7100 If *cellSF is NULL on input, a PetscSF will be created. 7101 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 7102 7103 An array that maps each point to its containing cell can be obtained with 7104 7105 $ const PetscSFNode *cells; 7106 $ PetscInt nFound; 7107 $ const PetscInt *found; 7108 $ 7109 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 7110 7111 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 7112 the index of the cell in its rank's local numbering. 7113 7114 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 7115 @*/ 7116 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 7117 { 7118 PetscErrorCode ierr; 7119 7120 PetscFunctionBegin; 7121 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7122 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 7123 PetscValidPointer(cellSF,4); 7124 if (*cellSF) { 7125 PetscMPIInt result; 7126 7127 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 7128 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRMPI(ierr); 7129 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 7130 } else { 7131 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 7132 } 7133 if (!dm->ops->locatepoints) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 7134 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 7135 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 7136 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 7137 PetscFunctionReturn(0); 7138 } 7139 7140 /*@ 7141 DMGetOutputDM - Retrieve the DM associated with the layout for output 7142 7143 Collective on dm 7144 7145 Input Parameter: 7146 . dm - The original DM 7147 7148 Output Parameter: 7149 . odm - The DM which provides the layout for output 7150 7151 Level: intermediate 7152 7153 .seealso: VecView(), DMGetGlobalSection() 7154 @*/ 7155 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 7156 { 7157 PetscSection section; 7158 PetscBool hasConstraints, ghasConstraints; 7159 PetscErrorCode ierr; 7160 7161 PetscFunctionBegin; 7162 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7163 PetscValidPointer(odm,2); 7164 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 7165 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 7166 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 7167 if (!ghasConstraints) { 7168 *odm = dm; 7169 PetscFunctionReturn(0); 7170 } 7171 if (!dm->dmBC) { 7172 PetscSection newSection, gsection; 7173 PetscSF sf; 7174 7175 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 7176 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 7177 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 7178 ierr = DMSetLocalSection(dm->dmBC, newSection);CHKERRQ(ierr); 7179 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 7180 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 7181 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 7182 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 7183 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 7184 } 7185 *odm = dm->dmBC; 7186 PetscFunctionReturn(0); 7187 } 7188 7189 /*@ 7190 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 7191 7192 Input Parameter: 7193 . dm - The original DM 7194 7195 Output Parameters: 7196 + num - The output sequence number 7197 - val - The output sequence value 7198 7199 Level: intermediate 7200 7201 Note: This is intended for output that should appear in sequence, for instance 7202 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7203 7204 .seealso: VecView() 7205 @*/ 7206 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 7207 { 7208 PetscFunctionBegin; 7209 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7210 if (num) {PetscValidIntPointer(num,2); *num = dm->outputSequenceNum;} 7211 if (val) {PetscValidRealPointer(val,3);*val = dm->outputSequenceVal;} 7212 PetscFunctionReturn(0); 7213 } 7214 7215 /*@ 7216 DMSetOutputSequenceNumber - Set the sequence number/value for output 7217 7218 Input Parameters: 7219 + dm - The original DM 7220 . num - The output sequence number 7221 - val - The output sequence value 7222 7223 Level: intermediate 7224 7225 Note: This is intended for output that should appear in sequence, for instance 7226 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7227 7228 .seealso: VecView() 7229 @*/ 7230 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 7231 { 7232 PetscFunctionBegin; 7233 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7234 dm->outputSequenceNum = num; 7235 dm->outputSequenceVal = val; 7236 PetscFunctionReturn(0); 7237 } 7238 7239 /*@C 7240 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 7241 7242 Input Parameters: 7243 + dm - The original DM 7244 . name - The sequence name 7245 - num - The output sequence number 7246 7247 Output Parameter: 7248 . val - The output sequence value 7249 7250 Level: intermediate 7251 7252 Note: This is intended for output that should appear in sequence, for instance 7253 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 7254 7255 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 7256 @*/ 7257 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 7258 { 7259 PetscBool ishdf5; 7260 PetscErrorCode ierr; 7261 7262 PetscFunctionBegin; 7263 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7264 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 7265 PetscValidRealPointer(val,5); 7266 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 7267 if (ishdf5) { 7268 #if defined(PETSC_HAVE_HDF5) 7269 PetscScalar value; 7270 7271 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 7272 *val = PetscRealPart(value); 7273 #endif 7274 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 7275 PetscFunctionReturn(0); 7276 } 7277 7278 /*@ 7279 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 7280 7281 Not collective 7282 7283 Input Parameter: 7284 . dm - The DM 7285 7286 Output Parameter: 7287 . useNatural - The flag to build the mapping to a natural order during distribution 7288 7289 Level: beginner 7290 7291 .seealso: DMSetUseNatural(), DMCreate() 7292 @*/ 7293 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 7294 { 7295 PetscFunctionBegin; 7296 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7297 PetscValidBoolPointer(useNatural, 2); 7298 *useNatural = dm->useNatural; 7299 PetscFunctionReturn(0); 7300 } 7301 7302 /*@ 7303 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 7304 7305 Collective on dm 7306 7307 Input Parameters: 7308 + dm - The DM 7309 - useNatural - The flag to build the mapping to a natural order during distribution 7310 7311 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 7312 7313 Level: beginner 7314 7315 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 7316 @*/ 7317 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 7318 { 7319 PetscFunctionBegin; 7320 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7321 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 7322 dm->useNatural = useNatural; 7323 PetscFunctionReturn(0); 7324 } 7325 7326 /*@C 7327 DMCreateLabel - Create a label of the given name if it does not already exist 7328 7329 Not Collective 7330 7331 Input Parameters: 7332 + dm - The DM object 7333 - name - The label name 7334 7335 Level: intermediate 7336 7337 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7338 @*/ 7339 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 7340 { 7341 PetscBool flg; 7342 DMLabel label; 7343 PetscErrorCode ierr; 7344 7345 PetscFunctionBegin; 7346 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7347 PetscValidCharPointer(name, 2); 7348 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 7349 if (!flg) { 7350 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 7351 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 7352 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 7353 } 7354 PetscFunctionReturn(0); 7355 } 7356 7357 /*@C 7358 DMCreateLabelAtIndex - Create a label of the given name at the iven index. If it already exists, move it to this index. 7359 7360 Not Collective 7361 7362 Input Parameters: 7363 + dm - The DM object 7364 . l - The index for the label 7365 - name - The label name 7366 7367 Level: intermediate 7368 7369 .seealso: DMCreateLabel(), DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7370 @*/ 7371 PetscErrorCode DMCreateLabelAtIndex(DM dm, PetscInt l, const char name[]) 7372 { 7373 DMLabelLink orig, prev = NULL; 7374 DMLabel label; 7375 PetscInt Nl, m; 7376 PetscBool flg, match; 7377 const char *lname; 7378 PetscErrorCode ierr; 7379 7380 PetscFunctionBegin; 7381 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7382 PetscValidCharPointer(name, 3); 7383 ierr = DMHasLabel(dm, name, &flg);CHKERRQ(ierr); 7384 if (!flg) { 7385 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &label);CHKERRQ(ierr); 7386 ierr = DMAddLabel(dm, label);CHKERRQ(ierr); 7387 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 7388 } 7389 ierr = DMGetNumLabels(dm, &Nl);CHKERRQ(ierr); 7390 if (l >= Nl) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label index %D must be in [0, %D)", l, Nl); 7391 for (m = 0, orig = dm->labels; m < Nl; ++m, prev = orig, orig = orig->next) { 7392 ierr = PetscObjectGetName((PetscObject) orig->label, &lname);CHKERRQ(ierr); 7393 ierr = PetscStrcmp(name, lname, &match);CHKERRQ(ierr); 7394 if (match) break; 7395 } 7396 if (m == l) PetscFunctionReturn(0); 7397 if (!m) dm->labels = orig->next; 7398 else prev->next = orig->next; 7399 if (!l) { 7400 orig->next = dm->labels; 7401 dm->labels = orig; 7402 } else { 7403 for (m = 0, prev = dm->labels; m < l-1; ++m, prev = prev->next); 7404 orig->next = prev->next; 7405 prev->next = orig; 7406 } 7407 PetscFunctionReturn(0); 7408 } 7409 7410 /*@C 7411 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 7412 7413 Not Collective 7414 7415 Input Parameters: 7416 + dm - The DM object 7417 . name - The label name 7418 - point - The mesh point 7419 7420 Output Parameter: 7421 . value - The label value for this point, or -1 if the point is not in the label 7422 7423 Level: beginner 7424 7425 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 7426 @*/ 7427 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 7428 { 7429 DMLabel label; 7430 PetscErrorCode ierr; 7431 7432 PetscFunctionBegin; 7433 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7434 PetscValidCharPointer(name, 2); 7435 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7436 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 7437 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 7438 PetscFunctionReturn(0); 7439 } 7440 7441 /*@C 7442 DMSetLabelValue - Add a point to a Sieve Label with given value 7443 7444 Not Collective 7445 7446 Input Parameters: 7447 + dm - The DM object 7448 . name - The label name 7449 . point - The mesh point 7450 - value - The label value for this point 7451 7452 Output Parameter: 7453 7454 Level: beginner 7455 7456 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 7457 @*/ 7458 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7459 { 7460 DMLabel label; 7461 PetscErrorCode ierr; 7462 7463 PetscFunctionBegin; 7464 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7465 PetscValidCharPointer(name, 2); 7466 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7467 if (!label) { 7468 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 7469 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7470 } 7471 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 7472 PetscFunctionReturn(0); 7473 } 7474 7475 /*@C 7476 DMClearLabelValue - Remove a point from a Sieve Label with given value 7477 7478 Not Collective 7479 7480 Input Parameters: 7481 + dm - The DM object 7482 . name - The label name 7483 . point - The mesh point 7484 - value - The label value for this point 7485 7486 Output Parameter: 7487 7488 Level: beginner 7489 7490 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 7491 @*/ 7492 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 7493 { 7494 DMLabel label; 7495 PetscErrorCode ierr; 7496 7497 PetscFunctionBegin; 7498 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7499 PetscValidCharPointer(name, 2); 7500 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7501 if (!label) PetscFunctionReturn(0); 7502 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 7503 PetscFunctionReturn(0); 7504 } 7505 7506 /*@C 7507 DMGetLabelSize - Get the number of different integer ids in a Label 7508 7509 Not Collective 7510 7511 Input Parameters: 7512 + dm - The DM object 7513 - name - The label name 7514 7515 Output Parameter: 7516 . size - The number of different integer ids, or 0 if the label does not exist 7517 7518 Level: beginner 7519 7520 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 7521 @*/ 7522 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 7523 { 7524 DMLabel label; 7525 PetscErrorCode ierr; 7526 7527 PetscFunctionBegin; 7528 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7529 PetscValidCharPointer(name, 2); 7530 PetscValidIntPointer(size, 3); 7531 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7532 *size = 0; 7533 if (!label) PetscFunctionReturn(0); 7534 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 7535 PetscFunctionReturn(0); 7536 } 7537 7538 /*@C 7539 DMGetLabelIdIS - Get the integer ids in a label 7540 7541 Not Collective 7542 7543 Input Parameters: 7544 + mesh - The DM object 7545 - name - The label name 7546 7547 Output Parameter: 7548 . ids - The integer ids, or NULL if the label does not exist 7549 7550 Level: beginner 7551 7552 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 7553 @*/ 7554 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 7555 { 7556 DMLabel label; 7557 PetscErrorCode ierr; 7558 7559 PetscFunctionBegin; 7560 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7561 PetscValidCharPointer(name, 2); 7562 PetscValidPointer(ids, 3); 7563 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7564 *ids = NULL; 7565 if (label) { 7566 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 7567 } else { 7568 /* returning an empty IS */ 7569 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 7570 } 7571 PetscFunctionReturn(0); 7572 } 7573 7574 /*@C 7575 DMGetStratumSize - Get the number of points in a label stratum 7576 7577 Not Collective 7578 7579 Input Parameters: 7580 + dm - The DM object 7581 . name - The label name 7582 - value - The stratum value 7583 7584 Output Parameter: 7585 . size - The stratum size 7586 7587 Level: beginner 7588 7589 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 7590 @*/ 7591 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 7592 { 7593 DMLabel label; 7594 PetscErrorCode ierr; 7595 7596 PetscFunctionBegin; 7597 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7598 PetscValidCharPointer(name, 2); 7599 PetscValidIntPointer(size, 4); 7600 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7601 *size = 0; 7602 if (!label) PetscFunctionReturn(0); 7603 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 7604 PetscFunctionReturn(0); 7605 } 7606 7607 /*@C 7608 DMGetStratumIS - Get the points in a label stratum 7609 7610 Not Collective 7611 7612 Input Parameters: 7613 + dm - The DM object 7614 . name - The label name 7615 - value - The stratum value 7616 7617 Output Parameter: 7618 . points - The stratum points, or NULL if the label does not exist or does not have that value 7619 7620 Level: beginner 7621 7622 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 7623 @*/ 7624 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 7625 { 7626 DMLabel label; 7627 PetscErrorCode ierr; 7628 7629 PetscFunctionBegin; 7630 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7631 PetscValidCharPointer(name, 2); 7632 PetscValidPointer(points, 4); 7633 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7634 *points = NULL; 7635 if (!label) PetscFunctionReturn(0); 7636 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 7637 PetscFunctionReturn(0); 7638 } 7639 7640 /*@C 7641 DMSetStratumIS - Set the points in a label stratum 7642 7643 Not Collective 7644 7645 Input Parameters: 7646 + dm - The DM object 7647 . name - The label name 7648 . value - The stratum value 7649 - points - The stratum points 7650 7651 Level: beginner 7652 7653 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 7654 @*/ 7655 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 7656 { 7657 DMLabel label; 7658 PetscErrorCode ierr; 7659 7660 PetscFunctionBegin; 7661 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7662 PetscValidCharPointer(name, 2); 7663 PetscValidPointer(points, 4); 7664 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7665 if (!label) PetscFunctionReturn(0); 7666 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 7667 PetscFunctionReturn(0); 7668 } 7669 7670 /*@C 7671 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 7672 7673 Not Collective 7674 7675 Input Parameters: 7676 + dm - The DM object 7677 . name - The label name 7678 - value - The label value for this point 7679 7680 Output Parameter: 7681 7682 Level: beginner 7683 7684 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 7685 @*/ 7686 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 7687 { 7688 DMLabel label; 7689 PetscErrorCode ierr; 7690 7691 PetscFunctionBegin; 7692 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7693 PetscValidCharPointer(name, 2); 7694 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 7695 if (!label) PetscFunctionReturn(0); 7696 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 7697 PetscFunctionReturn(0); 7698 } 7699 7700 /*@ 7701 DMGetNumLabels - Return the number of labels defined by the mesh 7702 7703 Not Collective 7704 7705 Input Parameter: 7706 . dm - The DM object 7707 7708 Output Parameter: 7709 . numLabels - the number of Labels 7710 7711 Level: intermediate 7712 7713 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7714 @*/ 7715 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 7716 { 7717 DMLabelLink next = dm->labels; 7718 PetscInt n = 0; 7719 7720 PetscFunctionBegin; 7721 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7722 PetscValidIntPointer(numLabels, 2); 7723 while (next) {++n; next = next->next;} 7724 *numLabels = n; 7725 PetscFunctionReturn(0); 7726 } 7727 7728 /*@C 7729 DMGetLabelName - Return the name of nth label 7730 7731 Not Collective 7732 7733 Input Parameters: 7734 + dm - The DM object 7735 - n - the label number 7736 7737 Output Parameter: 7738 . name - the label name 7739 7740 Level: intermediate 7741 7742 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7743 @*/ 7744 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 7745 { 7746 DMLabelLink next = dm->labels; 7747 PetscInt l = 0; 7748 PetscErrorCode ierr; 7749 7750 PetscFunctionBegin; 7751 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7752 PetscValidPointer(name, 3); 7753 while (next) { 7754 if (l == n) { 7755 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 7756 PetscFunctionReturn(0); 7757 } 7758 ++l; 7759 next = next->next; 7760 } 7761 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7762 } 7763 7764 /*@C 7765 DMHasLabel - Determine whether the mesh has a label of a given name 7766 7767 Not Collective 7768 7769 Input Parameters: 7770 + dm - The DM object 7771 - name - The label name 7772 7773 Output Parameter: 7774 . hasLabel - PETSC_TRUE if the label is present 7775 7776 Level: intermediate 7777 7778 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7779 @*/ 7780 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 7781 { 7782 DMLabelLink next = dm->labels; 7783 const char *lname; 7784 PetscErrorCode ierr; 7785 7786 PetscFunctionBegin; 7787 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7788 PetscValidCharPointer(name, 2); 7789 PetscValidBoolPointer(hasLabel, 3); 7790 *hasLabel = PETSC_FALSE; 7791 while (next) { 7792 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7793 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 7794 if (*hasLabel) break; 7795 next = next->next; 7796 } 7797 PetscFunctionReturn(0); 7798 } 7799 7800 /*@C 7801 DMGetLabel - Return the label of a given name, or NULL 7802 7803 Not Collective 7804 7805 Input Parameters: 7806 + dm - The DM object 7807 - name - The label name 7808 7809 Output Parameter: 7810 . label - The DMLabel, or NULL if the label is absent 7811 7812 Note: Some of the default labels in a DMPlex will be 7813 $ "depth" - Holds the depth (co-dimension) of each mesh point 7814 $ "celltype" - Holds the topological type of each cell 7815 $ "ghost" - If the DM is distributed with overlap, this marks the cells and faces in the overlap 7816 $ "Cell Sets" - Mirrors the cell sets defined by GMsh and ExodusII 7817 $ "Face Sets" - Mirrors the face sets defined by GMsh and ExodusII 7818 $ "Vertex Sets" - Mirrors the vertex sets defined by GMsh 7819 7820 Level: intermediate 7821 7822 .seealso: DMCreateLabel(), DMHasLabel(), DMPlexGetDepthLabel(), DMPlexGetCellType() 7823 @*/ 7824 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 7825 { 7826 DMLabelLink next = dm->labels; 7827 PetscBool hasLabel; 7828 const char *lname; 7829 PetscErrorCode ierr; 7830 7831 PetscFunctionBegin; 7832 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7833 PetscValidCharPointer(name, 2); 7834 PetscValidPointer(label, 3); 7835 *label = NULL; 7836 while (next) { 7837 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7838 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7839 if (hasLabel) { 7840 *label = next->label; 7841 break; 7842 } 7843 next = next->next; 7844 } 7845 PetscFunctionReturn(0); 7846 } 7847 7848 /*@C 7849 DMGetLabelByNum - Return the nth label 7850 7851 Not Collective 7852 7853 Input Parameters: 7854 + dm - The DM object 7855 - n - the label number 7856 7857 Output Parameter: 7858 . label - the label 7859 7860 Level: intermediate 7861 7862 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7863 @*/ 7864 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 7865 { 7866 DMLabelLink next = dm->labels; 7867 PetscInt l = 0; 7868 7869 PetscFunctionBegin; 7870 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7871 PetscValidPointer(label, 3); 7872 while (next) { 7873 if (l == n) { 7874 *label = next->label; 7875 PetscFunctionReturn(0); 7876 } 7877 ++l; 7878 next = next->next; 7879 } 7880 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 7881 } 7882 7883 /*@C 7884 DMAddLabel - Add the label to this mesh 7885 7886 Not Collective 7887 7888 Input Parameters: 7889 + dm - The DM object 7890 - label - The DMLabel 7891 7892 Level: developer 7893 7894 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7895 @*/ 7896 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 7897 { 7898 DMLabelLink l, *p, tmpLabel; 7899 PetscBool hasLabel; 7900 const char *lname; 7901 PetscBool flg; 7902 PetscErrorCode ierr; 7903 7904 PetscFunctionBegin; 7905 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7906 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 7907 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 7908 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 7909 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 7910 tmpLabel->label = label; 7911 tmpLabel->output = PETSC_TRUE; 7912 for (p=&dm->labels; (l=*p); p=&l->next) {} 7913 *p = tmpLabel; 7914 ierr = PetscObjectReference((PetscObject)label);CHKERRQ(ierr); 7915 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 7916 if (flg) dm->depthLabel = label; 7917 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 7918 if (flg) dm->celltypeLabel = label; 7919 PetscFunctionReturn(0); 7920 } 7921 7922 /*@C 7923 DMSetLabel - Replaces the label of a given name, or ignores it if the name is not present 7924 7925 Not Collective 7926 7927 Input Parameters: 7928 + dm - The DM object 7929 - label - The DMLabel, having the same name, to substitute 7930 7931 Note: Some of the default labels in a DMPlex will be 7932 $ "depth" - Holds the depth (co-dimension) of each mesh point 7933 $ "celltype" - Holds the topological type of each cell 7934 $ "ghost" - If the DM is distributed with overlap, this marks the cells and faces in the overlap 7935 $ "Cell Sets" - Mirrors the cell sets defined by GMsh and ExodusII 7936 $ "Face Sets" - Mirrors the face sets defined by GMsh and ExodusII 7937 $ "Vertex Sets" - Mirrors the vertex sets defined by GMsh 7938 7939 Level: intermediate 7940 7941 .seealso: DMCreateLabel(), DMHasLabel(), DMPlexGetDepthLabel(), DMPlexGetCellType() 7942 @*/ 7943 PetscErrorCode DMSetLabel(DM dm, DMLabel label) 7944 { 7945 DMLabelLink next = dm->labels; 7946 PetscBool hasLabel, flg; 7947 const char *name, *lname; 7948 PetscErrorCode ierr; 7949 7950 PetscFunctionBegin; 7951 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7952 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 7953 ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr); 7954 while (next) { 7955 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7956 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7957 if (hasLabel) { 7958 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 7959 ierr = PetscStrcmp(lname, "depth", &flg);CHKERRQ(ierr); 7960 if (flg) dm->depthLabel = label; 7961 ierr = PetscStrcmp(lname, "celltype", &flg);CHKERRQ(ierr); 7962 if (flg) dm->celltypeLabel = label; 7963 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 7964 next->label = label; 7965 break; 7966 } 7967 next = next->next; 7968 } 7969 PetscFunctionReturn(0); 7970 } 7971 7972 /*@C 7973 DMRemoveLabel - Remove the label given by name from this mesh 7974 7975 Not Collective 7976 7977 Input Parameters: 7978 + dm - The DM object 7979 - name - The label name 7980 7981 Output Parameter: 7982 . label - The DMLabel, or NULL if the label is absent 7983 7984 Level: developer 7985 7986 Notes: 7987 DMRemoveLabel(dm,name,NULL) removes the label from dm and calls 7988 DMLabelDestroy() on the label. 7989 7990 DMRemoveLabel(dm,name,&label) removes the label from dm, but it DOES NOT 7991 call DMLabelDestroy(). Instead, the label is returned and the user is 7992 responsible of calling DMLabelDestroy() at some point. 7993 7994 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel(), DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabelBySelf() 7995 @*/ 7996 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 7997 { 7998 DMLabelLink link, *pnext; 7999 PetscBool hasLabel; 8000 const char *lname; 8001 PetscErrorCode ierr; 8002 8003 PetscFunctionBegin; 8004 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8005 PetscValidCharPointer(name, 2); 8006 if (label) { 8007 PetscValidPointer(label, 3); 8008 *label = NULL; 8009 } 8010 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 8011 ierr = PetscObjectGetName((PetscObject) link->label, &lname);CHKERRQ(ierr); 8012 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 8013 if (hasLabel) { 8014 *pnext = link->next; /* Remove from list */ 8015 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 8016 if (hasLabel) dm->depthLabel = NULL; 8017 ierr = PetscStrcmp(name, "celltype", &hasLabel);CHKERRQ(ierr); 8018 if (hasLabel) dm->celltypeLabel = NULL; 8019 if (label) *label = link->label; 8020 else {ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr);} 8021 ierr = PetscFree(link);CHKERRQ(ierr); 8022 break; 8023 } 8024 } 8025 PetscFunctionReturn(0); 8026 } 8027 8028 /*@ 8029 DMRemoveLabelBySelf - Remove the label from this mesh 8030 8031 Not Collective 8032 8033 Input Parameters: 8034 + dm - The DM object 8035 . label - (Optional) The DMLabel to be removed from the DM 8036 - failNotFound - Should it fail if the label is not found in the DM? 8037 8038 Level: developer 8039 8040 Notes: 8041 Only exactly the same instance is removed if found, name match is ignored. 8042 If the DM has an exclusive reference to the label, it gets destroyed and 8043 *label nullified. 8044 8045 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabel() DMGetLabelValue(), DMSetLabelValue(), DMLabelDestroy(), DMRemoveLabel() 8046 @*/ 8047 PetscErrorCode DMRemoveLabelBySelf(DM dm, DMLabel *label, PetscBool failNotFound) 8048 { 8049 DMLabelLink link, *pnext; 8050 PetscBool hasLabel = PETSC_FALSE; 8051 PetscErrorCode ierr; 8052 8053 PetscFunctionBegin; 8054 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8055 PetscValidPointer(label, 2); 8056 if (!*label && !failNotFound) PetscFunctionReturn(0); 8057 PetscValidHeaderSpecific(*label, DMLABEL_CLASSID, 2); 8058 PetscValidLogicalCollectiveBool(dm,failNotFound,3); 8059 for (pnext=&dm->labels; (link=*pnext); pnext=&link->next) { 8060 if (*label == link->label) { 8061 hasLabel = PETSC_TRUE; 8062 *pnext = link->next; /* Remove from list */ 8063 if (*label == dm->depthLabel) dm->depthLabel = NULL; 8064 if (*label == dm->celltypeLabel) dm->celltypeLabel = NULL; 8065 if (((PetscObject) link->label)->refct < 2) *label = NULL; /* nullify if exclusive reference */ 8066 ierr = DMLabelDestroy(&link->label);CHKERRQ(ierr); 8067 ierr = PetscFree(link);CHKERRQ(ierr); 8068 break; 8069 } 8070 } 8071 if (!hasLabel && failNotFound) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Given label not found in DM"); 8072 PetscFunctionReturn(0); 8073 } 8074 8075 /*@C 8076 DMGetLabelOutput - Get the output flag for a given label 8077 8078 Not Collective 8079 8080 Input Parameters: 8081 + dm - The DM object 8082 - name - The label name 8083 8084 Output Parameter: 8085 . output - The flag for output 8086 8087 Level: developer 8088 8089 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8090 @*/ 8091 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 8092 { 8093 DMLabelLink next = dm->labels; 8094 const char *lname; 8095 PetscErrorCode ierr; 8096 8097 PetscFunctionBegin; 8098 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8099 PetscValidPointer(name, 2); 8100 PetscValidPointer(output, 3); 8101 while (next) { 8102 PetscBool flg; 8103 8104 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8105 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 8106 if (flg) {*output = next->output; PetscFunctionReturn(0);} 8107 next = next->next; 8108 } 8109 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 8110 } 8111 8112 /*@C 8113 DMSetLabelOutput - Set the output flag for a given label 8114 8115 Not Collective 8116 8117 Input Parameters: 8118 + dm - The DM object 8119 . name - The label name 8120 - output - The flag for output 8121 8122 Level: developer 8123 8124 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 8125 @*/ 8126 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 8127 { 8128 DMLabelLink next = dm->labels; 8129 const char *lname; 8130 PetscErrorCode ierr; 8131 8132 PetscFunctionBegin; 8133 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8134 PetscValidCharPointer(name, 2); 8135 while (next) { 8136 PetscBool flg; 8137 8138 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 8139 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 8140 if (flg) {next->output = output; PetscFunctionReturn(0);} 8141 next = next->next; 8142 } 8143 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 8144 } 8145 8146 /*@ 8147 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 8148 8149 Collective on dmA 8150 8151 Input Parameter: 8152 + dmA - The DM object with initial labels 8153 . dmB - The DM object with copied labels 8154 . mode - Copy labels by pointers (PETSC_OWN_POINTER) or duplicate them (PETSC_COPY_VALUES) 8155 - all - Copy all labels including "depth", "dim", and "celltype" (PETSC_TRUE) which are otherwise ignored (PETSC_FALSE) 8156 8157 Level: intermediate 8158 8159 Note: This is typically used when interpolating or otherwise adding to a mesh 8160 8161 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection(), DMShareLabels() 8162 @*/ 8163 PetscErrorCode DMCopyLabels(DM dmA, DM dmB, PetscCopyMode mode, PetscBool all) 8164 { 8165 DMLabel label, labelNew; 8166 const char *name; 8167 PetscBool flg; 8168 DMLabelLink link; 8169 PetscErrorCode ierr; 8170 8171 PetscFunctionBegin; 8172 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 8173 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 8174 PetscValidLogicalCollectiveEnum(dmA, mode,3); 8175 PetscValidLogicalCollectiveBool(dmA, all, 4); 8176 if (mode==PETSC_USE_POINTER) SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_SUP, "PETSC_USE_POINTER not supported for objects"); 8177 if (dmA == dmB) PetscFunctionReturn(0); 8178 for (link=dmA->labels; link; link=link->next) { 8179 label=link->label; 8180 ierr = PetscObjectGetName((PetscObject)label, &name);CHKERRQ(ierr); 8181 if (!all) { 8182 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 8183 if (flg) continue; 8184 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 8185 if (flg) continue; 8186 ierr = PetscStrcmp(name, "celltype", &flg);CHKERRQ(ierr); 8187 if (flg) continue; 8188 } 8189 if (mode==PETSC_COPY_VALUES) { 8190 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 8191 } else { 8192 labelNew = label; 8193 } 8194 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 8195 if (mode==PETSC_COPY_VALUES) {ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);} 8196 } 8197 PetscFunctionReturn(0); 8198 } 8199 8200 PetscErrorCode DMSetLabelValue_Fast(DM dm, DMLabel *label, const char name[], PetscInt point, PetscInt value) 8201 { 8202 PetscErrorCode ierr; 8203 PetscFunctionBegin; 8204 PetscValidPointer(label,2); 8205 if (!*label) { 8206 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 8207 ierr = DMGetLabel(dm, name, label);CHKERRQ(ierr); 8208 } 8209 ierr = DMLabelSetValue(*label, point, value);CHKERRQ(ierr); 8210 PetscFunctionReturn(0); 8211 } 8212 8213 /* 8214 Many mesh programs, such as Triangle and TetGen, allow only a single label for each mesh point. Therefore, we would 8215 like to encode all label IDs using a single, universal label. We can do this by assigning an integer to every 8216 (label, id) pair in the DM. 8217 8218 However, a mesh point can have multiple labels, so we must separate all these values. We will assign a bit range to 8219 each label. 8220 */ 8221 PetscErrorCode DMUniversalLabelCreate(DM dm, DMUniversalLabel *universal) 8222 { 8223 DMUniversalLabel ul; 8224 PetscBool *active; 8225 PetscInt pStart, pEnd, p, Nl, l, m; 8226 PetscErrorCode ierr; 8227 8228 PetscFunctionBegin; 8229 ierr = PetscMalloc1(1, &ul);CHKERRQ(ierr); 8230 ierr = DMLabelCreate(PETSC_COMM_SELF, "universal", &ul->label);CHKERRQ(ierr); 8231 ierr = DMGetNumLabels(dm, &Nl);CHKERRQ(ierr); 8232 ierr = PetscCalloc1(Nl, &active);CHKERRQ(ierr); 8233 ul->Nl = 0; 8234 for (l = 0; l < Nl; ++l) { 8235 PetscBool isdepth, iscelltype; 8236 const char *name; 8237 8238 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 8239 ierr = PetscStrncmp(name, "depth", 6, &isdepth);CHKERRQ(ierr); 8240 ierr = PetscStrncmp(name, "celltype", 9, &iscelltype);CHKERRQ(ierr); 8241 active[l] = !(isdepth || iscelltype) ? PETSC_TRUE : PETSC_FALSE; 8242 if (active[l]) ++ul->Nl; 8243 } 8244 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); 8245 ul->Nv = 0; 8246 for (l = 0, m = 0; l < Nl; ++l) { 8247 DMLabel label; 8248 PetscInt nv; 8249 const char *name; 8250 8251 if (!active[l]) continue; 8252 ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr); 8253 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8254 ierr = DMLabelGetNumValues(label, &nv);CHKERRQ(ierr); 8255 ierr = PetscStrallocpy(name, &ul->names[m]);CHKERRQ(ierr); 8256 ul->indices[m] = l; 8257 ul->Nv += nv; 8258 ul->offsets[m+1] = nv; 8259 ul->bits[m+1] = PetscCeilReal(PetscLog2Real(nv+1)); 8260 ++m; 8261 } 8262 for (l = 1; l <= ul->Nl; ++l) { 8263 ul->offsets[l] = ul->offsets[l-1] + ul->offsets[l]; 8264 ul->bits[l] = ul->bits[l-1] + ul->bits[l]; 8265 } 8266 for (l = 0; l < ul->Nl; ++l) { 8267 PetscInt b; 8268 8269 ul->masks[l] = 0; 8270 for (b = ul->bits[l]; b < ul->bits[l+1]; ++b) ul->masks[l] |= 1 << b; 8271 } 8272 ierr = PetscMalloc1(ul->Nv, &ul->values);CHKERRQ(ierr); 8273 for (l = 0, m = 0; l < Nl; ++l) { 8274 DMLabel label; 8275 IS valueIS; 8276 const PetscInt *varr; 8277 PetscInt nv, v; 8278 8279 if (!active[l]) continue; 8280 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8281 ierr = DMLabelGetNumValues(label, &nv);CHKERRQ(ierr); 8282 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 8283 ierr = ISGetIndices(valueIS, &varr);CHKERRQ(ierr); 8284 for (v = 0; v < nv; ++v) { 8285 ul->values[ul->offsets[m]+v] = varr[v]; 8286 } 8287 ierr = ISRestoreIndices(valueIS, &varr);CHKERRQ(ierr); 8288 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 8289 ierr = PetscSortInt(nv, &ul->values[ul->offsets[m]]);CHKERRQ(ierr); 8290 ++m; 8291 } 8292 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 8293 for (p = pStart; p < pEnd; ++p) { 8294 PetscInt uval = 0; 8295 PetscBool marked = PETSC_FALSE; 8296 8297 for (l = 0, m = 0; l < Nl; ++l) { 8298 DMLabel label; 8299 PetscInt val, defval, loc, nv; 8300 8301 if (!active[l]) continue; 8302 ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); 8303 ierr = DMLabelGetValue(label, p, &val);CHKERRQ(ierr); 8304 ierr = DMLabelGetDefaultValue(label, &defval);CHKERRQ(ierr); 8305 if (val == defval) {++m; continue;} 8306 nv = ul->offsets[m+1]-ul->offsets[m]; 8307 marked = PETSC_TRUE; 8308 ierr = PetscFindInt(val, nv, &ul->values[ul->offsets[m]], &loc);CHKERRQ(ierr); 8309 if (loc < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Label value %D not found in compression array", val); 8310 uval += (loc+1) << ul->bits[m]; 8311 ++m; 8312 } 8313 if (marked) {ierr = DMLabelSetValue(ul->label, p, uval);CHKERRQ(ierr);} 8314 } 8315 ierr = PetscFree(active);CHKERRQ(ierr); 8316 *universal = ul; 8317 PetscFunctionReturn(0); 8318 } 8319 8320 PetscErrorCode DMUniversalLabelDestroy(DMUniversalLabel *universal) 8321 { 8322 PetscInt l; 8323 PetscErrorCode ierr; 8324 8325 PetscFunctionBegin; 8326 for (l = 0; l < (*universal)->Nl; ++l) {ierr = PetscFree((*universal)->names[l]);CHKERRQ(ierr);} 8327 ierr = DMLabelDestroy(&(*universal)->label);CHKERRQ(ierr); 8328 ierr = PetscFree5((*universal)->names, (*universal)->indices, (*universal)->offsets, (*universal)->bits, (*universal)->masks);CHKERRQ(ierr); 8329 ierr = PetscFree((*universal)->values);CHKERRQ(ierr); 8330 ierr = PetscFree(*universal);CHKERRQ(ierr); 8331 *universal = NULL; 8332 PetscFunctionReturn(0); 8333 } 8334 8335 PetscErrorCode DMUniversalLabelGetLabel(DMUniversalLabel ul, DMLabel *ulabel) 8336 { 8337 PetscFunctionBegin; 8338 PetscValidPointer(ulabel, 2); 8339 *ulabel = ul->label; 8340 PetscFunctionReturn(0); 8341 } 8342 8343 PetscErrorCode DMUniversalLabelCreateLabels(DMUniversalLabel ul, PetscBool preserveOrder, DM dm) 8344 { 8345 PetscInt Nl = ul->Nl, l; 8346 PetscErrorCode ierr; 8347 8348 PetscFunctionBegin; 8349 PetscValidHeaderSpecific(dm, DM_CLASSID, 3); 8350 for (l = 0; l < Nl; ++l) { 8351 if (preserveOrder) {ierr = DMCreateLabelAtIndex(dm, ul->indices[l], ul->names[l]);CHKERRQ(ierr);} 8352 else {ierr = DMCreateLabel(dm, ul->names[l]);CHKERRQ(ierr);} 8353 } 8354 if (preserveOrder) { 8355 for (l = 0; l < ul->Nl; ++l) { 8356 const char *name; 8357 PetscBool match; 8358 8359 ierr = DMGetLabelName(dm, ul->indices[l], &name);CHKERRQ(ierr); 8360 ierr = PetscStrcmp(name, ul->names[l], &match);CHKERRQ(ierr); 8361 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]); 8362 } 8363 } 8364 PetscFunctionReturn(0); 8365 } 8366 8367 PetscErrorCode DMUniversalLabelSetLabelValue(DMUniversalLabel ul, DM dm, PetscBool useIndex, PetscInt p, PetscInt value) 8368 { 8369 PetscInt l; 8370 PetscErrorCode ierr; 8371 8372 PetscFunctionBegin; 8373 for (l = 0; l < ul->Nl; ++l) { 8374 DMLabel label; 8375 PetscInt lval = (value & ul->masks[l]) >> ul->bits[l]; 8376 8377 if (lval) { 8378 if (useIndex) {ierr = DMGetLabelByNum(dm, ul->indices[l], &label);CHKERRQ(ierr);} 8379 else {ierr = DMGetLabel(dm, ul->names[l], &label);CHKERRQ(ierr);} 8380 ierr = DMLabelSetValue(label, p, ul->values[ul->offsets[l]+lval-1]);CHKERRQ(ierr); 8381 } 8382 } 8383 PetscFunctionReturn(0); 8384 } 8385 8386 /*@ 8387 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 8388 8389 Input Parameter: 8390 . dm - The DM object 8391 8392 Output Parameter: 8393 . cdm - The coarse DM 8394 8395 Level: intermediate 8396 8397 .seealso: DMSetCoarseDM() 8398 @*/ 8399 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 8400 { 8401 PetscFunctionBegin; 8402 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8403 PetscValidPointer(cdm, 2); 8404 *cdm = dm->coarseMesh; 8405 PetscFunctionReturn(0); 8406 } 8407 8408 /*@ 8409 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 8410 8411 Input Parameters: 8412 + dm - The DM object 8413 - cdm - The coarse DM 8414 8415 Level: intermediate 8416 8417 .seealso: DMGetCoarseDM() 8418 @*/ 8419 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 8420 { 8421 PetscErrorCode ierr; 8422 8423 PetscFunctionBegin; 8424 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8425 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 8426 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 8427 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 8428 dm->coarseMesh = cdm; 8429 PetscFunctionReturn(0); 8430 } 8431 8432 /*@ 8433 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 8434 8435 Input Parameter: 8436 . dm - The DM object 8437 8438 Output Parameter: 8439 . fdm - The fine DM 8440 8441 Level: intermediate 8442 8443 .seealso: DMSetFineDM() 8444 @*/ 8445 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 8446 { 8447 PetscFunctionBegin; 8448 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8449 PetscValidPointer(fdm, 2); 8450 *fdm = dm->fineMesh; 8451 PetscFunctionReturn(0); 8452 } 8453 8454 /*@ 8455 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 8456 8457 Input Parameters: 8458 + dm - The DM object 8459 - fdm - The fine DM 8460 8461 Level: intermediate 8462 8463 .seealso: DMGetFineDM() 8464 @*/ 8465 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 8466 { 8467 PetscErrorCode ierr; 8468 8469 PetscFunctionBegin; 8470 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8471 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 8472 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 8473 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 8474 dm->fineMesh = fdm; 8475 PetscFunctionReturn(0); 8476 } 8477 8478 /*=== DMBoundary code ===*/ 8479 8480 /*@C 8481 DMAddBoundary - Add a boundary condition to the model 8482 8483 Collective on dm 8484 8485 Input Parameters: 8486 + dm - The DM, with a PetscDS that matches the problem being constrained 8487 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 8488 . name - The BC name 8489 . label - The label defining constrained points 8490 . Nv - The number of DMLabel values for constrained points 8491 . values - An array of values for constrained points 8492 . field - The field to constrain 8493 . Nc - The number of constrained field components (0 will constrain all fields) 8494 . comps - An array of constrained component numbers 8495 . bcFunc - A pointwise function giving boundary values 8496 . bcFunc_t - A pointwise function giving the time deriative of the boundary values, or NULL 8497 - ctx - An optional user context for bcFunc 8498 8499 Output Parameter: 8500 . bd - (Optional) Boundary number 8501 8502 Options Database Keys: 8503 + -bc_<boundary name> <num> - Overrides the boundary ids 8504 - -bc_<boundary name>_comp <num> - Overrides the boundary components 8505 8506 Note: 8507 Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is: 8508 8509 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 8510 8511 If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is: 8512 8513 $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8514 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8515 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8516 $ PetscReal time, const PetscReal x[], PetscScalar bcval[]) 8517 8518 + dim - the spatial dimension 8519 . Nf - the number of fields 8520 . uOff - the offset into u[] and u_t[] for each field 8521 . uOff_x - the offset into u_x[] for each field 8522 . u - each field evaluated at the current point 8523 . u_t - the time derivative of each field evaluated at the current point 8524 . u_x - the gradient of each field evaluated at the current point 8525 . aOff - the offset into a[] and a_t[] for each auxiliary field 8526 . aOff_x - the offset into a_x[] for each auxiliary field 8527 . a - each auxiliary field evaluated at the current point 8528 . a_t - the time derivative of each auxiliary field evaluated at the current point 8529 . a_x - the gradient of auxiliary each field evaluated at the current point 8530 . t - current time 8531 . x - coordinates of the current point 8532 . numConstants - number of constant parameters 8533 . constants - constant parameters 8534 - bcval - output values at the current point 8535 8536 Level: developer 8537 8538 .seealso: DSGetBoundary(), PetscDSAddBoundary() 8539 @*/ 8540 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) 8541 { 8542 PetscDS ds; 8543 PetscErrorCode ierr; 8544 8545 PetscFunctionBegin; 8546 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8547 PetscValidLogicalCollectiveEnum(dm, type, 2); 8548 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4); 8549 PetscValidLogicalCollectiveInt(dm, Nv, 5); 8550 PetscValidLogicalCollectiveInt(dm, field, 7); 8551 PetscValidLogicalCollectiveInt(dm, Nc, 8); 8552 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 8553 ierr = DMCompleteBoundaryLabel_Internal(dm, ds, field, PETSC_MAX_INT, label);CHKERRQ(ierr); 8554 ierr = PetscDSAddBoundary(ds, type, name, label, Nv, values, field, Nc, comps, bcFunc, bcFunc_t, ctx, bd);CHKERRQ(ierr); 8555 PetscFunctionReturn(0); 8556 } 8557 8558 /* TODO Remove this since now the structures are the same */ 8559 static PetscErrorCode DMPopulateBoundary(DM dm) 8560 { 8561 PetscDS ds; 8562 DMBoundary *lastnext; 8563 DSBoundary dsbound; 8564 PetscErrorCode ierr; 8565 8566 PetscFunctionBegin; 8567 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 8568 dsbound = ds->boundary; 8569 if (dm->boundary) { 8570 DMBoundary next = dm->boundary; 8571 8572 /* quick check to see if the PetscDS has changed */ 8573 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 8574 /* the PetscDS has changed: tear down and rebuild */ 8575 while (next) { 8576 DMBoundary b = next; 8577 8578 next = b->next; 8579 ierr = PetscFree(b);CHKERRQ(ierr); 8580 } 8581 dm->boundary = NULL; 8582 } 8583 8584 lastnext = &(dm->boundary); 8585 while (dsbound) { 8586 DMBoundary dmbound; 8587 8588 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 8589 dmbound->dsboundary = dsbound; 8590 dmbound->label = dsbound->label; 8591 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 8592 *lastnext = dmbound; 8593 lastnext = &(dmbound->next); 8594 dsbound = dsbound->next; 8595 } 8596 PetscFunctionReturn(0); 8597 } 8598 8599 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 8600 { 8601 DMBoundary b; 8602 PetscErrorCode ierr; 8603 8604 PetscFunctionBegin; 8605 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8606 PetscValidBoolPointer(isBd, 3); 8607 *isBd = PETSC_FALSE; 8608 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 8609 b = dm->boundary; 8610 while (b && !(*isBd)) { 8611 DMLabel label = b->label; 8612 DSBoundary dsb = b->dsboundary; 8613 PetscInt i; 8614 8615 if (label) { 8616 for (i = 0; i < dsb->Nv && !(*isBd); ++i) {ierr = DMLabelStratumHasPoint(label, dsb->values[i], point, isBd);CHKERRQ(ierr);} 8617 } 8618 b = b->next; 8619 } 8620 PetscFunctionReturn(0); 8621 } 8622 8623 /*@C 8624 DMProjectFunction - This projects the given function into the function space provided, putting the coefficients in a global vector. 8625 8626 Collective on DM 8627 8628 Input Parameters: 8629 + dm - The DM 8630 . time - The time 8631 . funcs - The coordinate functions to evaluate, one per field 8632 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8633 - mode - The insertion mode for values 8634 8635 Output Parameter: 8636 . X - vector 8637 8638 Calling sequence of func: 8639 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8640 8641 + dim - The spatial dimension 8642 . time - The time at which to sample 8643 . x - The coordinates 8644 . Nf - The number of fields 8645 . u - The output field values 8646 - ctx - optional user-defined function context 8647 8648 Level: developer 8649 8650 .seealso: DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 8651 @*/ 8652 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 8653 { 8654 Vec localX; 8655 PetscErrorCode ierr; 8656 8657 PetscFunctionBegin; 8658 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8659 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 8660 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8661 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 8662 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 8663 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 8664 PetscFunctionReturn(0); 8665 } 8666 8667 /*@C 8668 DMProjectFunctionLocal - This projects the given function into the function space provided, putting the coefficients in a local vector. 8669 8670 Not collective 8671 8672 Input Parameters: 8673 + dm - The DM 8674 . time - The time 8675 . funcs - The coordinate functions to evaluate, one per field 8676 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8677 - mode - The insertion mode for values 8678 8679 Output Parameter: 8680 . localX - vector 8681 8682 Calling sequence of func: 8683 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8684 8685 + dim - The spatial dimension 8686 . x - The coordinates 8687 . Nf - The number of fields 8688 . u - The output field values 8689 - ctx - optional user-defined function context 8690 8691 Level: developer 8692 8693 .seealso: DMProjectFunction(), DMProjectFunctionLabel(), DMComputeL2Diff() 8694 @*/ 8695 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 8696 { 8697 PetscErrorCode ierr; 8698 8699 PetscFunctionBegin; 8700 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8701 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 8702 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 8703 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8704 PetscFunctionReturn(0); 8705 } 8706 8707 /*@C 8708 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. 8709 8710 Collective on DM 8711 8712 Input Parameters: 8713 + dm - The DM 8714 . time - The time 8715 . label - The DMLabel selecting the portion of the mesh for projection 8716 . funcs - The coordinate functions to evaluate, one per field 8717 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8718 - mode - The insertion mode for values 8719 8720 Output Parameter: 8721 . X - vector 8722 8723 Calling sequence of func: 8724 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8725 8726 + dim - The spatial dimension 8727 . x - The coordinates 8728 . Nf - The number of fields 8729 . u - The output field values 8730 - ctx - optional user-defined function context 8731 8732 Level: developer 8733 8734 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal(), DMComputeL2Diff() 8735 @*/ 8736 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) 8737 { 8738 Vec localX; 8739 PetscErrorCode ierr; 8740 8741 PetscFunctionBegin; 8742 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8743 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 8744 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8745 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 8746 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 8747 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 8748 PetscFunctionReturn(0); 8749 } 8750 8751 /*@C 8752 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. 8753 8754 Not collective 8755 8756 Input Parameters: 8757 + dm - The DM 8758 . time - The time 8759 . label - The DMLabel selecting the portion of the mesh for projection 8760 . funcs - The coordinate functions to evaluate, one per field 8761 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 8762 - mode - The insertion mode for values 8763 8764 Output Parameter: 8765 . localX - vector 8766 8767 Calling sequence of func: 8768 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 8769 8770 + dim - The spatial dimension 8771 . x - The coordinates 8772 . Nf - The number of fields 8773 . u - The output field values 8774 - ctx - optional user-defined function context 8775 8776 Level: developer 8777 8778 .seealso: DMProjectFunction(), DMProjectFunctionLocal(), DMProjectFunctionLabel(), DMComputeL2Diff() 8779 @*/ 8780 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) 8781 { 8782 PetscErrorCode ierr; 8783 8784 PetscFunctionBegin; 8785 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8786 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 8787 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 8788 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 8789 PetscFunctionReturn(0); 8790 } 8791 8792 /*@C 8793 DMProjectFieldLocal - This projects the given function of the input fields into the function space provided, putting the coefficients in a local vector. 8794 8795 Not collective 8796 8797 Input Parameters: 8798 + dm - The DM 8799 . time - The time 8800 . localU - The input field vector 8801 . funcs - The functions to evaluate, one per field 8802 - mode - The insertion mode for values 8803 8804 Output Parameter: 8805 . localX - The output vector 8806 8807 Calling sequence of func: 8808 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8809 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8810 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8811 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8812 8813 + dim - The spatial dimension 8814 . Nf - The number of input fields 8815 . NfAux - The number of input auxiliary fields 8816 . uOff - The offset of each field in u[] 8817 . uOff_x - The offset of each field in u_x[] 8818 . u - The field values at this point in space 8819 . u_t - The field time derivative at this point in space (or NULL) 8820 . u_x - The field derivatives at this point in space 8821 . aOff - The offset of each auxiliary field in u[] 8822 . aOff_x - The offset of each auxiliary field in u_x[] 8823 . a - The auxiliary field values at this point in space 8824 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8825 . a_x - The auxiliary field derivatives at this point in space 8826 . t - The current time 8827 . x - The coordinates of this point 8828 . numConstants - The number of constants 8829 . constants - The value of each constant 8830 - f - The value of the function at this point in space 8831 8832 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. 8833 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 8834 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8835 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8836 8837 Level: intermediate 8838 8839 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8840 @*/ 8841 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 8842 void (**funcs)(PetscInt, PetscInt, PetscInt, 8843 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8844 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8845 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8846 InsertMode mode, Vec localX) 8847 { 8848 PetscErrorCode ierr; 8849 8850 PetscFunctionBegin; 8851 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8852 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 8853 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 8854 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 8855 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 8856 PetscFunctionReturn(0); 8857 } 8858 8859 /*@C 8860 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. 8861 8862 Not collective 8863 8864 Input Parameters: 8865 + dm - The DM 8866 . time - The time 8867 . label - The DMLabel marking the portion of the domain to output 8868 . numIds - The number of label ids to use 8869 . ids - The label ids to use for marking 8870 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 8871 . comps - The components to set in the output, or NULL for all components 8872 . localU - The input field vector 8873 . funcs - The functions to evaluate, one per field 8874 - mode - The insertion mode for values 8875 8876 Output Parameter: 8877 . localX - The output vector 8878 8879 Calling sequence of func: 8880 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8881 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8882 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8883 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8884 8885 + dim - The spatial dimension 8886 . Nf - The number of input fields 8887 . NfAux - The number of input auxiliary fields 8888 . uOff - The offset of each field in u[] 8889 . uOff_x - The offset of each field in u_x[] 8890 . u - The field values at this point in space 8891 . u_t - The field time derivative at this point in space (or NULL) 8892 . u_x - The field derivatives at this point in space 8893 . aOff - The offset of each auxiliary field in u[] 8894 . aOff_x - The offset of each auxiliary field in u_x[] 8895 . a - The auxiliary field values at this point in space 8896 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8897 . a_x - The auxiliary field derivatives at this point in space 8898 . t - The current time 8899 . x - The coordinates of this point 8900 . numConstants - The number of constants 8901 . constants - The value of each constant 8902 - f - The value of the function at this point in space 8903 8904 Note: There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 8905 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 8906 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8907 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8908 8909 Level: intermediate 8910 8911 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8912 @*/ 8913 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 8914 void (**funcs)(PetscInt, PetscInt, PetscInt, 8915 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8916 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8917 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8918 InsertMode mode, Vec localX) 8919 { 8920 PetscErrorCode ierr; 8921 8922 PetscFunctionBegin; 8923 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8924 PetscValidHeaderSpecific(localU,VEC_CLASSID,8); 8925 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 8926 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLabelLocal",((PetscObject)dm)->type_name); 8927 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 8928 PetscFunctionReturn(0); 8929 } 8930 8931 /*@C 8932 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. 8933 8934 Not collective 8935 8936 Input Parameters: 8937 + dm - The DM 8938 . time - The time 8939 . label - The DMLabel marking the portion of the domain boundary to output 8940 . numIds - The number of label ids to use 8941 . ids - The label ids to use for marking 8942 . Nc - The number of components to set in the output, or PETSC_DETERMINE for all components 8943 . comps - The components to set in the output, or NULL for all components 8944 . localU - The input field vector 8945 . funcs - The functions to evaluate, one per field 8946 - mode - The insertion mode for values 8947 8948 Output Parameter: 8949 . localX - The output vector 8950 8951 Calling sequence of func: 8952 $ func(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8953 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 8954 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 8955 $ PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 8956 8957 + dim - The spatial dimension 8958 . Nf - The number of input fields 8959 . NfAux - The number of input auxiliary fields 8960 . uOff - The offset of each field in u[] 8961 . uOff_x - The offset of each field in u_x[] 8962 . u - The field values at this point in space 8963 . u_t - The field time derivative at this point in space (or NULL) 8964 . u_x - The field derivatives at this point in space 8965 . aOff - The offset of each auxiliary field in u[] 8966 . aOff_x - The offset of each auxiliary field in u_x[] 8967 . a - The auxiliary field values at this point in space 8968 . a_t - The auxiliary field time derivative at this point in space (or NULL) 8969 . a_x - The auxiliary field derivatives at this point in space 8970 . t - The current time 8971 . x - The coordinates of this point 8972 . n - The face normal 8973 . numConstants - The number of constants 8974 . constants - The value of each constant 8975 - f - The value of the function at this point in space 8976 8977 Note: 8978 There are three different DMs that potentially interact in this function. The output DM, dm, specifies the layout of the values calculates by funcs. 8979 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 8980 a subdomain. You can also output a different number of fields than the input, with different discretizations. Last the auxiliary DM, attached to the 8981 auxiliary field vector, which is attached to dm, can also be different. It can have a different topology, number of fields, and discretizations. 8982 8983 Level: intermediate 8984 8985 .seealso: DMProjectField(), DMProjectFieldLabelLocal(), DMProjectFunction(), DMComputeL2Diff() 8986 @*/ 8987 PetscErrorCode DMProjectBdFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 8988 void (**funcs)(PetscInt, PetscInt, PetscInt, 8989 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8990 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 8991 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 8992 InsertMode mode, Vec localX) 8993 { 8994 PetscErrorCode ierr; 8995 8996 PetscFunctionBegin; 8997 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 8998 PetscValidHeaderSpecific(localU,VEC_CLASSID,8); 8999 PetscValidHeaderSpecific(localX,VEC_CLASSID,11); 9000 if (!dm->ops->projectbdfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectBdFieldLabelLocal",((PetscObject)dm)->type_name); 9001 ierr = (dm->ops->projectbdfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 9002 PetscFunctionReturn(0); 9003 } 9004 9005 /*@C 9006 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9007 9008 Input Parameters: 9009 + dm - The DM 9010 . time - The time 9011 . funcs - The functions to evaluate for each field component 9012 . ctxs - Optional array of contexts to pass to each function, or NULL. 9013 - X - The coefficient vector u_h, a global vector 9014 9015 Output Parameter: 9016 . diff - The diff ||u - u_h||_2 9017 9018 Level: developer 9019 9020 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 9021 @*/ 9022 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 9023 { 9024 PetscErrorCode ierr; 9025 9026 PetscFunctionBegin; 9027 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9028 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9029 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 9030 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 9031 PetscFunctionReturn(0); 9032 } 9033 9034 /*@C 9035 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 9036 9037 Collective on dm 9038 9039 Input Parameters: 9040 + dm - The DM 9041 , time - The time 9042 . funcs - The gradient functions to evaluate for each field component 9043 . ctxs - Optional array of contexts to pass to each function, or NULL. 9044 . X - The coefficient vector u_h, a global vector 9045 - n - The vector to project along 9046 9047 Output Parameter: 9048 . diff - The diff ||(grad u - grad u_h) . n||_2 9049 9050 Level: developer 9051 9052 .seealso: DMProjectFunction(), DMComputeL2Diff() 9053 @*/ 9054 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) 9055 { 9056 PetscErrorCode ierr; 9057 9058 PetscFunctionBegin; 9059 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9060 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9061 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 9062 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 9063 PetscFunctionReturn(0); 9064 } 9065 9066 /*@C 9067 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 9068 9069 Collective on dm 9070 9071 Input Parameters: 9072 + dm - The DM 9073 . time - The time 9074 . funcs - The functions to evaluate for each field component 9075 . ctxs - Optional array of contexts to pass to each function, or NULL. 9076 - X - The coefficient vector u_h, a global vector 9077 9078 Output Parameter: 9079 . diff - The array of differences, ||u^f - u^f_h||_2 9080 9081 Level: developer 9082 9083 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 9084 @*/ 9085 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 9086 { 9087 PetscErrorCode ierr; 9088 9089 PetscFunctionBegin; 9090 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9091 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 9092 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 9093 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 9094 PetscFunctionReturn(0); 9095 } 9096 9097 /*@C 9098 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 9099 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 9100 9101 Collective on dm 9102 9103 Input parameters: 9104 + dm - the pre-adaptation DM object 9105 - label - label with the flags 9106 9107 Output parameters: 9108 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 9109 9110 Level: intermediate 9111 9112 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 9113 @*/ 9114 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 9115 { 9116 PetscErrorCode ierr; 9117 9118 PetscFunctionBegin; 9119 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9120 PetscValidPointer(label,2); 9121 PetscValidPointer(dmAdapt,3); 9122 *dmAdapt = NULL; 9123 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 9124 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 9125 if (*dmAdapt) { 9126 (*dmAdapt)->prealloc_only = dm->prealloc_only; /* maybe this should go .... */ 9127 ierr = PetscFree((*dmAdapt)->vectype);CHKERRQ(ierr); 9128 ierr = PetscStrallocpy(dm->vectype,(char**)&(*dmAdapt)->vectype);CHKERRQ(ierr); 9129 ierr = PetscFree((*dmAdapt)->mattype);CHKERRQ(ierr); 9130 ierr = PetscStrallocpy(dm->mattype,(char**)&(*dmAdapt)->mattype);CHKERRQ(ierr); 9131 } 9132 PetscFunctionReturn(0); 9133 } 9134 9135 /*@C 9136 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 9137 9138 Input Parameters: 9139 + dm - The DM object 9140 . metric - The metric to which the mesh is adapted, defined vertex-wise. 9141 - 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_". 9142 9143 Output Parameter: 9144 . dmAdapt - Pointer to the DM object containing the adapted mesh 9145 9146 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 9147 9148 Level: advanced 9149 9150 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 9151 @*/ 9152 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 9153 { 9154 PetscErrorCode ierr; 9155 9156 PetscFunctionBegin; 9157 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9158 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 9159 if (bdLabel) PetscValidPointer(bdLabel, 3); 9160 PetscValidPointer(dmAdapt, 4); 9161 *dmAdapt = NULL; 9162 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 9163 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 9164 PetscFunctionReturn(0); 9165 } 9166 9167 /*@C 9168 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 9169 9170 Not Collective 9171 9172 Input Parameter: 9173 . dm - The DM 9174 9175 Output Parameters: 9176 + nranks - the number of neighbours 9177 - ranks - the neighbors ranks 9178 9179 Notes: 9180 Do not free the array, it is freed when the DM is destroyed. 9181 9182 Level: beginner 9183 9184 .seealso: DMDAGetNeighbors(), PetscSFGetRootRanks() 9185 @*/ 9186 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 9187 { 9188 PetscErrorCode ierr; 9189 9190 PetscFunctionBegin; 9191 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9192 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 9193 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 9194 PetscFunctionReturn(0); 9195 } 9196 9197 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 9198 9199 /* 9200 Converts the input vector to a ghosted vector and then calls the standard coloring code. 9201 This has be a different function because it requires DM which is not defined in the Mat library 9202 */ 9203 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 9204 { 9205 PetscErrorCode ierr; 9206 9207 PetscFunctionBegin; 9208 if (coloring->ctype == IS_COLORING_LOCAL) { 9209 Vec x1local; 9210 DM dm; 9211 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 9212 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 9213 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 9214 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 9215 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 9216 x1 = x1local; 9217 } 9218 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 9219 if (coloring->ctype == IS_COLORING_LOCAL) { 9220 DM dm; 9221 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 9222 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 9223 } 9224 PetscFunctionReturn(0); 9225 } 9226 9227 /*@ 9228 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 9229 9230 Input Parameter: 9231 . coloring - the MatFDColoring object 9232 9233 Developer Notes: 9234 this routine exists because the PETSc Mat library does not know about the DM objects 9235 9236 Level: advanced 9237 9238 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 9239 @*/ 9240 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 9241 { 9242 PetscFunctionBegin; 9243 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 9244 PetscFunctionReturn(0); 9245 } 9246 9247 /*@ 9248 DMGetCompatibility - determine if two DMs are compatible 9249 9250 Collective 9251 9252 Input Parameters: 9253 + dm1 - the first DM 9254 - dm2 - the second DM 9255 9256 Output Parameters: 9257 + compatible - whether or not the two DMs are compatible 9258 - set - whether or not the compatible value was set 9259 9260 Notes: 9261 Two DMs are deemed compatible if they represent the same parallel decomposition 9262 of the same topology. This implies that the section (field data) on one 9263 "makes sense" with respect to the topology and parallel decomposition of the other. 9264 Loosely speaking, compatible DMs represent the same domain and parallel 9265 decomposition, but hold different data. 9266 9267 Typically, one would confirm compatibility if intending to simultaneously iterate 9268 over a pair of vectors obtained from different DMs. 9269 9270 For example, two DMDA objects are compatible if they have the same local 9271 and global sizes and the same stencil width. They can have different numbers 9272 of degrees of freedom per node. Thus, one could use the node numbering from 9273 either DM in bounds for a loop over vectors derived from either DM. 9274 9275 Consider the operation of summing data living on a 2-dof DMDA to data living 9276 on a 1-dof DMDA, which should be compatible, as in the following snippet. 9277 .vb 9278 ... 9279 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 9280 if (set && compatible) { 9281 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 9282 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 9283 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 9284 for (j=y; j<y+n; ++j) { 9285 for (i=x; i<x+m, ++i) { 9286 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 9287 } 9288 } 9289 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 9290 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 9291 } else { 9292 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 9293 } 9294 ... 9295 .ve 9296 9297 Checking compatibility might be expensive for a given implementation of DM, 9298 or might be impossible to unambiguously confirm or deny. For this reason, 9299 this function may decline to determine compatibility, and hence users should 9300 always check the "set" output parameter. 9301 9302 A DM is always compatible with itself. 9303 9304 In the current implementation, DMs which live on "unequal" communicators 9305 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 9306 incompatible. 9307 9308 This function is labeled "Collective," as information about all subdomains 9309 is required on each rank. However, in DM implementations which store all this 9310 information locally, this function may be merely "Logically Collective". 9311 9312 Developer Notes: 9313 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 9314 iff B is compatible with A. Thus, this function checks the implementations 9315 of both dm and dmc (if they are of different types), attempting to determine 9316 compatibility. It is left to DM implementers to ensure that symmetry is 9317 preserved. The simplest way to do this is, when implementing type-specific 9318 logic for this function, is to check for existing logic in the implementation 9319 of other DM types and let *set = PETSC_FALSE if found. 9320 9321 Level: advanced 9322 9323 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 9324 @*/ 9325 9326 PetscErrorCode DMGetCompatibility(DM dm1,DM dm2,PetscBool *compatible,PetscBool *set) 9327 { 9328 PetscErrorCode ierr; 9329 PetscMPIInt compareResult; 9330 DMType type,type2; 9331 PetscBool sameType; 9332 9333 PetscFunctionBegin; 9334 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 9335 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 9336 9337 /* Declare a DM compatible with itself */ 9338 if (dm1 == dm2) { 9339 *set = PETSC_TRUE; 9340 *compatible = PETSC_TRUE; 9341 PetscFunctionReturn(0); 9342 } 9343 9344 /* Declare a DM incompatible with a DM that lives on an "unequal" 9345 communicator. Note that this does not preclude compatibility with 9346 DMs living on "congruent" or "similar" communicators, but this must be 9347 determined by the implementation-specific logic */ 9348 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm1),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRMPI(ierr); 9349 if (compareResult == MPI_UNEQUAL) { 9350 *set = PETSC_TRUE; 9351 *compatible = PETSC_FALSE; 9352 PetscFunctionReturn(0); 9353 } 9354 9355 /* Pass to the implementation-specific routine, if one exists. */ 9356 if (dm1->ops->getcompatibility) { 9357 ierr = (*dm1->ops->getcompatibility)(dm1,dm2,compatible,set);CHKERRQ(ierr); 9358 if (*set) PetscFunctionReturn(0); 9359 } 9360 9361 /* If dm1 and dm2 are of different types, then attempt to check compatibility 9362 with an implementation of this function from dm2 */ 9363 ierr = DMGetType(dm1,&type);CHKERRQ(ierr); 9364 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 9365 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 9366 if (!sameType && dm2->ops->getcompatibility) { 9367 ierr = (*dm2->ops->getcompatibility)(dm2,dm1,compatible,set);CHKERRQ(ierr); /* Note argument order */ 9368 } else { 9369 *set = PETSC_FALSE; 9370 } 9371 PetscFunctionReturn(0); 9372 } 9373 9374 /*@C 9375 DMMonitorSet - Sets an ADDITIONAL function that is to be used after a solve to monitor discretization performance. 9376 9377 Logically Collective on DM 9378 9379 Input Parameters: 9380 + DM - the DM 9381 . f - the monitor function 9382 . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired) 9383 - monitordestroy - [optional] routine that frees monitor context (may be NULL) 9384 9385 Options Database Keys: 9386 - -dm_monitor_cancel - cancels all monitors that have been hardwired into a code by calls to DMMonitorSet(), but 9387 does not cancel those set via the options database. 9388 9389 Notes: 9390 Several different monitoring routines may be set by calling 9391 DMMonitorSet() multiple times; all will be called in the 9392 order in which they were set. 9393 9394 Fortran Notes: 9395 Only a single monitor function can be set for each DM object 9396 9397 Level: intermediate 9398 9399 .seealso: DMMonitorCancel() 9400 @*/ 9401 PetscErrorCode DMMonitorSet(DM dm, PetscErrorCode (*f)(DM, void *), void *mctx, PetscErrorCode (*monitordestroy)(void**)) 9402 { 9403 PetscInt m; 9404 PetscErrorCode ierr; 9405 9406 PetscFunctionBegin; 9407 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9408 for (m = 0; m < dm->numbermonitors; ++m) { 9409 PetscBool identical; 9410 9411 ierr = PetscMonitorCompare((PetscErrorCode (*)(void)) f, mctx, monitordestroy, (PetscErrorCode (*)(void)) dm->monitor[m], dm->monitorcontext[m], dm->monitordestroy[m], &identical);CHKERRQ(ierr); 9412 if (identical) PetscFunctionReturn(0); 9413 } 9414 if (dm->numbermonitors >= MAXDMMONITORS) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many monitors set"); 9415 dm->monitor[dm->numbermonitors] = f; 9416 dm->monitordestroy[dm->numbermonitors] = monitordestroy; 9417 dm->monitorcontext[dm->numbermonitors++] = (void *) mctx; 9418 PetscFunctionReturn(0); 9419 } 9420 9421 /*@ 9422 DMMonitorCancel - Clears all the monitor functions for a DM object. 9423 9424 Logically Collective on DM 9425 9426 Input Parameter: 9427 . dm - the DM 9428 9429 Options Database Key: 9430 . -dm_monitor_cancel - cancels all monitors that have been hardwired 9431 into a code by calls to DMonitorSet(), but does not cancel those 9432 set via the options database 9433 9434 Notes: 9435 There is no way to clear one specific monitor from a DM object. 9436 9437 Level: intermediate 9438 9439 .seealso: DMMonitorSet() 9440 @*/ 9441 PetscErrorCode DMMonitorCancel(DM dm) 9442 { 9443 PetscErrorCode ierr; 9444 PetscInt m; 9445 9446 PetscFunctionBegin; 9447 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9448 for (m = 0; m < dm->numbermonitors; ++m) { 9449 if (dm->monitordestroy[m]) {ierr = (*dm->monitordestroy[m])(&dm->monitorcontext[m]);CHKERRQ(ierr);} 9450 } 9451 dm->numbermonitors = 0; 9452 PetscFunctionReturn(0); 9453 } 9454 9455 /*@C 9456 DMMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 9457 9458 Collective on DM 9459 9460 Input Parameters: 9461 + dm - DM object you wish to monitor 9462 . name - the monitor type one is seeking 9463 . help - message indicating what monitoring is done 9464 . manual - manual page for the monitor 9465 . monitor - the monitor function 9466 - 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 9467 9468 Output Parameter: 9469 . flg - Flag set if the monitor was created 9470 9471 Level: developer 9472 9473 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 9474 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 9475 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 9476 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 9477 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 9478 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 9479 PetscOptionsFList(), PetscOptionsEList() 9480 @*/ 9481 PetscErrorCode DMMonitorSetFromOptions(DM dm, const char name[], const char help[], const char manual[], PetscErrorCode (*monitor)(DM, void *), PetscErrorCode (*monitorsetup)(DM, PetscViewerAndFormat *), PetscBool *flg) 9482 { 9483 PetscViewer viewer; 9484 PetscViewerFormat format; 9485 PetscErrorCode ierr; 9486 9487 PetscFunctionBegin; 9488 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9489 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), ((PetscObject) dm)->options, ((PetscObject) dm)->prefix, name, &viewer, &format, flg);CHKERRQ(ierr); 9490 if (*flg) { 9491 PetscViewerAndFormat *vf; 9492 9493 ierr = PetscViewerAndFormatCreate(viewer, format, &vf);CHKERRQ(ierr); 9494 ierr = PetscObjectDereference((PetscObject) viewer);CHKERRQ(ierr); 9495 if (monitorsetup) {ierr = (*monitorsetup)(dm, vf);CHKERRQ(ierr);} 9496 ierr = DMMonitorSet(dm,(PetscErrorCode (*)(DM, void *)) monitor, vf, (PetscErrorCode (*)(void **)) PetscViewerAndFormatDestroy);CHKERRQ(ierr); 9497 } 9498 PetscFunctionReturn(0); 9499 } 9500 9501 /*@ 9502 DMMonitor - runs the user provided monitor routines, if they exist 9503 9504 Collective on DM 9505 9506 Input Parameters: 9507 . dm - The DM 9508 9509 Level: developer 9510 9511 .seealso: DMMonitorSet() 9512 @*/ 9513 PetscErrorCode DMMonitor(DM dm) 9514 { 9515 PetscInt m; 9516 PetscErrorCode ierr; 9517 9518 PetscFunctionBegin; 9519 if (!dm) PetscFunctionReturn(0); 9520 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9521 for (m = 0; m < dm->numbermonitors; ++m) { 9522 ierr = (*dm->monitor[m])(dm, dm->monitorcontext[m]);CHKERRQ(ierr); 9523 } 9524 PetscFunctionReturn(0); 9525 } 9526 9527 /*@ 9528 DMComputeError - Computes the error assuming the user has given exact solution functions 9529 9530 Collective on DM 9531 9532 Input Parameters: 9533 + dm - The DM 9534 . sol - The solution vector 9535 . errors - An array of length Nf, the number of fields, or NULL for no output 9536 - errorVec - A Vec pointer, or NULL for no output 9537 9538 Output Parameters: 9539 + errors - The error in each field 9540 - errorVec - Creates a vector to hold the cellwise error 9541 9542 Note: The exact solutions come from the PetscDS object, and the time comes from DMGetOutputSequenceNumber(). 9543 9544 Level: developer 9545 9546 .seealso: DMMonitorSet(), DMGetRegionNumDS(), PetscDSGetExactSolution(), DMGetOutputSequenceNumber() 9547 @*/ 9548 PetscErrorCode DMComputeError(DM dm, Vec sol, PetscReal errors[], Vec *errorVec) 9549 { 9550 PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 9551 void **ctxs; 9552 PetscReal time; 9553 PetscInt Nf, f, Nds, s; 9554 PetscErrorCode ierr; 9555 9556 PetscFunctionBegin; 9557 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9558 ierr = PetscCalloc2(Nf, &exactSol, Nf, &ctxs);CHKERRQ(ierr); 9559 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 9560 for (s = 0; s < Nds; ++s) { 9561 PetscDS ds; 9562 DMLabel label; 9563 IS fieldIS; 9564 const PetscInt *fields; 9565 PetscInt dsNf; 9566 9567 ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 9568 ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 9569 if (fieldIS) {ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr);} 9570 for (f = 0; f < dsNf; ++f) { 9571 const PetscInt field = fields[f]; 9572 ierr = PetscDSGetExactSolution(ds, field, &exactSol[field], &ctxs[field]);CHKERRQ(ierr); 9573 } 9574 if (fieldIS) {ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr);} 9575 } 9576 for (f = 0; f < Nf; ++f) { 9577 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); 9578 } 9579 ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr); 9580 if (errors) {ierr = DMComputeL2FieldDiff(dm, time, exactSol, ctxs, sol, errors);CHKERRQ(ierr);} 9581 if (errorVec) { 9582 DM edm; 9583 DMPolytopeType ct; 9584 PetscBool simplex; 9585 PetscInt dim, cStart, Nf; 9586 9587 ierr = DMClone(dm, &edm);CHKERRQ(ierr); 9588 ierr = DMGetDimension(edm, &dim);CHKERRQ(ierr); 9589 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr); 9590 ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr); 9591 simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE; 9592 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 9593 for (f = 0; f < Nf; ++f) { 9594 PetscFE fe, efe; 9595 PetscQuadrature q; 9596 const char *name; 9597 9598 ierr = DMGetField(dm, f, NULL, (PetscObject *) &fe);CHKERRQ(ierr); 9599 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nf, simplex, 0, PETSC_DETERMINE, &efe);CHKERRQ(ierr); 9600 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 9601 ierr = PetscObjectSetName((PetscObject) efe, name);CHKERRQ(ierr); 9602 ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 9603 ierr = PetscFESetQuadrature(efe, q);CHKERRQ(ierr); 9604 ierr = DMSetField(edm, f, NULL, (PetscObject) efe);CHKERRQ(ierr); 9605 ierr = PetscFEDestroy(&efe);CHKERRQ(ierr); 9606 } 9607 ierr = DMCreateDS(edm);CHKERRQ(ierr); 9608 9609 ierr = DMCreateGlobalVector(edm, errorVec);CHKERRQ(ierr); 9610 ierr = PetscObjectSetName((PetscObject) *errorVec, "Error");CHKERRQ(ierr); 9611 ierr = DMPlexComputeL2DiffVec(dm, time, exactSol, ctxs, sol, *errorVec);CHKERRQ(ierr); 9612 ierr = DMDestroy(&edm);CHKERRQ(ierr); 9613 } 9614 ierr = PetscFree2(exactSol, ctxs);CHKERRQ(ierr); 9615 PetscFunctionReturn(0); 9616 } 9617 9618 /*@ 9619 DMGetNumAuxiliaryVec - Get the number of auxiliary vectors associated with this DM 9620 9621 Not collective 9622 9623 Input Parameter: 9624 . dm - The DM 9625 9626 Output Parameter: 9627 . numAux - The nubmer of auxiliary data vectors 9628 9629 Level: advanced 9630 9631 .seealso: DMGetAuxiliaryLabels(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 9632 @*/ 9633 PetscErrorCode DMGetNumAuxiliaryVec(DM dm, PetscInt *numAux) 9634 { 9635 PetscErrorCode ierr; 9636 9637 PetscFunctionBegin; 9638 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9639 ierr = PetscHMapAuxGetSize(dm->auxData, numAux);CHKERRQ(ierr); 9640 PetscFunctionReturn(0); 9641 } 9642 9643 /*@ 9644 DMGetAuxiliaryVec - Get the auxiliary vector for region specified by the given label and value 9645 9646 Not collective 9647 9648 Input Parameters: 9649 + dm - The DM 9650 . label - The DMLabel 9651 - value - The label value indicating the region 9652 9653 Output Parameter: 9654 . aux - The Vec holding auxiliary field data 9655 9656 Note: If no auxiliary vector is found for this (label, value), (NULL, 0) is checked as well. 9657 9658 Level: advanced 9659 9660 .seealso: DMSetAuxiliaryVec(), DMGetNumAuxiliaryVec() 9661 @*/ 9662 PetscErrorCode DMGetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, Vec *aux) 9663 { 9664 PetscHashAuxKey key, wild = {NULL, 0}; 9665 PetscBool has; 9666 PetscErrorCode ierr; 9667 9668 PetscFunctionBegin; 9669 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9670 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 9671 key.label = label; 9672 key.value = value; 9673 ierr = PetscHMapAuxHas(dm->auxData, key, &has);CHKERRQ(ierr); 9674 if (has) {ierr = PetscHMapAuxGet(dm->auxData, key, aux);CHKERRQ(ierr);} 9675 else {ierr = PetscHMapAuxGet(dm->auxData, wild, aux);CHKERRQ(ierr);} 9676 PetscFunctionReturn(0); 9677 } 9678 9679 /*@ 9680 DMSetAuxiliaryVec - Set the auxiliary vector for region specified by the given label and value 9681 9682 Not collective 9683 9684 Input Parameters: 9685 + dm - The DM 9686 . label - The DMLabel 9687 . value - The label value indicating the region 9688 - aux - The Vec holding auxiliary field data 9689 9690 Level: advanced 9691 9692 .seealso: DMGetAuxiliaryVec() 9693 @*/ 9694 PetscErrorCode DMSetAuxiliaryVec(DM dm, DMLabel label, PetscInt value, Vec aux) 9695 { 9696 Vec old; 9697 PetscHashAuxKey key; 9698 PetscErrorCode ierr; 9699 9700 PetscFunctionBegin; 9701 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9702 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 9703 key.label = label; 9704 key.value = value; 9705 ierr = PetscHMapAuxGet(dm->auxData, key, &old);CHKERRQ(ierr); 9706 ierr = PetscObjectReference((PetscObject) aux);CHKERRQ(ierr); 9707 ierr = PetscObjectDereference((PetscObject) old);CHKERRQ(ierr); 9708 if (!aux) {ierr = PetscHMapAuxDel(dm->auxData, key);CHKERRQ(ierr);} 9709 else {ierr = PetscHMapAuxSet(dm->auxData, key, aux);CHKERRQ(ierr);} 9710 PetscFunctionReturn(0); 9711 } 9712 9713 /*@C 9714 DMGetAuxiliaryLabels - Get the labels and values for all auxiliary vectors in this DM 9715 9716 Not collective 9717 9718 Input Parameter: 9719 . dm - The DM 9720 9721 Output Parameters: 9722 + labels - The DMLabels for each Vec 9723 - values - The label values for each Vec 9724 9725 Note: The arrays passed in must be at least as large as DMGetNumAuxiliaryVec(). 9726 9727 Level: advanced 9728 9729 .seealso: DMGetNumAuxiliaryVec(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 9730 @*/ 9731 PetscErrorCode DMGetAuxiliaryLabels(DM dm, DMLabel labels[], PetscInt values[]) 9732 { 9733 PetscHashAuxKey *keys; 9734 PetscInt n, i, off = 0; 9735 PetscErrorCode ierr; 9736 9737 PetscFunctionBegin; 9738 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9739 PetscValidPointer(labels, 2); 9740 PetscValidPointer(values, 3); 9741 ierr = DMGetNumAuxiliaryVec(dm, &n);CHKERRQ(ierr); 9742 ierr = PetscMalloc1(n, &keys);CHKERRQ(ierr); 9743 ierr = PetscHMapAuxGetKeys(dm->auxData, &off, keys);CHKERRQ(ierr); 9744 for (i = 0; i < n; ++i) {labels[i] = keys[i].label; values[i] = keys[i].value;} 9745 ierr = PetscFree(keys);CHKERRQ(ierr); 9746 PetscFunctionReturn(0); 9747 } 9748 9749 /*@ 9750 DMCopyAuxiliaryVec - Copy the auxiliary data to a new DM 9751 9752 Not collective 9753 9754 Input Parameter: 9755 . dm - The DM 9756 9757 Output Parameter: 9758 . dmNew - The new DM, now with the same auxiliary data 9759 9760 Level: advanced 9761 9762 .seealso: DMGetNumAuxiliaryVec(), DMGetAuxiliaryVec(), DMSetAuxiliaryVec() 9763 @*/ 9764 PetscErrorCode DMCopyAuxiliaryVec(DM dm, DM dmNew) 9765 { 9766 PetscErrorCode ierr; 9767 9768 PetscFunctionBegin; 9769 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9770 ierr = PetscHMapAuxDestroy(&dmNew->auxData);CHKERRQ(ierr); 9771 ierr = PetscHMapAuxDuplicate(dm->auxData, &dmNew->auxData);CHKERRQ(ierr); 9772 PetscFunctionReturn(0); 9773 } 9774