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