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