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