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