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