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