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