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