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 /*@C 3185 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 3186 3187 Not Collective 3188 3189 Input Parameters: 3190 + dm - the DM object 3191 - destroy - the destroy function 3192 3193 Level: intermediate 3194 3195 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3196 3197 @*/ 3198 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 3199 { 3200 PetscFunctionBegin; 3201 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3202 dm->ctxdestroy = destroy; 3203 PetscFunctionReturn(0); 3204 } 3205 3206 /*@ 3207 DMSetApplicationContext - Set a user context into a DM object 3208 3209 Not Collective 3210 3211 Input Parameters: 3212 + dm - the DM object 3213 - ctx - the user context 3214 3215 Level: intermediate 3216 3217 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3218 3219 @*/ 3220 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 3221 { 3222 PetscFunctionBegin; 3223 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3224 dm->ctx = ctx; 3225 PetscFunctionReturn(0); 3226 } 3227 3228 /*@ 3229 DMGetApplicationContext - Gets a user context from a DM object 3230 3231 Not Collective 3232 3233 Input Parameter: 3234 . dm - the DM object 3235 3236 Output Parameter: 3237 . ctx - the user context 3238 3239 Level: intermediate 3240 3241 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3242 3243 @*/ 3244 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 3245 { 3246 PetscFunctionBegin; 3247 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3248 *(void**)ctx = dm->ctx; 3249 PetscFunctionReturn(0); 3250 } 3251 3252 /*@C 3253 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 3254 3255 Logically Collective on dm 3256 3257 Input Parameter: 3258 + dm - the DM object 3259 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 3260 3261 Level: intermediate 3262 3263 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 3264 DMSetJacobian() 3265 3266 @*/ 3267 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 3268 { 3269 PetscFunctionBegin; 3270 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3271 dm->ops->computevariablebounds = f; 3272 PetscFunctionReturn(0); 3273 } 3274 3275 /*@ 3276 DMHasVariableBounds - does the DM object have a variable bounds function? 3277 3278 Not Collective 3279 3280 Input Parameter: 3281 . dm - the DM object to destroy 3282 3283 Output Parameter: 3284 . flg - PETSC_TRUE if the variable bounds function exists 3285 3286 Level: developer 3287 3288 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3289 3290 @*/ 3291 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 3292 { 3293 PetscFunctionBegin; 3294 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3295 PetscValidPointer(flg,2); 3296 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 3297 PetscFunctionReturn(0); 3298 } 3299 3300 /*@C 3301 DMComputeVariableBounds - compute variable bounds used by SNESVI. 3302 3303 Logically Collective on dm 3304 3305 Input Parameters: 3306 . dm - the DM object 3307 3308 Output parameters: 3309 + xl - lower bound 3310 - xu - upper bound 3311 3312 Level: advanced 3313 3314 Notes: 3315 This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 3316 3317 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3318 3319 @*/ 3320 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 3321 { 3322 PetscErrorCode ierr; 3323 3324 PetscFunctionBegin; 3325 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3326 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 3327 PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 3328 if (!dm->ops->computevariablebounds) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 3329 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 3330 PetscFunctionReturn(0); 3331 } 3332 3333 /*@ 3334 DMHasColoring - does the DM object have a method of providing a coloring? 3335 3336 Not Collective 3337 3338 Input Parameter: 3339 . dm - the DM object 3340 3341 Output Parameter: 3342 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 3343 3344 Level: developer 3345 3346 .seealso DMCreateColoring() 3347 3348 @*/ 3349 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 3350 { 3351 PetscFunctionBegin; 3352 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3353 PetscValidPointer(flg,2); 3354 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 3355 PetscFunctionReturn(0); 3356 } 3357 3358 /*@ 3359 DMHasCreateRestriction - does the DM object have a method of providing a restriction? 3360 3361 Not Collective 3362 3363 Input Parameter: 3364 . dm - the DM object 3365 3366 Output Parameter: 3367 . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction(). 3368 3369 Level: developer 3370 3371 .seealso DMCreateRestriction() 3372 3373 @*/ 3374 PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg) 3375 { 3376 PetscFunctionBegin; 3377 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3378 PetscValidPointer(flg,2); 3379 *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE; 3380 PetscFunctionReturn(0); 3381 } 3382 3383 3384 /*@ 3385 DMHasCreateInjection - does the DM object have a method of providing an injection? 3386 3387 Not Collective 3388 3389 Input Parameter: 3390 . dm - the DM object 3391 3392 Output Parameter: 3393 . flg - PETSC_TRUE if the DM has facilities for DMCreateInjection(). 3394 3395 Level: developer 3396 3397 .seealso DMCreateInjection() 3398 3399 @*/ 3400 PetscErrorCode DMHasCreateInjection(DM dm,PetscBool *flg) 3401 { 3402 PetscErrorCode ierr; 3403 3404 PetscFunctionBegin; 3405 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3406 PetscValidPointer(flg,2); 3407 if (dm->ops->hascreateinjection) { 3408 ierr = (*dm->ops->hascreateinjection)(dm,flg);CHKERRQ(ierr); 3409 } else { 3410 *flg = (dm->ops->createinjection) ? PETSC_TRUE : PETSC_FALSE; 3411 } 3412 PetscFunctionReturn(0); 3413 } 3414 3415 3416 /*@C 3417 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 3418 3419 Collective on dm 3420 3421 Input Parameter: 3422 + dm - the DM object 3423 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 3424 3425 Level: developer 3426 3427 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 3428 3429 @*/ 3430 PetscErrorCode DMSetVec(DM dm,Vec x) 3431 { 3432 PetscErrorCode ierr; 3433 3434 PetscFunctionBegin; 3435 if (x) { 3436 if (!dm->x) { 3437 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 3438 } 3439 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 3440 } else if (dm->x) { 3441 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 3442 } 3443 PetscFunctionReturn(0); 3444 } 3445 3446 PetscFunctionList DMList = NULL; 3447 PetscBool DMRegisterAllCalled = PETSC_FALSE; 3448 3449 /*@C 3450 DMSetType - Builds a DM, for a particular DM implementation. 3451 3452 Collective on dm 3453 3454 Input Parameters: 3455 + dm - The DM object 3456 - method - The name of the DM type 3457 3458 Options Database Key: 3459 . -dm_type <type> - Sets the DM type; use -help for a list of available types 3460 3461 Notes: 3462 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 3463 3464 Level: intermediate 3465 3466 .seealso: DMGetType(), DMCreate() 3467 @*/ 3468 PetscErrorCode DMSetType(DM dm, DMType method) 3469 { 3470 PetscErrorCode (*r)(DM); 3471 PetscBool match; 3472 PetscErrorCode ierr; 3473 3474 PetscFunctionBegin; 3475 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3476 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 3477 if (match) PetscFunctionReturn(0); 3478 3479 ierr = DMRegisterAll();CHKERRQ(ierr); 3480 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 3481 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 3482 3483 if (dm->ops->destroy) { 3484 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 3485 } 3486 ierr = PetscMemzero(dm->ops,sizeof(*dm->ops));CHKERRQ(ierr); 3487 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 3488 ierr = (*r)(dm);CHKERRQ(ierr); 3489 PetscFunctionReturn(0); 3490 } 3491 3492 /*@C 3493 DMGetType - Gets the DM type name (as a string) from the DM. 3494 3495 Not Collective 3496 3497 Input Parameter: 3498 . dm - The DM 3499 3500 Output Parameter: 3501 . type - The DM type name 3502 3503 Level: intermediate 3504 3505 .seealso: DMSetType(), DMCreate() 3506 @*/ 3507 PetscErrorCode DMGetType(DM dm, DMType *type) 3508 { 3509 PetscErrorCode ierr; 3510 3511 PetscFunctionBegin; 3512 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3513 PetscValidPointer(type,2); 3514 ierr = DMRegisterAll();CHKERRQ(ierr); 3515 *type = ((PetscObject)dm)->type_name; 3516 PetscFunctionReturn(0); 3517 } 3518 3519 /*@C 3520 DMConvert - Converts a DM to another DM, either of the same or different type. 3521 3522 Collective on dm 3523 3524 Input Parameters: 3525 + dm - the DM 3526 - newtype - new DM type (use "same" for the same type) 3527 3528 Output Parameter: 3529 . M - pointer to new DM 3530 3531 Notes: 3532 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 3533 the MPI communicator of the generated DM is always the same as the communicator 3534 of the input DM. 3535 3536 Level: intermediate 3537 3538 .seealso: DMCreate() 3539 @*/ 3540 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 3541 { 3542 DM B; 3543 char convname[256]; 3544 PetscBool sametype/*, issame */; 3545 PetscErrorCode ierr; 3546 3547 PetscFunctionBegin; 3548 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3549 PetscValidType(dm,1); 3550 PetscValidPointer(M,3); 3551 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 3552 /* ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); */ 3553 if (sametype) { 3554 *M = dm; 3555 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 3556 PetscFunctionReturn(0); 3557 } else { 3558 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 3559 3560 /* 3561 Order of precedence: 3562 1) See if a specialized converter is known to the current DM. 3563 2) See if a specialized converter is known to the desired DM class. 3564 3) See if a good general converter is registered for the desired class 3565 4) See if a good general converter is known for the current matrix. 3566 5) Use a really basic converter. 3567 */ 3568 3569 /* 1) See if a specialized converter is known to the current DM and the desired class */ 3570 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3571 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3572 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3573 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3574 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3575 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 3576 if (conv) goto foundconv; 3577 3578 /* 2) See if a specialized converter is known to the desired DM class. */ 3579 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 3580 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 3581 ierr = PetscStrncpy(convname,"DMConvert_",sizeof(convname));CHKERRQ(ierr); 3582 ierr = PetscStrlcat(convname,((PetscObject) dm)->type_name,sizeof(convname));CHKERRQ(ierr); 3583 ierr = PetscStrlcat(convname,"_",sizeof(convname));CHKERRQ(ierr); 3584 ierr = PetscStrlcat(convname,newtype,sizeof(convname));CHKERRQ(ierr); 3585 ierr = PetscStrlcat(convname,"_C",sizeof(convname));CHKERRQ(ierr); 3586 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 3587 if (conv) { 3588 ierr = DMDestroy(&B);CHKERRQ(ierr); 3589 goto foundconv; 3590 } 3591 3592 #if 0 3593 /* 3) See if a good general converter is registered for the desired class */ 3594 conv = B->ops->convertfrom; 3595 ierr = DMDestroy(&B);CHKERRQ(ierr); 3596 if (conv) goto foundconv; 3597 3598 /* 4) See if a good general converter is known for the current matrix */ 3599 if (dm->ops->convert) { 3600 conv = dm->ops->convert; 3601 } 3602 if (conv) goto foundconv; 3603 #endif 3604 3605 /* 5) Use a really basic converter. */ 3606 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 3607 3608 foundconv: 3609 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3610 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 3611 /* Things that are independent of DM type: We should consult DMClone() here */ 3612 { 3613 PetscBool isper; 3614 const PetscReal *maxCell, *L; 3615 const DMBoundaryType *bd; 3616 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 3617 ierr = DMSetPeriodicity(*M, isper, maxCell, L, bd);CHKERRQ(ierr); 3618 } 3619 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3620 } 3621 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 3622 PetscFunctionReturn(0); 3623 } 3624 3625 /*--------------------------------------------------------------------------------------------------------------------*/ 3626 3627 /*@C 3628 DMRegister - Adds a new DM component implementation 3629 3630 Not Collective 3631 3632 Input Parameters: 3633 + name - The name of a new user-defined creation routine 3634 - create_func - The creation routine itself 3635 3636 Notes: 3637 DMRegister() may be called multiple times to add several user-defined DMs 3638 3639 3640 Sample usage: 3641 .vb 3642 DMRegister("my_da", MyDMCreate); 3643 .ve 3644 3645 Then, your DM type can be chosen with the procedural interface via 3646 .vb 3647 DMCreate(MPI_Comm, DM *); 3648 DMSetType(DM,"my_da"); 3649 .ve 3650 or at runtime via the option 3651 .vb 3652 -da_type my_da 3653 .ve 3654 3655 Level: advanced 3656 3657 .seealso: DMRegisterAll(), DMRegisterDestroy() 3658 3659 @*/ 3660 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 3661 { 3662 PetscErrorCode ierr; 3663 3664 PetscFunctionBegin; 3665 ierr = DMInitializePackage();CHKERRQ(ierr); 3666 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 3667 PetscFunctionReturn(0); 3668 } 3669 3670 /*@C 3671 DMLoad - Loads a DM that has been stored in binary with DMView(). 3672 3673 Collective on viewer 3674 3675 Input Parameters: 3676 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 3677 some related function before a call to DMLoad(). 3678 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 3679 HDF5 file viewer, obtained from PetscViewerHDF5Open() 3680 3681 Level: intermediate 3682 3683 Notes: 3684 The type is determined by the data in the file, any type set into the DM before this call is ignored. 3685 3686 Notes for advanced users: 3687 Most users should not need to know the details of the binary storage 3688 format, since DMLoad() and DMView() completely hide these details. 3689 But for anyone who's interested, the standard binary matrix storage 3690 format is 3691 .vb 3692 has not yet been determined 3693 .ve 3694 3695 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 3696 @*/ 3697 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 3698 { 3699 PetscBool isbinary, ishdf5; 3700 PetscErrorCode ierr; 3701 3702 PetscFunctionBegin; 3703 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 3704 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3705 ierr = PetscViewerCheckReadable(viewer);CHKERRQ(ierr); 3706 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 3707 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 3708 if (isbinary) { 3709 PetscInt classid; 3710 char type[256]; 3711 3712 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3713 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3714 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3715 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3716 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3717 } else if (ishdf5) { 3718 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3719 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3720 PetscFunctionReturn(0); 3721 } 3722 3723 /******************************** FEM Support **********************************/ 3724 3725 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3726 { 3727 PetscInt f; 3728 PetscErrorCode ierr; 3729 3730 PetscFunctionBegin; 3731 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3732 for (f = 0; f < len; ++f) { 3733 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3734 } 3735 PetscFunctionReturn(0); 3736 } 3737 3738 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3739 { 3740 PetscInt f, g; 3741 PetscErrorCode ierr; 3742 3743 PetscFunctionBegin; 3744 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3745 for (f = 0; f < rows; ++f) { 3746 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3747 for (g = 0; g < cols; ++g) { 3748 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3749 } 3750 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3751 } 3752 PetscFunctionReturn(0); 3753 } 3754 3755 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3756 { 3757 PetscInt localSize, bs; 3758 PetscMPIInt size; 3759 Vec x, xglob; 3760 const PetscScalar *xarray; 3761 PetscErrorCode ierr; 3762 3763 PetscFunctionBegin; 3764 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm),&size);CHKERRQ(ierr); 3765 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3766 ierr = VecCopy(X, x);CHKERRQ(ierr); 3767 ierr = VecChop(x, tol);CHKERRQ(ierr); 3768 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm),"%s:\n",name);CHKERRQ(ierr); 3769 if (size > 1) { 3770 ierr = VecGetLocalSize(x,&localSize);CHKERRQ(ierr); 3771 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr); 3772 ierr = VecGetBlockSize(x,&bs);CHKERRQ(ierr); 3773 ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject) dm),bs,localSize,PETSC_DETERMINE,xarray,&xglob);CHKERRQ(ierr); 3774 } else { 3775 xglob = x; 3776 } 3777 ierr = VecView(xglob,PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject) dm)));CHKERRQ(ierr); 3778 if (size > 1) { 3779 ierr = VecDestroy(&xglob);CHKERRQ(ierr); 3780 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 3781 } 3782 ierr = VecDestroy(&x);CHKERRQ(ierr); 3783 PetscFunctionReturn(0); 3784 } 3785 3786 /*@ 3787 DMGetSection - Get the PetscSection encoding the local data layout for the DM. 3788 3789 Input Parameter: 3790 . dm - The DM 3791 3792 Output Parameter: 3793 . section - The PetscSection 3794 3795 Options Database Keys: 3796 . -dm_petscsection_view - View the Section created by the DM 3797 3798 Level: intermediate 3799 3800 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3801 3802 .seealso: DMSetSection(), DMGetGlobalSection() 3803 @*/ 3804 PetscErrorCode DMGetSection(DM dm, PetscSection *section) 3805 { 3806 PetscErrorCode ierr; 3807 3808 PetscFunctionBegin; 3809 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3810 PetscValidPointer(section, 2); 3811 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3812 PetscInt d; 3813 3814 if (dm->setfromoptionscalled) for (d = 0; d < dm->Nds; ++d) {ierr = PetscDSSetFromOptions(dm->probs[d].ds);CHKERRQ(ierr);} 3815 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3816 if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 3817 } 3818 *section = dm->defaultSection; 3819 PetscFunctionReturn(0); 3820 } 3821 3822 /*@ 3823 DMSetSection - Set the PetscSection encoding the local data layout for the DM. 3824 3825 Input Parameters: 3826 + dm - The DM 3827 - section - The PetscSection 3828 3829 Level: intermediate 3830 3831 Note: Any existing Section will be destroyed 3832 3833 .seealso: DMSetSection(), DMGetGlobalSection() 3834 @*/ 3835 PetscErrorCode DMSetSection(DM dm, PetscSection section) 3836 { 3837 PetscInt numFields = 0; 3838 PetscInt f; 3839 PetscErrorCode ierr; 3840 3841 PetscFunctionBegin; 3842 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3843 if (section) { 3844 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3845 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3846 } 3847 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3848 dm->defaultSection = section; 3849 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3850 if (numFields) { 3851 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3852 for (f = 0; f < numFields; ++f) { 3853 PetscObject disc; 3854 const char *name; 3855 3856 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3857 ierr = DMGetField(dm, f, NULL, &disc);CHKERRQ(ierr); 3858 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3859 } 3860 } 3861 /* The global section will be rebuilt in the next call to DMGetGlobalSection(). */ 3862 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3863 PetscFunctionReturn(0); 3864 } 3865 3866 /*@ 3867 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3868 3869 not collective 3870 3871 Input Parameter: 3872 . dm - The DM 3873 3874 Output Parameter: 3875 + 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. 3876 - 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. 3877 3878 Level: advanced 3879 3880 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3881 3882 .seealso: DMSetDefaultConstraints() 3883 @*/ 3884 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3885 { 3886 PetscErrorCode ierr; 3887 3888 PetscFunctionBegin; 3889 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3890 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3891 if (section) {*section = dm->defaultConstraintSection;} 3892 if (mat) {*mat = dm->defaultConstraintMat;} 3893 PetscFunctionReturn(0); 3894 } 3895 3896 /*@ 3897 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3898 3899 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(). 3900 3901 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. 3902 3903 collective on dm 3904 3905 Input Parameters: 3906 + dm - The DM 3907 + 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). 3908 - 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). 3909 3910 Level: advanced 3911 3912 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3913 3914 .seealso: DMGetDefaultConstraints() 3915 @*/ 3916 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3917 { 3918 PetscMPIInt result; 3919 PetscErrorCode ierr; 3920 3921 PetscFunctionBegin; 3922 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3923 if (section) { 3924 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3925 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3926 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3927 } 3928 if (mat) { 3929 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3930 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3931 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3932 } 3933 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3934 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3935 dm->defaultConstraintSection = section; 3936 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3937 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3938 dm->defaultConstraintMat = mat; 3939 PetscFunctionReturn(0); 3940 } 3941 3942 #if defined(PETSC_USE_DEBUG) 3943 /* 3944 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3945 3946 Input Parameters: 3947 + dm - The DM 3948 . localSection - PetscSection describing the local data layout 3949 - globalSection - PetscSection describing the global data layout 3950 3951 Level: intermediate 3952 3953 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3954 */ 3955 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3956 { 3957 MPI_Comm comm; 3958 PetscLayout layout; 3959 const PetscInt *ranges; 3960 PetscInt pStart, pEnd, p, nroots; 3961 PetscMPIInt size, rank; 3962 PetscBool valid = PETSC_TRUE, gvalid; 3963 PetscErrorCode ierr; 3964 3965 PetscFunctionBegin; 3966 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3967 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3968 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3969 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3970 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3971 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3972 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3973 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3974 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3975 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3976 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3977 for (p = pStart; p < pEnd; ++p) { 3978 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3979 3980 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3981 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3982 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3983 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3984 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3985 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3986 if (!gdof) continue; /* Censored point */ 3987 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;} 3988 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;} 3989 if (gdof < 0) { 3990 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3991 for (d = 0; d < gsize; ++d) { 3992 PetscInt offset = -(goff+1) + d, r; 3993 3994 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3995 if (r < 0) r = -(r+2); 3996 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;} 3997 } 3998 } 3999 } 4000 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 4001 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 4002 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 4003 if (!gvalid) { 4004 ierr = DMView(dm, NULL);CHKERRQ(ierr); 4005 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 4006 } 4007 PetscFunctionReturn(0); 4008 } 4009 #endif 4010 4011 /*@ 4012 DMGetGlobalSection - Get the PetscSection encoding the global data layout for the DM. 4013 4014 Collective on dm 4015 4016 Input Parameter: 4017 . dm - The DM 4018 4019 Output Parameter: 4020 . section - The PetscSection 4021 4022 Level: intermediate 4023 4024 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 4025 4026 .seealso: DMSetSection(), DMGetSection() 4027 @*/ 4028 PetscErrorCode DMGetGlobalSection(DM dm, PetscSection *section) 4029 { 4030 PetscErrorCode ierr; 4031 4032 PetscFunctionBegin; 4033 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4034 PetscValidPointer(section, 2); 4035 if (!dm->defaultGlobalSection) { 4036 PetscSection s; 4037 4038 ierr = DMGetSection(dm, &s);CHKERRQ(ierr); 4039 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 4040 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a point PetscSF in order to create a global PetscSection"); 4041 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 4042 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 4043 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 4044 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 4045 } 4046 *section = dm->defaultGlobalSection; 4047 PetscFunctionReturn(0); 4048 } 4049 4050 /*@ 4051 DMSetGlobalSection - Set the PetscSection encoding the global data layout for the DM. 4052 4053 Input Parameters: 4054 + dm - The DM 4055 - section - The PetscSection, or NULL 4056 4057 Level: intermediate 4058 4059 Note: Any existing Section will be destroyed 4060 4061 .seealso: DMGetGlobalSection(), DMSetSection() 4062 @*/ 4063 PetscErrorCode DMSetGlobalSection(DM dm, PetscSection section) 4064 { 4065 PetscErrorCode ierr; 4066 4067 PetscFunctionBegin; 4068 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4069 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 4070 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 4071 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 4072 dm->defaultGlobalSection = section; 4073 #if defined(PETSC_USE_DEBUG) 4074 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 4075 #endif 4076 PetscFunctionReturn(0); 4077 } 4078 4079 /*@ 4080 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 4081 it is created from the default PetscSection layouts in the DM. 4082 4083 Input Parameter: 4084 . dm - The DM 4085 4086 Output Parameter: 4087 . sf - The PetscSF 4088 4089 Level: intermediate 4090 4091 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4092 4093 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 4094 @*/ 4095 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 4096 { 4097 PetscInt nroots; 4098 PetscErrorCode ierr; 4099 4100 PetscFunctionBegin; 4101 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4102 PetscValidPointer(sf, 2); 4103 if (!dm->defaultSF) { 4104 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm),&dm->defaultSF);CHKERRQ(ierr); 4105 } 4106 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 4107 if (nroots < 0) { 4108 PetscSection section, gSection; 4109 4110 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 4111 if (section) { 4112 ierr = DMGetGlobalSection(dm, &gSection);CHKERRQ(ierr); 4113 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 4114 } else { 4115 *sf = NULL; 4116 PetscFunctionReturn(0); 4117 } 4118 } 4119 *sf = dm->defaultSF; 4120 PetscFunctionReturn(0); 4121 } 4122 4123 /*@ 4124 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 4125 4126 Input Parameters: 4127 + dm - The DM 4128 - sf - The PetscSF 4129 4130 Level: intermediate 4131 4132 Note: Any previous SF is destroyed 4133 4134 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 4135 @*/ 4136 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 4137 { 4138 PetscErrorCode ierr; 4139 4140 PetscFunctionBegin; 4141 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4142 if (sf) { 4143 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4144 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4145 } 4146 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 4147 dm->defaultSF = sf; 4148 PetscFunctionReturn(0); 4149 } 4150 4151 /*@C 4152 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 4153 describing the data layout. 4154 4155 Input Parameters: 4156 + dm - The DM 4157 . localSection - PetscSection describing the local data layout 4158 - globalSection - PetscSection describing the global data layout 4159 4160 Level: intermediate 4161 4162 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 4163 @*/ 4164 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 4165 { 4166 MPI_Comm comm; 4167 PetscLayout layout; 4168 const PetscInt *ranges; 4169 PetscInt *local; 4170 PetscSFNode *remote; 4171 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 4172 PetscMPIInt size, rank; 4173 PetscErrorCode ierr; 4174 4175 PetscFunctionBegin; 4176 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4177 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 4178 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 4179 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4180 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 4181 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 4182 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 4183 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 4184 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 4185 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 4186 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 4187 for (p = pStart; p < pEnd; ++p) { 4188 PetscInt gdof, gcdof; 4189 4190 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4191 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4192 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)); 4193 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4194 } 4195 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 4196 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 4197 for (p = pStart, l = 0; p < pEnd; ++p) { 4198 const PetscInt *cind; 4199 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 4200 4201 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 4202 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 4203 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 4204 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 4205 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 4206 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 4207 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 4208 if (!gdof) continue; /* Censored point */ 4209 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 4210 if (gsize != dof-cdof) { 4211 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); 4212 cdof = 0; /* Ignore constraints */ 4213 } 4214 for (d = 0, c = 0; d < dof; ++d) { 4215 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 4216 local[l+d-c] = off+d; 4217 } 4218 if (gdof < 0) { 4219 for (d = 0; d < gsize; ++d, ++l) { 4220 PetscInt offset = -(goff+1) + d, r; 4221 4222 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 4223 if (r < 0) r = -(r+2); 4224 if ((r < 0) || (r >= size)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d mapped to invalid process %d (%d, %d)", p, r, gdof, goff); 4225 remote[l].rank = r; 4226 remote[l].index = offset - ranges[r]; 4227 } 4228 } else { 4229 for (d = 0; d < gsize; ++d, ++l) { 4230 remote[l].rank = rank; 4231 remote[l].index = goff+d - ranges[rank]; 4232 } 4233 } 4234 } 4235 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 4236 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 4237 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 4238 PetscFunctionReturn(0); 4239 } 4240 4241 /*@ 4242 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 4243 4244 Input Parameter: 4245 . dm - The DM 4246 4247 Output Parameter: 4248 . sf - The PetscSF 4249 4250 Level: intermediate 4251 4252 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 4253 4254 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 4255 @*/ 4256 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 4257 { 4258 PetscFunctionBegin; 4259 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4260 PetscValidPointer(sf, 2); 4261 *sf = dm->sf; 4262 PetscFunctionReturn(0); 4263 } 4264 4265 /*@ 4266 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 4267 4268 Input Parameters: 4269 + dm - The DM 4270 - sf - The PetscSF 4271 4272 Level: intermediate 4273 4274 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 4275 @*/ 4276 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 4277 { 4278 PetscErrorCode ierr; 4279 4280 PetscFunctionBegin; 4281 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4282 if (sf) { 4283 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 4284 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 4285 } 4286 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 4287 dm->sf = sf; 4288 PetscFunctionReturn(0); 4289 } 4290 4291 static PetscErrorCode DMSetDefaultAdjacency_Private(DM dm, PetscInt f, PetscObject disc) 4292 { 4293 PetscClassId id; 4294 PetscErrorCode ierr; 4295 4296 PetscFunctionBegin; 4297 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 4298 if (id == PETSCFE_CLASSID) { 4299 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr); 4300 } else if (id == PETSCFV_CLASSID) { 4301 ierr = DMSetAdjacency(dm, f, PETSC_TRUE, PETSC_FALSE);CHKERRQ(ierr); 4302 } else { 4303 ierr = DMSetAdjacency(dm, f, PETSC_FALSE, PETSC_TRUE);CHKERRQ(ierr); 4304 } 4305 PetscFunctionReturn(0); 4306 } 4307 4308 static PetscErrorCode DMFieldEnlarge_Static(DM dm, PetscInt NfNew) 4309 { 4310 RegionField *tmpr; 4311 PetscInt Nf = dm->Nf, f; 4312 PetscErrorCode ierr; 4313 4314 PetscFunctionBegin; 4315 if (Nf >= NfNew) PetscFunctionReturn(0); 4316 ierr = PetscMalloc1(NfNew, &tmpr);CHKERRQ(ierr); 4317 for (f = 0; f < Nf; ++f) tmpr[f] = dm->fields[f]; 4318 for (f = Nf; f < NfNew; ++f) {tmpr[f].disc = NULL; tmpr[f].label = NULL;} 4319 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4320 dm->Nf = NfNew; 4321 dm->fields = tmpr; 4322 PetscFunctionReturn(0); 4323 } 4324 4325 /*@ 4326 DMClearFields - Remove all fields from the DM 4327 4328 Logically collective on dm 4329 4330 Input Parameter: 4331 . dm - The DM 4332 4333 Level: intermediate 4334 4335 .seealso: DMGetNumFields(), DMSetNumFields(), DMSetField() 4336 @*/ 4337 PetscErrorCode DMClearFields(DM dm) 4338 { 4339 PetscInt f; 4340 PetscErrorCode ierr; 4341 4342 PetscFunctionBegin; 4343 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4344 for (f = 0; f < dm->Nf; ++f) { 4345 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4346 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4347 } 4348 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 4349 dm->fields = NULL; 4350 dm->Nf = 0; 4351 PetscFunctionReturn(0); 4352 } 4353 4354 /*@ 4355 DMGetNumFields - Get the number of fields in the DM 4356 4357 Not collective 4358 4359 Input Parameter: 4360 . dm - The DM 4361 4362 Output Parameter: 4363 . Nf - The number of fields 4364 4365 Level: intermediate 4366 4367 .seealso: DMSetNumFields(), DMSetField() 4368 @*/ 4369 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 4370 { 4371 PetscFunctionBegin; 4372 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4373 PetscValidPointer(numFields, 2); 4374 *numFields = dm->Nf; 4375 PetscFunctionReturn(0); 4376 } 4377 4378 /*@ 4379 DMSetNumFields - Set the number of fields in the DM 4380 4381 Logically collective on dm 4382 4383 Input Parameters: 4384 + dm - The DM 4385 - Nf - The number of fields 4386 4387 Level: intermediate 4388 4389 .seealso: DMGetNumFields(), DMSetField() 4390 @*/ 4391 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 4392 { 4393 PetscInt Nf, f; 4394 PetscErrorCode ierr; 4395 4396 PetscFunctionBegin; 4397 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4398 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4399 for (f = Nf; f < numFields; ++f) { 4400 PetscContainer obj; 4401 4402 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 4403 ierr = DMAddField(dm, NULL, (PetscObject) obj);CHKERRQ(ierr); 4404 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 4405 } 4406 PetscFunctionReturn(0); 4407 } 4408 4409 /*@ 4410 DMGetField - Return the discretization object for a given DM field 4411 4412 Not collective 4413 4414 Input Parameters: 4415 + dm - The DM 4416 - f - The field number 4417 4418 Output Parameters: 4419 + label - The label indicating the support of the field, or NULL for the entire mesh 4420 - field - The discretization object 4421 4422 Level: intermediate 4423 4424 .seealso: DMAddField(), DMSetField() 4425 @*/ 4426 PetscErrorCode DMGetField(DM dm, PetscInt f, DMLabel *label, PetscObject *field) 4427 { 4428 PetscFunctionBegin; 4429 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4430 PetscValidPointer(field, 3); 4431 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); 4432 if (label) *label = dm->fields[f].label; 4433 if (field) *field = dm->fields[f].disc; 4434 PetscFunctionReturn(0); 4435 } 4436 4437 /*@ 4438 DMSetField - Set the discretization object for a given DM field 4439 4440 Logically collective on dm 4441 4442 Input Parameters: 4443 + dm - The DM 4444 . f - The field number 4445 . label - The label indicating the support of the field, or NULL for the entire mesh 4446 - field - The discretization object 4447 4448 Level: intermediate 4449 4450 .seealso: DMAddField(), DMGetField() 4451 @*/ 4452 PetscErrorCode DMSetField(DM dm, PetscInt f, DMLabel label, PetscObject field) 4453 { 4454 PetscErrorCode ierr; 4455 4456 PetscFunctionBegin; 4457 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4458 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3); 4459 PetscValidHeader(field, 4); 4460 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 4461 ierr = DMFieldEnlarge_Static(dm, f+1);CHKERRQ(ierr); 4462 ierr = DMLabelDestroy(&dm->fields[f].label);CHKERRQ(ierr); 4463 ierr = PetscObjectDestroy(&dm->fields[f].disc);CHKERRQ(ierr); 4464 dm->fields[f].label = label; 4465 dm->fields[f].disc = field; 4466 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4467 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 4468 ierr = DMSetDefaultAdjacency_Private(dm, f, field);CHKERRQ(ierr); 4469 ierr = DMClearDS(dm);CHKERRQ(ierr); 4470 PetscFunctionReturn(0); 4471 } 4472 4473 /*@ 4474 DMAddField - Add the discretization object for the given DM field 4475 4476 Logically collective on dm 4477 4478 Input Parameters: 4479 + dm - The DM 4480 . label - The label indicating the support of the field, or NULL for the entire mesh 4481 - field - The discretization object 4482 4483 Level: intermediate 4484 4485 .seealso: DMSetField(), DMGetField() 4486 @*/ 4487 PetscErrorCode DMAddField(DM dm, DMLabel label, PetscObject field) 4488 { 4489 PetscInt Nf = dm->Nf; 4490 PetscErrorCode ierr; 4491 4492 PetscFunctionBegin; 4493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4494 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 3); 4495 PetscValidHeader(field, 3); 4496 ierr = DMFieldEnlarge_Static(dm, Nf+1);CHKERRQ(ierr); 4497 dm->fields[Nf].label = label; 4498 dm->fields[Nf].disc = field; 4499 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4500 ierr = PetscObjectReference((PetscObject) field);CHKERRQ(ierr); 4501 ierr = DMSetDefaultAdjacency_Private(dm, Nf, field);CHKERRQ(ierr); 4502 ierr = DMClearDS(dm);CHKERRQ(ierr); 4503 PetscFunctionReturn(0); 4504 } 4505 4506 /*@ 4507 DMCopyFields - Copy the discretizations for the DM into another DM 4508 4509 Collective on dm 4510 4511 Input Parameter: 4512 . dm - The DM 4513 4514 Output Parameter: 4515 . newdm - The DM 4516 4517 Level: advanced 4518 4519 .seealso: DMGetField(), DMSetField(), DMAddField(), DMCopyDS(), DMGetDS(), DMGetCellDS() 4520 @*/ 4521 PetscErrorCode DMCopyFields(DM dm, DM newdm) 4522 { 4523 PetscInt Nf, f; 4524 PetscErrorCode ierr; 4525 4526 PetscFunctionBegin; 4527 if (dm == newdm) PetscFunctionReturn(0); 4528 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4529 ierr = DMClearFields(newdm);CHKERRQ(ierr); 4530 for (f = 0; f < Nf; ++f) { 4531 DMLabel label; 4532 PetscObject field; 4533 PetscBool useCone, useClosure; 4534 4535 ierr = DMGetField(dm, f, &label, &field);CHKERRQ(ierr); 4536 ierr = DMSetField(newdm, f, label, field);CHKERRQ(ierr); 4537 ierr = DMGetAdjacency(dm, f, &useCone, &useClosure);CHKERRQ(ierr); 4538 ierr = DMSetAdjacency(newdm, f, useCone, useClosure);CHKERRQ(ierr); 4539 } 4540 PetscFunctionReturn(0); 4541 } 4542 4543 /*@ 4544 DMGetAdjacency - Returns the flags for determining variable influence 4545 4546 Not collective 4547 4548 Input Parameters: 4549 + dm - The DM object 4550 - f - The field number, or PETSC_DEFAULT for the default adjacency 4551 4552 Output Parameter: 4553 + useCone - Flag for variable influence starting with the cone operation 4554 - useClosure - Flag for variable influence using transitive closure 4555 4556 Notes: 4557 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4558 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4559 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4560 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another. 4561 4562 Level: developer 4563 4564 .seealso: DMSetAdjacency(), DMGetField(), DMSetField() 4565 @*/ 4566 PetscErrorCode DMGetAdjacency(DM dm, PetscInt f, PetscBool *useCone, PetscBool *useClosure) 4567 { 4568 PetscFunctionBegin; 4569 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4570 if (useCone) PetscValidPointer(useCone, 3); 4571 if (useClosure) PetscValidPointer(useClosure, 4); 4572 if (f < 0) { 4573 if (useCone) *useCone = dm->adjacency[0]; 4574 if (useClosure) *useClosure = dm->adjacency[1]; 4575 } else { 4576 PetscInt Nf; 4577 PetscErrorCode ierr; 4578 4579 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4580 if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf); 4581 if (useCone) *useCone = dm->fields[f].adjacency[0]; 4582 if (useClosure) *useClosure = dm->fields[f].adjacency[1]; 4583 } 4584 PetscFunctionReturn(0); 4585 } 4586 4587 /*@ 4588 DMSetAdjacency - Set the flags for determining variable influence 4589 4590 Not collective 4591 4592 Input Parameters: 4593 + dm - The DM object 4594 . f - The field number 4595 . useCone - Flag for variable influence starting with the cone operation 4596 - useClosure - Flag for variable influence using transitive closure 4597 4598 Notes: 4599 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4600 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4601 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4602 Further explanation can be found in the User's Manual Section on the Influence of Variables on One Another. 4603 4604 Level: developer 4605 4606 .seealso: DMGetAdjacency(), DMGetField(), DMSetField() 4607 @*/ 4608 PetscErrorCode DMSetAdjacency(DM dm, PetscInt f, PetscBool useCone, PetscBool useClosure) 4609 { 4610 PetscFunctionBegin; 4611 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4612 if (f < 0) { 4613 dm->adjacency[0] = useCone; 4614 dm->adjacency[1] = useClosure; 4615 } else { 4616 PetscInt Nf; 4617 PetscErrorCode ierr; 4618 4619 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4620 if (f >= Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, Nf); 4621 dm->fields[f].adjacency[0] = useCone; 4622 dm->fields[f].adjacency[1] = useClosure; 4623 } 4624 PetscFunctionReturn(0); 4625 } 4626 4627 /*@ 4628 DMGetBasicAdjacency - Returns the flags for determining variable influence, using either the default or field 0 if it is defined 4629 4630 Not collective 4631 4632 Input Parameters: 4633 . dm - The DM object 4634 4635 Output Parameter: 4636 + useCone - Flag for variable influence starting with the cone operation 4637 - useClosure - Flag for variable influence using transitive closure 4638 4639 Notes: 4640 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4641 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4642 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4643 4644 Level: developer 4645 4646 .seealso: DMSetBasicAdjacency(), DMGetField(), DMSetField() 4647 @*/ 4648 PetscErrorCode DMGetBasicAdjacency(DM dm, PetscBool *useCone, PetscBool *useClosure) 4649 { 4650 PetscInt Nf; 4651 PetscErrorCode ierr; 4652 4653 PetscFunctionBegin; 4654 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4655 if (useCone) PetscValidPointer(useCone, 3); 4656 if (useClosure) PetscValidPointer(useClosure, 4); 4657 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4658 if (!Nf) { 4659 ierr = DMGetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 4660 } else { 4661 ierr = DMGetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr); 4662 } 4663 PetscFunctionReturn(0); 4664 } 4665 4666 /*@ 4667 DMSetBasicAdjacency - Set the flags for determining variable influence, using either the default or field 0 if it is defined 4668 4669 Not collective 4670 4671 Input Parameters: 4672 + dm - The DM object 4673 . useCone - Flag for variable influence starting with the cone operation 4674 - useClosure - Flag for variable influence using transitive closure 4675 4676 Notes: 4677 $ FEM: Two points p and q are adjacent if q \in closure(star(p)), useCone = PETSC_FALSE, useClosure = PETSC_TRUE 4678 $ FVM: Two points p and q are adjacent if q \in support(p+cone(p)), useCone = PETSC_TRUE, useClosure = PETSC_FALSE 4679 $ FVM++: Two points p and q are adjacent if q \in star(closure(p)), useCone = PETSC_TRUE, useClosure = PETSC_TRUE 4680 4681 Level: developer 4682 4683 .seealso: DMGetBasicAdjacency(), DMGetField(), DMSetField() 4684 @*/ 4685 PetscErrorCode DMSetBasicAdjacency(DM dm, PetscBool useCone, PetscBool useClosure) 4686 { 4687 PetscInt Nf; 4688 PetscErrorCode ierr; 4689 4690 PetscFunctionBegin; 4691 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4692 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4693 if (!Nf) { 4694 ierr = DMSetAdjacency(dm, PETSC_DEFAULT, useCone, useClosure);CHKERRQ(ierr); 4695 } else { 4696 ierr = DMSetAdjacency(dm, 0, useCone, useClosure);CHKERRQ(ierr); 4697 } 4698 PetscFunctionReturn(0); 4699 } 4700 4701 static PetscErrorCode DMDSEnlarge_Static(DM dm, PetscInt NdsNew) 4702 { 4703 DMSpace *tmpd; 4704 PetscInt Nds = dm->Nds, s; 4705 PetscErrorCode ierr; 4706 4707 PetscFunctionBegin; 4708 if (Nds >= NdsNew) PetscFunctionReturn(0); 4709 ierr = PetscMalloc1(NdsNew, &tmpd);CHKERRQ(ierr); 4710 for (s = 0; s < Nds; ++s) tmpd[s] = dm->probs[s]; 4711 for (s = Nds; s < NdsNew; ++s) {tmpd[s].ds = NULL; tmpd[s].label = NULL; tmpd[s].fields = NULL;} 4712 ierr = PetscFree(dm->probs);CHKERRQ(ierr); 4713 dm->Nds = NdsNew; 4714 dm->probs = tmpd; 4715 PetscFunctionReturn(0); 4716 } 4717 4718 /*@ 4719 DMGetNumDS - Get the number of discrete systems in the DM 4720 4721 Not collective 4722 4723 Input Parameter: 4724 . dm - The DM 4725 4726 Output Parameter: 4727 . Nds - The number of PetscDS objects 4728 4729 Level: intermediate 4730 4731 .seealso: DMGetDS(), DMGetCellDS() 4732 @*/ 4733 PetscErrorCode DMGetNumDS(DM dm, PetscInt *Nds) 4734 { 4735 PetscFunctionBegin; 4736 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4737 PetscValidPointer(Nds, 2); 4738 *Nds = dm->Nds; 4739 PetscFunctionReturn(0); 4740 } 4741 4742 /*@ 4743 DMClearDS - Remove all discrete systems from the DM 4744 4745 Logically collective on dm 4746 4747 Input Parameter: 4748 . dm - The DM 4749 4750 Level: intermediate 4751 4752 .seealso: DMGetNumDS(), DMGetDS(), DMSetField() 4753 @*/ 4754 PetscErrorCode DMClearDS(DM dm) 4755 { 4756 PetscInt s; 4757 PetscErrorCode ierr; 4758 4759 PetscFunctionBegin; 4760 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4761 for (s = 0; s < dm->Nds; ++s) { 4762 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr); 4763 ierr = DMLabelDestroy(&dm->probs[s].label);CHKERRQ(ierr); 4764 ierr = ISDestroy(&dm->probs[s].fields);CHKERRQ(ierr); 4765 } 4766 ierr = PetscFree(dm->probs);CHKERRQ(ierr); 4767 dm->probs = NULL; 4768 dm->Nds = 0; 4769 PetscFunctionReturn(0); 4770 } 4771 4772 /*@ 4773 DMGetDS - Get the default PetscDS 4774 4775 Not collective 4776 4777 Input Parameter: 4778 . dm - The DM 4779 4780 Output Parameter: 4781 . prob - The default PetscDS 4782 4783 Level: intermediate 4784 4785 .seealso: DMGetCellDS(), DMGetRegionDS() 4786 @*/ 4787 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 4788 { 4789 PetscErrorCode ierr; 4790 4791 PetscFunctionBeginHot; 4792 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4793 PetscValidPointer(prob, 2); 4794 if (dm->Nds <= 0) { 4795 PetscDS ds; 4796 4797 ierr = PetscDSCreate(PetscObjectComm((PetscObject) dm), &ds);CHKERRQ(ierr); 4798 ierr = DMSetRegionDS(dm, NULL, NULL, ds);CHKERRQ(ierr); 4799 ierr = PetscDSDestroy(&ds);CHKERRQ(ierr); 4800 } 4801 *prob = dm->probs[0].ds; 4802 PetscFunctionReturn(0); 4803 } 4804 4805 /*@ 4806 DMGetCellDS - Get the PetscDS defined on a given cell 4807 4808 Not collective 4809 4810 Input Parameters: 4811 + dm - The DM 4812 - point - Cell for the DS 4813 4814 Output Parameter: 4815 . prob - The PetscDS defined on the given cell 4816 4817 Level: developer 4818 4819 .seealso: DMGetDS(), DMSetRegionDS() 4820 @*/ 4821 PetscErrorCode DMGetCellDS(DM dm, PetscInt point, PetscDS *prob) 4822 { 4823 PetscDS probDef = NULL; 4824 PetscInt s; 4825 PetscErrorCode ierr; 4826 4827 PetscFunctionBeginHot; 4828 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4829 PetscValidPointer(prob, 3); 4830 *prob = NULL; 4831 for (s = 0; s < dm->Nds; ++s) { 4832 PetscInt val; 4833 4834 if (!dm->probs[s].label) {probDef = dm->probs[s].ds;} 4835 else { 4836 ierr = DMLabelGetValue(dm->probs[s].label, point, &val);CHKERRQ(ierr); 4837 if (val >= 0) {*prob = dm->probs[s].ds; break;} 4838 } 4839 } 4840 if (!*prob) *prob = probDef; 4841 PetscFunctionReturn(0); 4842 } 4843 4844 /*@ 4845 DMGetRegionDS - Get the PetscDS for a given mesh region, defined by a DMLabel 4846 4847 Not collective 4848 4849 Input Parameters: 4850 + dm - The DM 4851 - label - The DMLabel defining the mesh region, or NULL for the entire mesh 4852 4853 Output Parameters: 4854 + fields - The IS containing the DM field numbers for the fields in this DS, or NULL 4855 - prob - The PetscDS defined on the given region, or NULL 4856 4857 Note: If the label is missing, this function returns an error 4858 4859 Level: advanced 4860 4861 .seealso: DMGetRegionNumDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 4862 @*/ 4863 PetscErrorCode DMGetRegionDS(DM dm, DMLabel label, IS *fields, PetscDS *ds) 4864 { 4865 PetscInt Nds = dm->Nds, s; 4866 4867 PetscFunctionBegin; 4868 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4869 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 4870 if (fields) {PetscValidPointer(fields, 3); *fields = NULL;} 4871 if (ds) {PetscValidPointer(ds, 4); *ds = NULL;} 4872 for (s = 0; s < Nds; ++s) { 4873 if (dm->probs[s].label == label) { 4874 if (fields) *fields = dm->probs[s].fields; 4875 if (ds) *ds = dm->probs[s].ds; 4876 PetscFunctionReturn(0); 4877 } 4878 } 4879 PetscFunctionReturn(0); 4880 } 4881 4882 /*@ 4883 DMGetRegionNumDS - Get the PetscDS for a given mesh region, defined by the region number 4884 4885 Not collective 4886 4887 Input Parameters: 4888 + dm - The DM 4889 - num - The region number, in [0, Nds) 4890 4891 Output Parameters: 4892 + label - The region label, or NULL 4893 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL 4894 - prob - The PetscDS defined on the given region, or NULL 4895 4896 Level: advanced 4897 4898 .seealso: DMGetRegionDS(), DMSetRegionDS(), DMGetDS(), DMGetCellDS() 4899 @*/ 4900 PetscErrorCode DMGetRegionNumDS(DM dm, PetscInt num, DMLabel *label, IS *fields, PetscDS *ds) 4901 { 4902 PetscInt Nds; 4903 PetscErrorCode ierr; 4904 4905 PetscFunctionBegin; 4906 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4907 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 4908 if ((num < 0) || (num >= Nds)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Region number %D is not in [0, %D)", num, Nds); 4909 if (label) { 4910 PetscValidPointer(label, 3); 4911 *label = dm->probs[num].label; 4912 } 4913 if (fields) { 4914 PetscValidPointer(fields, 4); 4915 *fields = dm->probs[num].fields; 4916 } 4917 if (ds) { 4918 PetscValidPointer(ds, 5); 4919 *ds = dm->probs[num].ds; 4920 } 4921 PetscFunctionReturn(0); 4922 } 4923 4924 /*@ 4925 DMSetRegionDS - Set the PetscDS for a given mesh region, defined by a DMLabel 4926 4927 Collective on dm 4928 4929 Input Parameters: 4930 + dm - The DM 4931 . label - The DMLabel defining the mesh region, or NULL for the entire mesh 4932 . fields - The IS containing the DM field numbers for the fields in this DS, or NULL for all fields 4933 - prob - The PetscDS defined on the given cell 4934 4935 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. If DS is replaced, 4936 the fields argument is ignored. 4937 4938 Level: advanced 4939 4940 .seealso: DMGetRegionDS(), DMGetDS(), DMGetCellDS() 4941 @*/ 4942 PetscErrorCode DMSetRegionDS(DM dm, DMLabel label, IS fields, PetscDS ds) 4943 { 4944 PetscInt Nds = dm->Nds, s; 4945 PetscErrorCode ierr; 4946 4947 PetscFunctionBegin; 4948 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4949 if (label) PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 2); 4950 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 3); 4951 for (s = 0; s < Nds; ++s) { 4952 if (dm->probs[s].label == label) { 4953 ierr = PetscDSDestroy(&dm->probs[s].ds);CHKERRQ(ierr); 4954 dm->probs[s].ds = ds; 4955 PetscFunctionReturn(0); 4956 } 4957 } 4958 ierr = DMDSEnlarge_Static(dm, Nds+1);CHKERRQ(ierr); 4959 ierr = PetscObjectReference((PetscObject) label);CHKERRQ(ierr); 4960 ierr = PetscObjectReference((PetscObject) fields);CHKERRQ(ierr); 4961 ierr = PetscObjectReference((PetscObject) ds);CHKERRQ(ierr); 4962 if (!label) { 4963 /* Put the NULL label at the front, so it is returned as the default */ 4964 for (s = Nds-1; s >=0; --s) dm->probs[s+1] = dm->probs[s]; 4965 Nds = 0; 4966 } 4967 dm->probs[Nds].label = label; 4968 dm->probs[Nds].fields = fields; 4969 dm->probs[Nds].ds = ds; 4970 PetscFunctionReturn(0); 4971 } 4972 4973 /*@ 4974 DMCreateDS - Create the discrete systems for the DM based upon the fields added to the DM 4975 4976 Collective on dm 4977 4978 Input Parameter: 4979 . dm - The DM 4980 4981 Note: If the label has a DS defined, it will be replaced. Otherwise, it will be added to the DM. 4982 4983 Level: intermediate 4984 4985 .seealso: DMSetField, DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 4986 @*/ 4987 PetscErrorCode DMCreateDS(DM dm) 4988 { 4989 MPI_Comm comm; 4990 PetscDS prob, probh = NULL; 4991 PetscInt dimEmbed, Nf = dm->Nf, f, s, field = 0, fieldh = 0; 4992 PetscBool doSetup = PETSC_TRUE; 4993 PetscErrorCode ierr; 4994 4995 PetscFunctionBegin; 4996 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4997 if (!dm->fields) PetscFunctionReturn(0); 4998 /* Can only handle two label cases right now: 4999 1) NULL 5000 2) Hybrid cells 5001 */ 5002 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 5003 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 5004 /* Create default DS */ 5005 ierr = DMGetRegionDS(dm, NULL, NULL, &prob);CHKERRQ(ierr); 5006 if (!prob) { 5007 IS fields; 5008 PetscInt *fld, nf; 5009 5010 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) ++nf; 5011 ierr = PetscMalloc1(nf, &fld);CHKERRQ(ierr); 5012 for (f = 0, nf = 0; f < Nf; ++f) if (!dm->fields[f].label) fld[nf++] = f; 5013 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr); 5014 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr); 5015 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr); 5016 ierr = ISGeneralSetIndices(fields, nf, fld, PETSC_OWN_POINTER);CHKERRQ(ierr); 5017 5018 ierr = PetscDSCreate(comm, &prob);CHKERRQ(ierr); 5019 ierr = DMSetRegionDS(dm, NULL, fields, prob);CHKERRQ(ierr); 5020 ierr = PetscDSDestroy(&prob);CHKERRQ(ierr); 5021 ierr = ISDestroy(&fields);CHKERRQ(ierr); 5022 ierr = DMGetRegionDS(dm, NULL, NULL, &prob);CHKERRQ(ierr); 5023 } 5024 ierr = PetscDSSetCoordinateDimension(prob, dimEmbed);CHKERRQ(ierr); 5025 /* Optionally create hybrid DS */ 5026 for (f = 0; f < Nf; ++f) { 5027 DMLabel label = dm->fields[f].label; 5028 PetscInt lStart, lEnd; 5029 5030 if (label) { 5031 DM plex; 5032 IS fields; 5033 PetscInt *fld; 5034 PetscInt depth, pMax[4]; 5035 5036 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 5037 ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 5038 ierr = DMPlexGetHybridBounds(plex, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 5039 ierr = DMDestroy(&plex);CHKERRQ(ierr); 5040 5041 ierr = DMLabelGetBounds(label, &lStart, &lEnd);CHKERRQ(ierr); 5042 if (lStart < pMax[depth]) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only support labels over hybrid cells right now"); 5043 ierr = PetscDSCreate(comm, &probh);CHKERRQ(ierr); 5044 ierr = PetscMalloc1(1, &fld);CHKERRQ(ierr); 5045 fld[0] = f; 5046 ierr = ISCreate(PETSC_COMM_SELF, &fields);CHKERRQ(ierr); 5047 ierr = PetscObjectSetOptionsPrefix((PetscObject) fields, "dm_fields_");CHKERRQ(ierr); 5048 ierr = ISSetType(fields, ISGENERAL);CHKERRQ(ierr); 5049 ierr = ISGeneralSetIndices(fields, 1, fld, PETSC_OWN_POINTER);CHKERRQ(ierr); 5050 ierr = DMSetRegionDS(dm, label, fields, probh);CHKERRQ(ierr); 5051 ierr = ISDestroy(&fields);CHKERRQ(ierr); 5052 ierr = PetscDSSetHybrid(probh, PETSC_TRUE);CHKERRQ(ierr); 5053 ierr = PetscDSSetCoordinateDimension(probh, dimEmbed);CHKERRQ(ierr); 5054 break; 5055 } 5056 } 5057 /* Set fields in DSes */ 5058 for (f = 0; f < Nf; ++f) { 5059 DMLabel label = dm->fields[f].label; 5060 PetscObject disc = dm->fields[f].disc; 5061 5062 if (!label) { 5063 ierr = PetscDSSetDiscretization(prob, field++, disc);CHKERRQ(ierr); 5064 if (probh) { 5065 PetscFE subfe; 5066 5067 ierr = PetscFEGetHeightSubspace((PetscFE) disc, 1, &subfe);CHKERRQ(ierr); 5068 ierr = PetscDSSetDiscretization(probh, fieldh++, (PetscObject) subfe);CHKERRQ(ierr); 5069 } 5070 } else { 5071 ierr = PetscDSSetDiscretization(probh, fieldh++, disc);CHKERRQ(ierr); 5072 } 5073 /* We allow people to have placeholder fields and construct the Section by hand */ 5074 { 5075 PetscClassId id; 5076 5077 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 5078 if ((id != PETSCFE_CLASSID) && (id != PETSCFV_CLASSID)) doSetup = PETSC_FALSE; 5079 } 5080 } 5081 ierr = PetscDSDestroy(&probh);CHKERRQ(ierr); 5082 /* Setup DSes */ 5083 if (doSetup) { 5084 for (s = 0; s < dm->Nds; ++s) {ierr = PetscDSSetUp(dm->probs[s].ds);CHKERRQ(ierr);} 5085 } 5086 PetscFunctionReturn(0); 5087 } 5088 5089 /*@ 5090 DMCopyDS - Copy the discrete systems for the DM into another DM 5091 5092 Collective on dm 5093 5094 Input Parameter: 5095 . dm - The DM 5096 5097 Output Parameter: 5098 . newdm - The DM 5099 5100 Level: advanced 5101 5102 .seealso: DMCopyFields(), DMAddField(), DMGetDS(), DMGetCellDS(), DMGetRegionDS(), DMSetRegionDS() 5103 @*/ 5104 PetscErrorCode DMCopyDS(DM dm, DM newdm) 5105 { 5106 PetscInt Nds, s; 5107 PetscErrorCode ierr; 5108 5109 PetscFunctionBegin; 5110 if (dm == newdm) PetscFunctionReturn(0); 5111 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 5112 ierr = DMClearDS(newdm);CHKERRQ(ierr); 5113 for (s = 0; s < Nds; ++s) { 5114 DMLabel label; 5115 IS fields; 5116 PetscDS ds; 5117 5118 ierr = DMGetRegionNumDS(dm, s, &label, &fields, &ds);CHKERRQ(ierr); 5119 ierr = DMSetRegionDS(newdm, label, fields, ds);CHKERRQ(ierr); 5120 } 5121 PetscFunctionReturn(0); 5122 } 5123 5124 /*@ 5125 DMCopyDisc - Copy the fields and discrete systems for the DM into another DM 5126 5127 Collective on dm 5128 5129 Input Parameter: 5130 . dm - The DM 5131 5132 Output Parameter: 5133 . newdm - The DM 5134 5135 Level: advanced 5136 5137 .seealso: DMCopyFields(), DMCopyDS() 5138 @*/ 5139 PetscErrorCode DMCopyDisc(DM dm, DM newdm) 5140 { 5141 PetscErrorCode ierr; 5142 5143 PetscFunctionBegin; 5144 if (dm == newdm) PetscFunctionReturn(0); 5145 ierr = DMCopyFields(dm, newdm);CHKERRQ(ierr); 5146 ierr = DMCopyDS(dm, newdm);CHKERRQ(ierr); 5147 PetscFunctionReturn(0); 5148 } 5149 5150 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 5151 { 5152 DM dm_coord,dmc_coord; 5153 PetscErrorCode ierr; 5154 Vec coords,ccoords; 5155 Mat inject; 5156 PetscFunctionBegin; 5157 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5158 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 5159 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5160 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 5161 if (coords && !ccoords) { 5162 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 5163 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5164 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 5165 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 5166 ierr = MatDestroy(&inject);CHKERRQ(ierr); 5167 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 5168 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5169 } 5170 PetscFunctionReturn(0); 5171 } 5172 5173 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 5174 { 5175 DM dm_coord,subdm_coord; 5176 PetscErrorCode ierr; 5177 Vec coords,ccoords,clcoords; 5178 VecScatter *scat_i,*scat_g; 5179 PetscFunctionBegin; 5180 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 5181 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 5182 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 5183 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 5184 if (coords && !ccoords) { 5185 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 5186 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 5187 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 5188 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 5189 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 5190 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5191 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5192 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5193 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 5194 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 5195 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 5196 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 5197 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 5198 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 5199 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 5200 ierr = PetscFree(scat_i);CHKERRQ(ierr); 5201 ierr = PetscFree(scat_g);CHKERRQ(ierr); 5202 } 5203 PetscFunctionReturn(0); 5204 } 5205 5206 /*@ 5207 DMGetDimension - Return the topological dimension of the DM 5208 5209 Not collective 5210 5211 Input Parameter: 5212 . dm - The DM 5213 5214 Output Parameter: 5215 . dim - The topological dimension 5216 5217 Level: beginner 5218 5219 .seealso: DMSetDimension(), DMCreate() 5220 @*/ 5221 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 5222 { 5223 PetscFunctionBegin; 5224 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5225 PetscValidPointer(dim, 2); 5226 *dim = dm->dim; 5227 PetscFunctionReturn(0); 5228 } 5229 5230 /*@ 5231 DMSetDimension - Set the topological dimension of the DM 5232 5233 Collective on dm 5234 5235 Input Parameters: 5236 + dm - The DM 5237 - dim - The topological dimension 5238 5239 Level: beginner 5240 5241 .seealso: DMGetDimension(), DMCreate() 5242 @*/ 5243 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 5244 { 5245 PetscDS ds; 5246 PetscErrorCode ierr; 5247 5248 PetscFunctionBegin; 5249 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5250 PetscValidLogicalCollectiveInt(dm, dim, 2); 5251 dm->dim = dim; 5252 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5253 if (ds->dimEmbed < 0) {ierr = PetscDSSetCoordinateDimension(ds, dm->dim);CHKERRQ(ierr);} 5254 PetscFunctionReturn(0); 5255 } 5256 5257 /*@ 5258 DMGetDimPoints - Get the half-open interval for all points of a given dimension 5259 5260 Collective on dm 5261 5262 Input Parameters: 5263 + dm - the DM 5264 - dim - the dimension 5265 5266 Output Parameters: 5267 + pStart - The first point of the given dimension 5268 - pEnd - The first point following points of the given dimension 5269 5270 Note: 5271 The points are vertices in the Hasse diagram encoding the topology. This is explained in 5272 https://arxiv.org/abs/0908.4427. If no points exist of this dimension in the storage scheme, 5273 then the interval is empty. 5274 5275 Level: intermediate 5276 5277 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 5278 @*/ 5279 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5280 { 5281 PetscInt d; 5282 PetscErrorCode ierr; 5283 5284 PetscFunctionBegin; 5285 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5286 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 5287 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 5288 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 5289 PetscFunctionReturn(0); 5290 } 5291 5292 /*@ 5293 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 5294 5295 Collective on dm 5296 5297 Input Parameters: 5298 + dm - the DM 5299 - c - coordinate vector 5300 5301 Notes: 5302 The coordinates do include those for ghost points, which are in the local vector. 5303 5304 The vector c should be destroyed by the caller. 5305 5306 Level: intermediate 5307 5308 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5309 @*/ 5310 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 5311 { 5312 PetscErrorCode ierr; 5313 5314 PetscFunctionBegin; 5315 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5316 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5317 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5318 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5319 dm->coordinates = c; 5320 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5321 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5322 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 5323 PetscFunctionReturn(0); 5324 } 5325 5326 /*@ 5327 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 5328 5329 Not collective 5330 5331 Input Parameters: 5332 + dm - the DM 5333 - c - coordinate vector 5334 5335 Notes: 5336 The coordinates of ghost points can be set using DMSetCoordinates() 5337 followed by DMGetCoordinatesLocal(). This is intended to enable the 5338 setting of ghost coordinates outside of the domain. 5339 5340 The vector c should be destroyed by the caller. 5341 5342 Level: intermediate 5343 5344 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 5345 @*/ 5346 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 5347 { 5348 PetscErrorCode ierr; 5349 5350 PetscFunctionBegin; 5351 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5352 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 5353 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 5354 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 5355 5356 dm->coordinatesLocal = c; 5357 5358 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 5359 PetscFunctionReturn(0); 5360 } 5361 5362 /*@ 5363 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 5364 5365 Collective on dm 5366 5367 Input Parameter: 5368 . dm - the DM 5369 5370 Output Parameter: 5371 . c - global coordinate vector 5372 5373 Note: 5374 This is a borrowed reference, so the user should NOT destroy this vector 5375 5376 Each process has only the local coordinates (does NOT have the ghost coordinates). 5377 5378 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5379 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5380 5381 Level: intermediate 5382 5383 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 5384 @*/ 5385 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 5386 { 5387 PetscErrorCode ierr; 5388 5389 PetscFunctionBegin; 5390 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5391 PetscValidPointer(c,2); 5392 if (!dm->coordinates && dm->coordinatesLocal) { 5393 DM cdm = NULL; 5394 PetscBool localized; 5395 5396 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5397 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 5398 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5399 /* Block size is not correctly set by CreateGlobalVector() if coordinates are localized */ 5400 if (localized) { 5401 PetscInt cdim; 5402 5403 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5404 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5405 } 5406 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 5407 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5408 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 5409 } 5410 *c = dm->coordinates; 5411 PetscFunctionReturn(0); 5412 } 5413 5414 /*@ 5415 DMGetCoordinatesLocalSetUp - Prepares a local vector of coordinates, so that DMGetCoordinatesLocalNoncollective() can be used as non-collective afterwards. 5416 5417 Collective on dm 5418 5419 Input Parameter: 5420 . dm - the DM 5421 5422 Level: advanced 5423 5424 .seealso: DMGetCoordinatesLocalNoncollective() 5425 @*/ 5426 PetscErrorCode DMGetCoordinatesLocalSetUp(DM dm) 5427 { 5428 PetscErrorCode ierr; 5429 5430 PetscFunctionBegin; 5431 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5432 if (!dm->coordinatesLocal && dm->coordinates) { 5433 DM cdm = NULL; 5434 PetscBool localized; 5435 5436 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5437 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 5438 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 5439 /* Block size is not correctly set by CreateLocalVector() if coordinates are localized */ 5440 if (localized) { 5441 PetscInt cdim; 5442 5443 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 5444 ierr = VecSetBlockSize(dm->coordinates, cdim);CHKERRQ(ierr); 5445 } 5446 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 5447 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5448 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 5449 } 5450 PetscFunctionReturn(0); 5451 } 5452 5453 /*@ 5454 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 5455 5456 Collective on dm 5457 5458 Input Parameter: 5459 . dm - the DM 5460 5461 Output Parameter: 5462 . c - coordinate vector 5463 5464 Note: 5465 This is a borrowed reference, so the user should NOT destroy this vector 5466 5467 Each process has the local and ghost coordinates 5468 5469 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5470 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5471 5472 Level: intermediate 5473 5474 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM(), DMGetCoordinatesLocalNoncollective() 5475 @*/ 5476 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 5477 { 5478 PetscErrorCode ierr; 5479 5480 PetscFunctionBegin; 5481 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5482 PetscValidPointer(c,2); 5483 ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr); 5484 *c = dm->coordinatesLocal; 5485 PetscFunctionReturn(0); 5486 } 5487 5488 /*@ 5489 DMGetCoordinatesLocalNoncollective - Non-collective version of DMGetCoordinatesLocal(). Fails if global coordinates have been set and DMGetCoordinatesLocalSetUp() not called. 5490 5491 Not collective 5492 5493 Input Parameter: 5494 . dm - the DM 5495 5496 Output Parameter: 5497 . c - coordinate vector 5498 5499 Level: advanced 5500 5501 .seealso: DMGetCoordinatesLocalSetUp(), DMGetCoordinatesLocal(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 5502 @*/ 5503 PetscErrorCode DMGetCoordinatesLocalNoncollective(DM dm, Vec *c) 5504 { 5505 PetscFunctionBegin; 5506 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5507 PetscValidPointer(c,2); 5508 if (!dm->coordinatesLocal && dm->coordinates) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called"); 5509 *c = dm->coordinatesLocal; 5510 PetscFunctionReturn(0); 5511 } 5512 5513 /*@ 5514 DMGetCoordinatesLocalTuple - Gets a local vector with the coordinates of specified points and section describing its layout. 5515 5516 Not collective 5517 5518 Input Parameter: 5519 + dm - the DM 5520 - p - the IS of points whose coordinates will be returned 5521 5522 Output Parameter: 5523 + pCoordSection - the PetscSection describing the layout of pCoord, i.e. each point corresponds to one point in p, and DOFs correspond to coordinates 5524 - pCoord - the Vec with coordinates of points in p 5525 5526 Note: 5527 DMGetCoordinatesLocalSetUp() must be called first. This function employs DMGetCoordinatesLocalNoncollective() so it is not collective. 5528 5529 This creates a new vector, so the user SHOULD destroy this vector 5530 5531 Each process has the local and ghost coordinates 5532 5533 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 5534 and (x_0,y_0,z_0,x_1,y_1,z_1...) 5535 5536 Level: advanced 5537 5538 .seealso: DMSetCoordinatesLocal(), DMGetCoordinatesLocal(), DMGetCoordinatesLocalNoncollective(), DMGetCoordinatesLocalSetUp(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 5539 @*/ 5540 PetscErrorCode DMGetCoordinatesLocalTuple(DM dm, IS p, PetscSection *pCoordSection, Vec *pCoord) 5541 { 5542 PetscSection cs, newcs; 5543 Vec coords; 5544 const PetscScalar *arr; 5545 PetscScalar *newarr=NULL; 5546 PetscInt n; 5547 PetscErrorCode ierr; 5548 5549 PetscFunctionBegin; 5550 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5551 PetscValidHeaderSpecific(p, IS_CLASSID, 2); 5552 if (pCoordSection) PetscValidPointer(pCoordSection, 3); 5553 if (pCoord) PetscValidPointer(pCoord, 4); 5554 if (!dm->coordinatesLocal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DMGetCoordinatesLocalSetUp() has not been called or coordinates not set"); 5555 if (!dm->coordinateDM || !dm->coordinateDM->defaultSection) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM not supported"); 5556 cs = dm->coordinateDM->defaultSection; 5557 coords = dm->coordinatesLocal; 5558 ierr = VecGetArrayRead(coords, &arr);CHKERRQ(ierr); 5559 ierr = PetscSectionExtractDofsFromArray(cs, MPIU_SCALAR, arr, p, &newcs, pCoord ? ((void**)&newarr) : NULL);CHKERRQ(ierr); 5560 ierr = VecRestoreArrayRead(coords, &arr);CHKERRQ(ierr); 5561 if (pCoord) { 5562 ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr); 5563 /* set array in two steps to mimic PETSC_OWN_POINTER */ 5564 ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)p), 1, n, NULL, pCoord);CHKERRQ(ierr); 5565 ierr = VecReplaceArray(*pCoord, newarr);CHKERRQ(ierr); 5566 } else { 5567 ierr = PetscFree(newarr);CHKERRQ(ierr); 5568 } 5569 if (pCoordSection) {*pCoordSection = newcs;} 5570 else {ierr = PetscSectionDestroy(&newcs);CHKERRQ(ierr);} 5571 PetscFunctionReturn(0); 5572 } 5573 5574 PetscErrorCode DMGetCoordinateField(DM dm, DMField *field) 5575 { 5576 PetscErrorCode ierr; 5577 5578 PetscFunctionBegin; 5579 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5580 PetscValidPointer(field,2); 5581 if (!dm->coordinateField) { 5582 if (dm->ops->createcoordinatefield) { 5583 ierr = (*dm->ops->createcoordinatefield)(dm,&dm->coordinateField);CHKERRQ(ierr); 5584 } 5585 } 5586 *field = dm->coordinateField; 5587 PetscFunctionReturn(0); 5588 } 5589 5590 PetscErrorCode DMSetCoordinateField(DM dm, DMField field) 5591 { 5592 PetscErrorCode ierr; 5593 5594 PetscFunctionBegin; 5595 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5596 if (field) PetscValidHeaderSpecific(field,DMFIELD_CLASSID,2); 5597 ierr = PetscObjectReference((PetscObject)field);CHKERRQ(ierr); 5598 ierr = DMFieldDestroy(&dm->coordinateField);CHKERRQ(ierr); 5599 dm->coordinateField = field; 5600 PetscFunctionReturn(0); 5601 } 5602 5603 /*@ 5604 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 5605 5606 Collective on dm 5607 5608 Input Parameter: 5609 . dm - the DM 5610 5611 Output Parameter: 5612 . cdm - coordinate DM 5613 5614 Level: intermediate 5615 5616 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 5617 @*/ 5618 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 5619 { 5620 PetscErrorCode ierr; 5621 5622 PetscFunctionBegin; 5623 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5624 PetscValidPointer(cdm,2); 5625 if (!dm->coordinateDM) { 5626 DM cdm; 5627 5628 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 5629 ierr = (*dm->ops->createcoordinatedm)(dm, &cdm);CHKERRQ(ierr); 5630 /* Just in case the DM sets the coordinate DM when creating it (DMP4est can do this, because it may not setup 5631 * until the call to CreateCoordinateDM) */ 5632 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 5633 dm->coordinateDM = cdm; 5634 } 5635 *cdm = dm->coordinateDM; 5636 PetscFunctionReturn(0); 5637 } 5638 5639 /*@ 5640 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 5641 5642 Logically Collective on dm 5643 5644 Input Parameters: 5645 + dm - the DM 5646 - cdm - coordinate DM 5647 5648 Level: intermediate 5649 5650 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 5651 @*/ 5652 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 5653 { 5654 PetscErrorCode ierr; 5655 5656 PetscFunctionBegin; 5657 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5658 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 5659 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5660 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 5661 dm->coordinateDM = cdm; 5662 PetscFunctionReturn(0); 5663 } 5664 5665 /*@ 5666 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 5667 5668 Not Collective 5669 5670 Input Parameter: 5671 . dm - The DM object 5672 5673 Output Parameter: 5674 . dim - The embedding dimension 5675 5676 Level: intermediate 5677 5678 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetSection(), DMSetSection() 5679 @*/ 5680 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 5681 { 5682 PetscFunctionBegin; 5683 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5684 PetscValidPointer(dim, 2); 5685 if (dm->dimEmbed == PETSC_DEFAULT) { 5686 dm->dimEmbed = dm->dim; 5687 } 5688 *dim = dm->dimEmbed; 5689 PetscFunctionReturn(0); 5690 } 5691 5692 /*@ 5693 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 5694 5695 Not Collective 5696 5697 Input Parameters: 5698 + dm - The DM object 5699 - dim - The embedding dimension 5700 5701 Level: intermediate 5702 5703 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetSection(), DMSetSection() 5704 @*/ 5705 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 5706 { 5707 PetscDS ds; 5708 PetscErrorCode ierr; 5709 5710 PetscFunctionBegin; 5711 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5712 dm->dimEmbed = dim; 5713 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 5714 ierr = PetscDSSetCoordinateDimension(ds, dim);CHKERRQ(ierr); 5715 PetscFunctionReturn(0); 5716 } 5717 5718 /*@ 5719 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 5720 5721 Collective on dm 5722 5723 Input Parameter: 5724 . dm - The DM object 5725 5726 Output Parameter: 5727 . section - The PetscSection object 5728 5729 Level: intermediate 5730 5731 .seealso: DMGetCoordinateDM(), DMGetSection(), DMSetSection() 5732 @*/ 5733 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 5734 { 5735 DM cdm; 5736 PetscErrorCode ierr; 5737 5738 PetscFunctionBegin; 5739 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5740 PetscValidPointer(section, 2); 5741 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5742 ierr = DMGetSection(cdm, section);CHKERRQ(ierr); 5743 PetscFunctionReturn(0); 5744 } 5745 5746 /*@ 5747 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 5748 5749 Not Collective 5750 5751 Input Parameters: 5752 + dm - The DM object 5753 . dim - The embedding dimension, or PETSC_DETERMINE 5754 - section - The PetscSection object 5755 5756 Level: intermediate 5757 5758 .seealso: DMGetCoordinateSection(), DMGetSection(), DMSetSection() 5759 @*/ 5760 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 5761 { 5762 DM cdm; 5763 PetscErrorCode ierr; 5764 5765 PetscFunctionBegin; 5766 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5767 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 5768 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 5769 ierr = DMSetSection(cdm, section);CHKERRQ(ierr); 5770 if (dim == PETSC_DETERMINE) { 5771 PetscInt d = PETSC_DEFAULT; 5772 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 5773 5774 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 5775 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5776 pStart = PetscMax(vStart, pStart); 5777 pEnd = PetscMin(vEnd, pEnd); 5778 for (v = pStart; v < pEnd; ++v) { 5779 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 5780 if (dd) {d = dd; break;} 5781 } 5782 if (d >= 0) {ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr);} 5783 } 5784 PetscFunctionReturn(0); 5785 } 5786 5787 /*@C 5788 DMGetPeriodicity - Get the description of mesh periodicity 5789 5790 Input Parameters: 5791 . dm - The DM object 5792 5793 Output Parameters: 5794 + per - Whether the DM is periodic or not 5795 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 5796 . L - If we assume the mesh is a torus, this is the length of each coordinate 5797 - bd - This describes the type of periodicity in each topological dimension 5798 5799 Level: developer 5800 5801 .seealso: DMGetPeriodicity() 5802 @*/ 5803 PetscErrorCode DMGetPeriodicity(DM dm, PetscBool *per, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 5804 { 5805 PetscFunctionBegin; 5806 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5807 if (per) *per = dm->periodic; 5808 if (L) *L = dm->L; 5809 if (maxCell) *maxCell = dm->maxCell; 5810 if (bd) *bd = dm->bdtype; 5811 PetscFunctionReturn(0); 5812 } 5813 5814 /*@C 5815 DMSetPeriodicity - Set the description of mesh periodicity 5816 5817 Input Parameters: 5818 + dm - The DM object 5819 . per - Whether the DM is periodic or not. If maxCell is not provided, coordinates need to be localized 5820 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 5821 . L - If we assume the mesh is a torus, this is the length of each coordinate 5822 - bd - This describes the type of periodicity in each topological dimension 5823 5824 Level: developer 5825 5826 .seealso: DMGetPeriodicity() 5827 @*/ 5828 PetscErrorCode DMSetPeriodicity(DM dm, PetscBool per, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 5829 { 5830 PetscInt dim, d; 5831 PetscErrorCode ierr; 5832 5833 PetscFunctionBegin; 5834 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5835 PetscValidLogicalCollectiveBool(dm,per,2); 5836 if (maxCell) { 5837 PetscValidPointer(maxCell,3); 5838 PetscValidPointer(L,4); 5839 PetscValidPointer(bd,5); 5840 } 5841 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 5842 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5843 if (maxCell) { 5844 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 5845 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 5846 } 5847 dm->periodic = per; 5848 PetscFunctionReturn(0); 5849 } 5850 5851 /*@ 5852 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. 5853 5854 Input Parameters: 5855 + dm - The DM 5856 . in - The input coordinate point (dim numbers) 5857 - endpoint - Include the endpoint L_i 5858 5859 Output Parameter: 5860 . out - The localized coordinate point 5861 5862 Level: developer 5863 5864 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 5865 @*/ 5866 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscBool endpoint, PetscScalar out[]) 5867 { 5868 PetscInt dim, d; 5869 PetscErrorCode ierr; 5870 5871 PetscFunctionBegin; 5872 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 5873 if (!dm->maxCell) { 5874 for (d = 0; d < dim; ++d) out[d] = in[d]; 5875 } else { 5876 if (endpoint) { 5877 for (d = 0; d < dim; ++d) { 5878 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)) { 5879 out[d] = in[d] - dm->L[d]*(PetscFloorReal(PetscRealPart(in[d])/dm->L[d]) - 1); 5880 } else { 5881 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 5882 } 5883 } 5884 } else { 5885 for (d = 0; d < dim; ++d) { 5886 out[d] = in[d] - dm->L[d]*PetscFloorReal(PetscRealPart(in[d])/dm->L[d]); 5887 } 5888 } 5889 } 5890 PetscFunctionReturn(0); 5891 } 5892 5893 /* 5894 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. 5895 5896 Input Parameters: 5897 + dm - The DM 5898 . dim - The spatial dimension 5899 . anchor - The anchor point, the input point can be no more than maxCell away from it 5900 - in - The input coordinate point (dim numbers) 5901 5902 Output Parameter: 5903 . out - The localized coordinate point 5904 5905 Level: developer 5906 5907 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 5908 5909 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 5910 */ 5911 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 5912 { 5913 PetscInt d; 5914 5915 PetscFunctionBegin; 5916 if (!dm->maxCell) { 5917 for (d = 0; d < dim; ++d) out[d] = in[d]; 5918 } else { 5919 for (d = 0; d < dim; ++d) { 5920 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 5921 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5922 } else { 5923 out[d] = in[d]; 5924 } 5925 } 5926 } 5927 PetscFunctionReturn(0); 5928 } 5929 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 5930 { 5931 PetscInt d; 5932 5933 PetscFunctionBegin; 5934 if (!dm->maxCell) { 5935 for (d = 0; d < dim; ++d) out[d] = in[d]; 5936 } else { 5937 for (d = 0; d < dim; ++d) { 5938 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d])) { 5939 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5940 } else { 5941 out[d] = in[d]; 5942 } 5943 } 5944 } 5945 PetscFunctionReturn(0); 5946 } 5947 5948 /* 5949 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. 5950 5951 Input Parameters: 5952 + dm - The DM 5953 . dim - The spatial dimension 5954 . anchor - The anchor point, the input point can be no more than maxCell away from it 5955 . in - The input coordinate delta (dim numbers) 5956 - out - The input coordinate point (dim numbers) 5957 5958 Output Parameter: 5959 . out - The localized coordinate in + out 5960 5961 Level: developer 5962 5963 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 5964 5965 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 5966 */ 5967 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 5968 { 5969 PetscInt d; 5970 5971 PetscFunctionBegin; 5972 if (!dm->maxCell) { 5973 for (d = 0; d < dim; ++d) out[d] += in[d]; 5974 } else { 5975 for (d = 0; d < dim; ++d) { 5976 if ((dm->bdtype[d] != DM_BOUNDARY_NONE) && (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d])) { 5977 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 5978 } else { 5979 out[d] += in[d]; 5980 } 5981 } 5982 } 5983 PetscFunctionReturn(0); 5984 } 5985 5986 /*@ 5987 DMGetCoordinatesLocalizedLocal - Check if the DM coordinates have been localized for cells on this process 5988 5989 Not collective 5990 5991 Input Parameter: 5992 . dm - The DM 5993 5994 Output Parameter: 5995 areLocalized - True if localized 5996 5997 Level: developer 5998 5999 .seealso: DMLocalizeCoordinates(), DMGetCoordinatesLocalized(), DMSetPeriodicity() 6000 @*/ 6001 PetscErrorCode DMGetCoordinatesLocalizedLocal(DM dm,PetscBool *areLocalized) 6002 { 6003 DM cdm; 6004 PetscSection coordSection; 6005 PetscInt cStart, cEnd, sStart, sEnd, c, dof; 6006 PetscBool isPlex, alreadyLocalized; 6007 PetscErrorCode ierr; 6008 6009 PetscFunctionBegin; 6010 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6011 PetscValidPointer(areLocalized, 2); 6012 *areLocalized = PETSC_FALSE; 6013 6014 /* We need some generic way of refering to cells/vertices */ 6015 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6016 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isPlex);CHKERRQ(ierr); 6017 if (!isPlex) PetscFunctionReturn(0); 6018 6019 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6020 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6021 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 6022 alreadyLocalized = PETSC_FALSE; 6023 for (c = cStart; c < cEnd; ++c) { 6024 if (c < sStart || c >= sEnd) continue; 6025 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 6026 if (dof) { alreadyLocalized = PETSC_TRUE; break; } 6027 } 6028 *areLocalized = alreadyLocalized; 6029 PetscFunctionReturn(0); 6030 } 6031 6032 /*@ 6033 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 6034 6035 Collective on dm 6036 6037 Input Parameter: 6038 . dm - The DM 6039 6040 Output Parameter: 6041 areLocalized - True if localized 6042 6043 Level: developer 6044 6045 .seealso: DMLocalizeCoordinates(), DMSetPeriodicity(), DMGetCoordinatesLocalizedLocal() 6046 @*/ 6047 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 6048 { 6049 PetscBool localized; 6050 PetscErrorCode ierr; 6051 6052 PetscFunctionBegin; 6053 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6054 PetscValidPointer(areLocalized, 2); 6055 ierr = DMGetCoordinatesLocalizedLocal(dm,&localized);CHKERRQ(ierr); 6056 ierr = MPIU_Allreduce(&localized,areLocalized,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6057 PetscFunctionReturn(0); 6058 } 6059 6060 /*@ 6061 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for cells having periodic faces 6062 6063 Collective on dm 6064 6065 Input Parameter: 6066 . dm - The DM 6067 6068 Level: developer 6069 6070 .seealso: DMSetPeriodicity(), DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 6071 @*/ 6072 PetscErrorCode DMLocalizeCoordinates(DM dm) 6073 { 6074 DM cdm; 6075 PetscSection coordSection, cSection; 6076 Vec coordinates, cVec; 6077 PetscScalar *coords, *coords2, *anchor, *localized; 6078 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 6079 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 6080 PetscInt maxHeight = 0, h; 6081 PetscInt *pStart = NULL, *pEnd = NULL; 6082 PetscErrorCode ierr; 6083 6084 PetscFunctionBegin; 6085 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6086 if (!dm->periodic) PetscFunctionReturn(0); 6087 ierr = DMGetCoordinatesLocalized(dm, &alreadyLocalized);CHKERRQ(ierr); 6088 if (alreadyLocalized) PetscFunctionReturn(0); 6089 6090 /* We need some generic way of refering to cells/vertices */ 6091 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 6092 { 6093 PetscBool isplex; 6094 6095 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 6096 if (isplex) { 6097 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6098 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 6099 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6100 pEnd = &pStart[maxHeight + 1]; 6101 newStart = vStart; 6102 newEnd = vEnd; 6103 for (h = 0; h <= maxHeight; h++) { 6104 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 6105 newStart = PetscMin(newStart,pStart[h]); 6106 newEnd = PetscMax(newEnd,pEnd[h]); 6107 } 6108 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 6109 } 6110 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 6111 if (!coordinates) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing local coordinates vector"); 6112 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 6113 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 6114 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 6115 6116 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 6117 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 6118 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 6119 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 6120 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 6121 6122 ierr = DMGetWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6123 localized = &anchor[bs]; 6124 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 6125 for (h = 0; h <= maxHeight; h++) { 6126 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6127 6128 for (c = cStart; c < cEnd; ++c) { 6129 PetscScalar *cellCoords = NULL; 6130 PetscInt b; 6131 6132 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 6133 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6134 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6135 for (d = 0; d < dof/bs; ++d) { 6136 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 6137 for (b = 0; b < bs; b++) { 6138 if (cellCoords[d*bs + b] != localized[b]) break; 6139 } 6140 if (b < bs) break; 6141 } 6142 if (d < dof/bs) { 6143 if (c >= sStart && c < sEnd) { 6144 PetscInt cdof; 6145 6146 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 6147 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 6148 } 6149 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 6150 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 6151 } 6152 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6153 } 6154 } 6155 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 6156 if (alreadyLocalizedGlobal) { 6157 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6158 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6159 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6160 PetscFunctionReturn(0); 6161 } 6162 for (v = vStart; v < vEnd; ++v) { 6163 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6164 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 6165 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 6166 } 6167 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 6168 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 6169 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 6170 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 6171 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 6172 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 6173 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 6174 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6175 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 6176 for (v = vStart; v < vEnd; ++v) { 6177 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 6178 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 6179 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 6180 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 6181 } 6182 for (h = 0; h <= maxHeight; h++) { 6183 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 6184 6185 for (c = cStart; c < cEnd; ++c) { 6186 PetscScalar *cellCoords = NULL; 6187 PetscInt b, cdof; 6188 6189 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 6190 if (!cdof) continue; 6191 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6192 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 6193 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 6194 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 6195 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 6196 } 6197 } 6198 ierr = DMRestoreWorkArray(dm, 2 * bs, MPIU_SCALAR, &anchor);CHKERRQ(ierr); 6199 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),MPIU_INT,&pStart);CHKERRQ(ierr); 6200 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 6201 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 6202 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 6203 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 6204 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 6205 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 6206 PetscFunctionReturn(0); 6207 } 6208 6209 /*@ 6210 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 6211 6212 Collective on v (see explanation below) 6213 6214 Input Parameters: 6215 + dm - The DM 6216 . v - The Vec of points 6217 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 6218 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 6219 6220 Output Parameter: 6221 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 6222 - cells - The PetscSF containing the ranks and local indices of the containing points. 6223 6224 6225 Level: developer 6226 6227 Notes: 6228 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 6229 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 6230 6231 If *cellSF is NULL on input, a PetscSF will be created. 6232 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 6233 6234 An array that maps each point to its containing cell can be obtained with 6235 6236 $ const PetscSFNode *cells; 6237 $ PetscInt nFound; 6238 $ const PetscInt *found; 6239 $ 6240 $ PetscSFGetGraph(cellSF,NULL,&nFound,&found,&cells); 6241 6242 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 6243 the index of the cell in its rank's local numbering. 6244 6245 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 6246 @*/ 6247 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 6248 { 6249 PetscErrorCode ierr; 6250 6251 PetscFunctionBegin; 6252 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6253 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 6254 PetscValidPointer(cellSF,4); 6255 if (*cellSF) { 6256 PetscMPIInt result; 6257 6258 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 6259 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)*cellSF),&result);CHKERRQ(ierr); 6260 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 6261 } else { 6262 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 6263 } 6264 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6265 if (dm->ops->locatepoints) { 6266 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 6267 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 6268 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 6269 PetscFunctionReturn(0); 6270 } 6271 6272 /*@ 6273 DMGetOutputDM - Retrieve the DM associated with the layout for output 6274 6275 Collective on dm 6276 6277 Input Parameter: 6278 . dm - The original DM 6279 6280 Output Parameter: 6281 . odm - The DM which provides the layout for output 6282 6283 Level: intermediate 6284 6285 .seealso: VecView(), DMGetGlobalSection() 6286 @*/ 6287 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 6288 { 6289 PetscSection section; 6290 PetscBool hasConstraints, ghasConstraints; 6291 PetscErrorCode ierr; 6292 6293 PetscFunctionBegin; 6294 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6295 PetscValidPointer(odm,2); 6296 ierr = DMGetSection(dm, §ion);CHKERRQ(ierr); 6297 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 6298 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 6299 if (!ghasConstraints) { 6300 *odm = dm; 6301 PetscFunctionReturn(0); 6302 } 6303 if (!dm->dmBC) { 6304 PetscSection newSection, gsection; 6305 PetscSF sf; 6306 6307 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 6308 ierr = DMCopyDisc(dm, dm->dmBC);CHKERRQ(ierr); 6309 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 6310 ierr = DMSetSection(dm->dmBC, newSection);CHKERRQ(ierr); 6311 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 6312 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 6313 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 6314 ierr = DMSetGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 6315 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 6316 } 6317 *odm = dm->dmBC; 6318 PetscFunctionReturn(0); 6319 } 6320 6321 /*@ 6322 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 6323 6324 Input Parameter: 6325 . dm - The original DM 6326 6327 Output Parameters: 6328 + num - The output sequence number 6329 - val - The output sequence value 6330 6331 Level: intermediate 6332 6333 Note: This is intended for output that should appear in sequence, for instance 6334 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6335 6336 .seealso: VecView() 6337 @*/ 6338 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 6339 { 6340 PetscFunctionBegin; 6341 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6342 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 6343 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 6344 PetscFunctionReturn(0); 6345 } 6346 6347 /*@ 6348 DMSetOutputSequenceNumber - Set the sequence number/value for output 6349 6350 Input Parameters: 6351 + dm - The original DM 6352 . num - The output sequence number 6353 - val - The output sequence value 6354 6355 Level: intermediate 6356 6357 Note: This is intended for output that should appear in sequence, for instance 6358 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6359 6360 .seealso: VecView() 6361 @*/ 6362 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 6363 { 6364 PetscFunctionBegin; 6365 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6366 dm->outputSequenceNum = num; 6367 dm->outputSequenceVal = val; 6368 PetscFunctionReturn(0); 6369 } 6370 6371 /*@C 6372 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 6373 6374 Input Parameters: 6375 + dm - The original DM 6376 . name - The sequence name 6377 - num - The output sequence number 6378 6379 Output Parameter: 6380 . val - The output sequence value 6381 6382 Level: intermediate 6383 6384 Note: This is intended for output that should appear in sequence, for instance 6385 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 6386 6387 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 6388 @*/ 6389 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 6390 { 6391 PetscBool ishdf5; 6392 PetscErrorCode ierr; 6393 6394 PetscFunctionBegin; 6395 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6396 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 6397 PetscValidPointer(val,4); 6398 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 6399 if (ishdf5) { 6400 #if defined(PETSC_HAVE_HDF5) 6401 PetscScalar value; 6402 6403 ierr = DMSequenceLoad_HDF5_Internal(dm, name, num, &value, viewer);CHKERRQ(ierr); 6404 *val = PetscRealPart(value); 6405 #endif 6406 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 6407 PetscFunctionReturn(0); 6408 } 6409 6410 /*@ 6411 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 6412 6413 Not collective 6414 6415 Input Parameter: 6416 . dm - The DM 6417 6418 Output Parameter: 6419 . useNatural - The flag to build the mapping to a natural order during distribution 6420 6421 Level: beginner 6422 6423 .seealso: DMSetUseNatural(), DMCreate() 6424 @*/ 6425 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 6426 { 6427 PetscFunctionBegin; 6428 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6429 PetscValidPointer(useNatural, 2); 6430 *useNatural = dm->useNatural; 6431 PetscFunctionReturn(0); 6432 } 6433 6434 /*@ 6435 DMSetUseNatural - Set the flag for creating a mapping to the natural order after distribution 6436 6437 Collective on dm 6438 6439 Input Parameters: 6440 + dm - The DM 6441 - useNatural - The flag to build the mapping to a natural order during distribution 6442 6443 Note: This also causes the map to be build after DMCreateSubDM() and DMCreateSuperDM() 6444 6445 Level: beginner 6446 6447 .seealso: DMGetUseNatural(), DMCreate(), DMPlexDistribute(), DMCreateSubDM(), DMCreateSuperDM() 6448 @*/ 6449 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 6450 { 6451 PetscFunctionBegin; 6452 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6453 PetscValidLogicalCollectiveBool(dm, useNatural, 2); 6454 dm->useNatural = useNatural; 6455 PetscFunctionReturn(0); 6456 } 6457 6458 6459 /*@C 6460 DMCreateLabel - Create a label of the given name if it does not already exist 6461 6462 Not Collective 6463 6464 Input Parameters: 6465 + dm - The DM object 6466 - name - The label name 6467 6468 Level: intermediate 6469 6470 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6471 @*/ 6472 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 6473 { 6474 DMLabelLink next = dm->labels->next; 6475 PetscBool flg = PETSC_FALSE; 6476 const char *lname; 6477 PetscErrorCode ierr; 6478 6479 PetscFunctionBegin; 6480 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6481 PetscValidCharPointer(name, 2); 6482 while (next) { 6483 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6484 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 6485 if (flg) break; 6486 next = next->next; 6487 } 6488 if (!flg) { 6489 DMLabelLink tmpLabel; 6490 6491 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 6492 ierr = DMLabelCreate(PETSC_COMM_SELF, name, &tmpLabel->label);CHKERRQ(ierr); 6493 tmpLabel->output = PETSC_TRUE; 6494 tmpLabel->next = dm->labels->next; 6495 dm->labels->next = tmpLabel; 6496 } 6497 PetscFunctionReturn(0); 6498 } 6499 6500 /*@C 6501 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 6502 6503 Not Collective 6504 6505 Input Parameters: 6506 + dm - The DM object 6507 . name - The label name 6508 - point - The mesh point 6509 6510 Output Parameter: 6511 . value - The label value for this point, or -1 if the point is not in the label 6512 6513 Level: beginner 6514 6515 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 6516 @*/ 6517 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 6518 { 6519 DMLabel label; 6520 PetscErrorCode ierr; 6521 6522 PetscFunctionBegin; 6523 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6524 PetscValidCharPointer(name, 2); 6525 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6526 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name); 6527 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 6528 PetscFunctionReturn(0); 6529 } 6530 6531 /*@C 6532 DMSetLabelValue - Add a point to a Sieve Label with given value 6533 6534 Not Collective 6535 6536 Input Parameters: 6537 + dm - The DM object 6538 . name - The label name 6539 . point - The mesh point 6540 - value - The label value for this point 6541 6542 Output Parameter: 6543 6544 Level: beginner 6545 6546 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 6547 @*/ 6548 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6549 { 6550 DMLabel label; 6551 PetscErrorCode ierr; 6552 6553 PetscFunctionBegin; 6554 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6555 PetscValidCharPointer(name, 2); 6556 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6557 if (!label) { 6558 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 6559 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6560 } 6561 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 6562 PetscFunctionReturn(0); 6563 } 6564 6565 /*@C 6566 DMClearLabelValue - Remove a point from a Sieve Label with given value 6567 6568 Not Collective 6569 6570 Input Parameters: 6571 + dm - The DM object 6572 . name - The label name 6573 . point - The mesh point 6574 - value - The label value for this point 6575 6576 Output Parameter: 6577 6578 Level: beginner 6579 6580 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 6581 @*/ 6582 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 6583 { 6584 DMLabel label; 6585 PetscErrorCode ierr; 6586 6587 PetscFunctionBegin; 6588 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6589 PetscValidCharPointer(name, 2); 6590 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6591 if (!label) PetscFunctionReturn(0); 6592 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 6593 PetscFunctionReturn(0); 6594 } 6595 6596 /*@C 6597 DMGetLabelSize - Get the number of different integer ids in a Label 6598 6599 Not Collective 6600 6601 Input Parameters: 6602 + dm - The DM object 6603 - name - The label name 6604 6605 Output Parameter: 6606 . size - The number of different integer ids, or 0 if the label does not exist 6607 6608 Level: beginner 6609 6610 .seealso: DMLabelGetNumValues(), DMSetLabelValue() 6611 @*/ 6612 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 6613 { 6614 DMLabel label; 6615 PetscErrorCode ierr; 6616 6617 PetscFunctionBegin; 6618 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6619 PetscValidCharPointer(name, 2); 6620 PetscValidPointer(size, 3); 6621 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6622 *size = 0; 6623 if (!label) PetscFunctionReturn(0); 6624 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 6625 PetscFunctionReturn(0); 6626 } 6627 6628 /*@C 6629 DMGetLabelIdIS - Get the integer ids in a label 6630 6631 Not Collective 6632 6633 Input Parameters: 6634 + mesh - The DM object 6635 - name - The label name 6636 6637 Output Parameter: 6638 . ids - The integer ids, or NULL if the label does not exist 6639 6640 Level: beginner 6641 6642 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 6643 @*/ 6644 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 6645 { 6646 DMLabel label; 6647 PetscErrorCode ierr; 6648 6649 PetscFunctionBegin; 6650 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6651 PetscValidCharPointer(name, 2); 6652 PetscValidPointer(ids, 3); 6653 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6654 *ids = NULL; 6655 if (label) { 6656 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 6657 } else { 6658 /* returning an empty IS */ 6659 ierr = ISCreateGeneral(PETSC_COMM_SELF,0,NULL,PETSC_USE_POINTER,ids);CHKERRQ(ierr); 6660 } 6661 PetscFunctionReturn(0); 6662 } 6663 6664 /*@C 6665 DMGetStratumSize - Get the number of points in a label stratum 6666 6667 Not Collective 6668 6669 Input Parameters: 6670 + dm - The DM object 6671 . name - The label name 6672 - value - The stratum value 6673 6674 Output Parameter: 6675 . size - The stratum size 6676 6677 Level: beginner 6678 6679 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 6680 @*/ 6681 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 6682 { 6683 DMLabel label; 6684 PetscErrorCode ierr; 6685 6686 PetscFunctionBegin; 6687 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6688 PetscValidCharPointer(name, 2); 6689 PetscValidPointer(size, 4); 6690 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6691 *size = 0; 6692 if (!label) PetscFunctionReturn(0); 6693 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 6694 PetscFunctionReturn(0); 6695 } 6696 6697 /*@C 6698 DMGetStratumIS - Get the points in a label stratum 6699 6700 Not Collective 6701 6702 Input Parameters: 6703 + dm - The DM object 6704 . name - The label name 6705 - value - The stratum value 6706 6707 Output Parameter: 6708 . points - The stratum points, or NULL if the label does not exist or does not have that value 6709 6710 Level: beginner 6711 6712 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 6713 @*/ 6714 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 6715 { 6716 DMLabel label; 6717 PetscErrorCode ierr; 6718 6719 PetscFunctionBegin; 6720 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6721 PetscValidCharPointer(name, 2); 6722 PetscValidPointer(points, 4); 6723 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6724 *points = NULL; 6725 if (!label) PetscFunctionReturn(0); 6726 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 6727 PetscFunctionReturn(0); 6728 } 6729 6730 /*@C 6731 DMSetStratumIS - Set the points in a label stratum 6732 6733 Not Collective 6734 6735 Input Parameters: 6736 + dm - The DM object 6737 . name - The label name 6738 . value - The stratum value 6739 - points - The stratum points 6740 6741 Level: beginner 6742 6743 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 6744 @*/ 6745 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 6746 { 6747 DMLabel label; 6748 PetscErrorCode ierr; 6749 6750 PetscFunctionBegin; 6751 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6752 PetscValidCharPointer(name, 2); 6753 PetscValidPointer(points, 4); 6754 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6755 if (!label) PetscFunctionReturn(0); 6756 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 6757 PetscFunctionReturn(0); 6758 } 6759 6760 /*@C 6761 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 6762 6763 Not Collective 6764 6765 Input Parameters: 6766 + dm - The DM object 6767 . name - The label name 6768 - value - The label value for this point 6769 6770 Output Parameter: 6771 6772 Level: beginner 6773 6774 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 6775 @*/ 6776 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 6777 { 6778 DMLabel label; 6779 PetscErrorCode ierr; 6780 6781 PetscFunctionBegin; 6782 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6783 PetscValidCharPointer(name, 2); 6784 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 6785 if (!label) PetscFunctionReturn(0); 6786 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 6787 PetscFunctionReturn(0); 6788 } 6789 6790 /*@ 6791 DMGetNumLabels - Return the number of labels defined by the mesh 6792 6793 Not Collective 6794 6795 Input Parameter: 6796 . dm - The DM object 6797 6798 Output Parameter: 6799 . numLabels - the number of Labels 6800 6801 Level: intermediate 6802 6803 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6804 @*/ 6805 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 6806 { 6807 DMLabelLink next = dm->labels->next; 6808 PetscInt n = 0; 6809 6810 PetscFunctionBegin; 6811 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6812 PetscValidPointer(numLabels, 2); 6813 while (next) {++n; next = next->next;} 6814 *numLabels = n; 6815 PetscFunctionReturn(0); 6816 } 6817 6818 /*@C 6819 DMGetLabelName - Return the name of nth label 6820 6821 Not Collective 6822 6823 Input Parameters: 6824 + dm - The DM object 6825 - n - the label number 6826 6827 Output Parameter: 6828 . name - the label name 6829 6830 Level: intermediate 6831 6832 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6833 @*/ 6834 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 6835 { 6836 DMLabelLink next = dm->labels->next; 6837 PetscInt l = 0; 6838 PetscErrorCode ierr; 6839 6840 PetscFunctionBegin; 6841 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6842 PetscValidPointer(name, 3); 6843 while (next) { 6844 if (l == n) { 6845 ierr = PetscObjectGetName((PetscObject) next->label, name);CHKERRQ(ierr); 6846 PetscFunctionReturn(0); 6847 } 6848 ++l; 6849 next = next->next; 6850 } 6851 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 6852 } 6853 6854 /*@C 6855 DMHasLabel - Determine whether the mesh has a label of a given name 6856 6857 Not Collective 6858 6859 Input Parameters: 6860 + dm - The DM object 6861 - name - The label name 6862 6863 Output Parameter: 6864 . hasLabel - PETSC_TRUE if the label is present 6865 6866 Level: intermediate 6867 6868 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6869 @*/ 6870 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 6871 { 6872 DMLabelLink next = dm->labels->next; 6873 const char *lname; 6874 PetscErrorCode ierr; 6875 6876 PetscFunctionBegin; 6877 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6878 PetscValidCharPointer(name, 2); 6879 PetscValidPointer(hasLabel, 3); 6880 *hasLabel = PETSC_FALSE; 6881 while (next) { 6882 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6883 ierr = PetscStrcmp(name, lname, hasLabel);CHKERRQ(ierr); 6884 if (*hasLabel) break; 6885 next = next->next; 6886 } 6887 PetscFunctionReturn(0); 6888 } 6889 6890 /*@C 6891 DMGetLabel - Return the label of a given name, or NULL 6892 6893 Not Collective 6894 6895 Input Parameters: 6896 + dm - The DM object 6897 - name - The label name 6898 6899 Output Parameter: 6900 . label - The DMLabel, or NULL if the label is absent 6901 6902 Level: intermediate 6903 6904 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6905 @*/ 6906 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 6907 { 6908 DMLabelLink next = dm->labels->next; 6909 PetscBool hasLabel; 6910 const char *lname; 6911 PetscErrorCode ierr; 6912 6913 PetscFunctionBegin; 6914 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6915 PetscValidCharPointer(name, 2); 6916 PetscValidPointer(label, 3); 6917 *label = NULL; 6918 while (next) { 6919 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 6920 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 6921 if (hasLabel) { 6922 *label = next->label; 6923 break; 6924 } 6925 next = next->next; 6926 } 6927 PetscFunctionReturn(0); 6928 } 6929 6930 /*@C 6931 DMGetLabelByNum - Return the nth label 6932 6933 Not Collective 6934 6935 Input Parameters: 6936 + dm - The DM object 6937 - n - the label number 6938 6939 Output Parameter: 6940 . label - the label 6941 6942 Level: intermediate 6943 6944 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6945 @*/ 6946 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 6947 { 6948 DMLabelLink next = dm->labels->next; 6949 PetscInt l = 0; 6950 6951 PetscFunctionBegin; 6952 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6953 PetscValidPointer(label, 3); 6954 while (next) { 6955 if (l == n) { 6956 *label = next->label; 6957 PetscFunctionReturn(0); 6958 } 6959 ++l; 6960 next = next->next; 6961 } 6962 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 6963 } 6964 6965 /*@C 6966 DMAddLabel - Add the label to this mesh 6967 6968 Not Collective 6969 6970 Input Parameters: 6971 + dm - The DM object 6972 - label - The DMLabel 6973 6974 Level: developer 6975 6976 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 6977 @*/ 6978 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 6979 { 6980 DMLabelLink tmpLabel; 6981 PetscBool hasLabel; 6982 const char *lname; 6983 PetscErrorCode ierr; 6984 6985 PetscFunctionBegin; 6986 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6987 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 6988 ierr = DMHasLabel(dm, lname, &hasLabel);CHKERRQ(ierr); 6989 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", lname); 6990 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 6991 tmpLabel->label = label; 6992 tmpLabel->output = PETSC_TRUE; 6993 tmpLabel->next = dm->labels->next; 6994 dm->labels->next = tmpLabel; 6995 PetscFunctionReturn(0); 6996 } 6997 6998 /*@C 6999 DMRemoveLabel - Remove the label from this mesh 7000 7001 Not Collective 7002 7003 Input Parameters: 7004 + dm - The DM object 7005 - name - The label name 7006 7007 Output Parameter: 7008 . label - The DMLabel, or NULL if the label is absent 7009 7010 Level: developer 7011 7012 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7013 @*/ 7014 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 7015 { 7016 DMLabelLink next = dm->labels->next; 7017 DMLabelLink last = NULL; 7018 PetscBool hasLabel; 7019 const char *lname; 7020 PetscErrorCode ierr; 7021 7022 PetscFunctionBegin; 7023 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7024 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 7025 *label = NULL; 7026 if (!hasLabel) PetscFunctionReturn(0); 7027 while (next) { 7028 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7029 ierr = PetscStrcmp(name, lname, &hasLabel);CHKERRQ(ierr); 7030 if (hasLabel) { 7031 if (last) last->next = next->next; 7032 else dm->labels->next = next->next; 7033 next->next = NULL; 7034 *label = next->label; 7035 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 7036 if (hasLabel) { 7037 dm->depthLabel = NULL; 7038 } 7039 ierr = PetscFree(next);CHKERRQ(ierr); 7040 break; 7041 } 7042 last = next; 7043 next = next->next; 7044 } 7045 PetscFunctionReturn(0); 7046 } 7047 7048 /*@C 7049 DMGetLabelOutput - Get the output flag for a given label 7050 7051 Not Collective 7052 7053 Input Parameters: 7054 + dm - The DM object 7055 - name - The label name 7056 7057 Output Parameter: 7058 . output - The flag for output 7059 7060 Level: developer 7061 7062 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7063 @*/ 7064 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 7065 { 7066 DMLabelLink next = dm->labels->next; 7067 const char *lname; 7068 PetscErrorCode ierr; 7069 7070 PetscFunctionBegin; 7071 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7072 PetscValidPointer(name, 2); 7073 PetscValidPointer(output, 3); 7074 while (next) { 7075 PetscBool flg; 7076 7077 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7078 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7079 if (flg) {*output = next->output; PetscFunctionReturn(0);} 7080 next = next->next; 7081 } 7082 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7083 } 7084 7085 /*@C 7086 DMSetLabelOutput - Set the output flag for a given label 7087 7088 Not Collective 7089 7090 Input Parameters: 7091 + dm - The DM object 7092 . name - The label name 7093 - output - The flag for output 7094 7095 Level: developer 7096 7097 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 7098 @*/ 7099 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 7100 { 7101 DMLabelLink next = dm->labels->next; 7102 const char *lname; 7103 PetscErrorCode ierr; 7104 7105 PetscFunctionBegin; 7106 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7107 PetscValidPointer(name, 2); 7108 while (next) { 7109 PetscBool flg; 7110 7111 ierr = PetscObjectGetName((PetscObject) next->label, &lname);CHKERRQ(ierr); 7112 ierr = PetscStrcmp(name, lname, &flg);CHKERRQ(ierr); 7113 if (flg) {next->output = output; PetscFunctionReturn(0);} 7114 next = next->next; 7115 } 7116 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 7117 } 7118 7119 7120 /*@ 7121 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 7122 7123 Collective on dmA 7124 7125 Input Parameter: 7126 . dmA - The DM object with initial labels 7127 7128 Output Parameter: 7129 . dmB - The DM object with copied labels 7130 7131 Level: intermediate 7132 7133 Note: This is typically used when interpolating or otherwise adding to a mesh 7134 7135 .seealso: DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 7136 @*/ 7137 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 7138 { 7139 PetscInt numLabels, l; 7140 PetscErrorCode ierr; 7141 7142 PetscFunctionBegin; 7143 if (dmA == dmB) PetscFunctionReturn(0); 7144 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 7145 for (l = 0; l < numLabels; ++l) { 7146 DMLabel label, labelNew; 7147 const char *name; 7148 PetscBool flg; 7149 7150 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 7151 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 7152 if (flg) continue; 7153 ierr = PetscStrcmp(name, "dim", &flg);CHKERRQ(ierr); 7154 if (flg) continue; 7155 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 7156 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 7157 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 7158 } 7159 PetscFunctionReturn(0); 7160 } 7161 7162 /*@ 7163 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 7164 7165 Input Parameter: 7166 . dm - The DM object 7167 7168 Output Parameter: 7169 . cdm - The coarse DM 7170 7171 Level: intermediate 7172 7173 .seealso: DMSetCoarseDM() 7174 @*/ 7175 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 7176 { 7177 PetscFunctionBegin; 7178 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7179 PetscValidPointer(cdm, 2); 7180 *cdm = dm->coarseMesh; 7181 PetscFunctionReturn(0); 7182 } 7183 7184 /*@ 7185 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 7186 7187 Input Parameters: 7188 + dm - The DM object 7189 - cdm - The coarse DM 7190 7191 Level: intermediate 7192 7193 .seealso: DMGetCoarseDM() 7194 @*/ 7195 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 7196 { 7197 PetscErrorCode ierr; 7198 7199 PetscFunctionBegin; 7200 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7201 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 7202 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 7203 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 7204 dm->coarseMesh = cdm; 7205 PetscFunctionReturn(0); 7206 } 7207 7208 /*@ 7209 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 7210 7211 Input Parameter: 7212 . dm - The DM object 7213 7214 Output Parameter: 7215 . fdm - The fine DM 7216 7217 Level: intermediate 7218 7219 .seealso: DMSetFineDM() 7220 @*/ 7221 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 7222 { 7223 PetscFunctionBegin; 7224 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7225 PetscValidPointer(fdm, 2); 7226 *fdm = dm->fineMesh; 7227 PetscFunctionReturn(0); 7228 } 7229 7230 /*@ 7231 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 7232 7233 Input Parameters: 7234 + dm - The DM object 7235 - fdm - The fine DM 7236 7237 Level: intermediate 7238 7239 .seealso: DMGetFineDM() 7240 @*/ 7241 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 7242 { 7243 PetscErrorCode ierr; 7244 7245 PetscFunctionBegin; 7246 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7247 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 7248 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 7249 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 7250 dm->fineMesh = fdm; 7251 PetscFunctionReturn(0); 7252 } 7253 7254 /*=== DMBoundary code ===*/ 7255 7256 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 7257 { 7258 PetscInt d; 7259 PetscErrorCode ierr; 7260 7261 PetscFunctionBegin; 7262 for (d = 0; d < dm->Nds; ++d) { 7263 ierr = PetscDSCopyBoundary(dm->probs[d].ds, dmNew->probs[d].ds);CHKERRQ(ierr); 7264 } 7265 PetscFunctionReturn(0); 7266 } 7267 7268 /*@C 7269 DMAddBoundary - Add a boundary condition to the model 7270 7271 Input Parameters: 7272 + dm - The DM, with a PetscDS that matches the problem being constrained 7273 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7274 . name - The BC name 7275 . labelname - The label defining constrained points 7276 . field - The field to constrain 7277 . numcomps - The number of constrained field components (0 will constrain all fields) 7278 . comps - An array of constrained component numbers 7279 . bcFunc - A pointwise function giving boundary values 7280 . numids - The number of DMLabel ids for constrained points 7281 . ids - An array of ids for constrained points 7282 - ctx - An optional user context for bcFunc 7283 7284 Options Database Keys: 7285 + -bc_<boundary name> <num> - Overrides the boundary ids 7286 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7287 7288 Level: developer 7289 7290 .seealso: DMGetBoundary() 7291 @*/ 7292 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) 7293 { 7294 PetscDS ds; 7295 PetscErrorCode ierr; 7296 7297 PetscFunctionBegin; 7298 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7299 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7300 ierr = PetscDSAddBoundary(ds, type,name, labelname, field, numcomps, comps, bcFunc, numids, ids, ctx);CHKERRQ(ierr); 7301 PetscFunctionReturn(0); 7302 } 7303 7304 /*@ 7305 DMGetNumBoundary - Get the number of registered BC 7306 7307 Input Parameters: 7308 . dm - The mesh object 7309 7310 Output Parameters: 7311 . numBd - The number of BC 7312 7313 Level: intermediate 7314 7315 .seealso: DMAddBoundary(), DMGetBoundary() 7316 @*/ 7317 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 7318 { 7319 PetscDS ds; 7320 PetscErrorCode ierr; 7321 7322 PetscFunctionBegin; 7323 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7324 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7325 ierr = PetscDSGetNumBoundary(ds, numBd);CHKERRQ(ierr); 7326 PetscFunctionReturn(0); 7327 } 7328 7329 /*@C 7330 DMGetBoundary - Get a model boundary condition 7331 7332 Input Parameters: 7333 + dm - The mesh object 7334 - bd - The BC number 7335 7336 Output Parameters: 7337 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 7338 . name - The BC name 7339 . labelname - The label defining constrained points 7340 . field - The field to constrain 7341 . numcomps - The number of constrained field components 7342 . comps - An array of constrained component numbers 7343 . bcFunc - A pointwise function giving boundary values 7344 . numids - The number of DMLabel ids for constrained points 7345 . ids - An array of ids for constrained points 7346 - ctx - An optional user context for bcFunc 7347 7348 Options Database Keys: 7349 + -bc_<boundary name> <num> - Overrides the boundary ids 7350 - -bc_<boundary name>_comp <num> - Overrides the boundary components 7351 7352 Level: developer 7353 7354 .seealso: DMAddBoundary() 7355 @*/ 7356 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) 7357 { 7358 PetscDS ds; 7359 PetscErrorCode ierr; 7360 7361 PetscFunctionBegin; 7362 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7363 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7364 ierr = PetscDSGetBoundary(ds, bd, type, name, labelname, field, numcomps, comps, func, numids, ids, ctx);CHKERRQ(ierr); 7365 PetscFunctionReturn(0); 7366 } 7367 7368 static PetscErrorCode DMPopulateBoundary(DM dm) 7369 { 7370 PetscDS ds; 7371 DMBoundary *lastnext; 7372 DSBoundary dsbound; 7373 PetscErrorCode ierr; 7374 7375 PetscFunctionBegin; 7376 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 7377 dsbound = ds->boundary; 7378 if (dm->boundary) { 7379 DMBoundary next = dm->boundary; 7380 7381 /* quick check to see if the PetscDS has changed */ 7382 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 7383 /* the PetscDS has changed: tear down and rebuild */ 7384 while (next) { 7385 DMBoundary b = next; 7386 7387 next = b->next; 7388 ierr = PetscFree(b);CHKERRQ(ierr); 7389 } 7390 dm->boundary = NULL; 7391 } 7392 7393 lastnext = &(dm->boundary); 7394 while (dsbound) { 7395 DMBoundary dmbound; 7396 7397 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 7398 dmbound->dsboundary = dsbound; 7399 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 7400 if (!dmbound->label) {ierr = PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr);} 7401 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 7402 *lastnext = dmbound; 7403 lastnext = &(dmbound->next); 7404 dsbound = dsbound->next; 7405 } 7406 PetscFunctionReturn(0); 7407 } 7408 7409 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 7410 { 7411 DMBoundary b; 7412 PetscErrorCode ierr; 7413 7414 PetscFunctionBegin; 7415 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7416 PetscValidPointer(isBd, 3); 7417 *isBd = PETSC_FALSE; 7418 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 7419 b = dm->boundary; 7420 while (b && !(*isBd)) { 7421 DMLabel label = b->label; 7422 DSBoundary dsb = b->dsboundary; 7423 7424 if (label) { 7425 PetscInt i; 7426 7427 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 7428 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 7429 } 7430 } 7431 b = b->next; 7432 } 7433 PetscFunctionReturn(0); 7434 } 7435 7436 /*@C 7437 DMProjectFunction - This projects the given function into the function space provided. 7438 7439 Input Parameters: 7440 + dm - The DM 7441 . time - The time 7442 . funcs - The coordinate functions to evaluate, one per field 7443 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 7444 - mode - The insertion mode for values 7445 7446 Output Parameter: 7447 . X - vector 7448 7449 Calling sequence of func: 7450 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 7451 7452 + dim - The spatial dimension 7453 . x - The coordinates 7454 . Nf - The number of fields 7455 . u - The output field values 7456 - ctx - optional user-defined function context 7457 7458 Level: developer 7459 7460 .seealso: DMComputeL2Diff() 7461 @*/ 7462 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 7463 { 7464 Vec localX; 7465 PetscErrorCode ierr; 7466 7467 PetscFunctionBegin; 7468 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7469 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7470 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7471 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7472 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7473 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7474 PetscFunctionReturn(0); 7475 } 7476 7477 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 7478 { 7479 PetscErrorCode ierr; 7480 7481 PetscFunctionBegin; 7482 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7483 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7484 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLocal",((PetscObject)dm)->type_name); 7485 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7486 PetscFunctionReturn(0); 7487 } 7488 7489 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) 7490 { 7491 Vec localX; 7492 PetscErrorCode ierr; 7493 7494 PetscFunctionBegin; 7495 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7496 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 7497 ierr = DMProjectFunctionLabelLocal(dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7498 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 7499 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 7500 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 7501 PetscFunctionReturn(0); 7502 } 7503 7504 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) 7505 { 7506 PetscErrorCode ierr; 7507 7508 PetscFunctionBegin; 7509 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7510 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 7511 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 7512 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, Nc, comps, funcs, ctxs, mode, localX);CHKERRQ(ierr); 7513 PetscFunctionReturn(0); 7514 } 7515 7516 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 7517 void (**funcs)(PetscInt, PetscInt, PetscInt, 7518 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7519 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7520 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 7521 InsertMode mode, Vec localX) 7522 { 7523 PetscErrorCode ierr; 7524 7525 PetscFunctionBegin; 7526 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7527 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 7528 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 7529 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 7530 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 7531 PetscFunctionReturn(0); 7532 } 7533 7534 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Nc, const PetscInt comps[], Vec localU, 7535 void (**funcs)(PetscInt, PetscInt, PetscInt, 7536 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7537 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 7538 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 7539 InsertMode mode, Vec localX) 7540 { 7541 PetscErrorCode ierr; 7542 7543 PetscFunctionBegin; 7544 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7545 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 7546 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 7547 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMProjectFieldLocal",((PetscObject)dm)->type_name); 7548 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, Nc, comps, localU, funcs, mode, localX);CHKERRQ(ierr); 7549 PetscFunctionReturn(0); 7550 } 7551 7552 /*@C 7553 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 7554 7555 Input Parameters: 7556 + dm - The DM 7557 . time - The time 7558 . funcs - The functions to evaluate for each field component 7559 . ctxs - Optional array of contexts to pass to each function, or NULL. 7560 - X - The coefficient vector u_h, a global vector 7561 7562 Output Parameter: 7563 . diff - The diff ||u - u_h||_2 7564 7565 Level: developer 7566 7567 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 7568 @*/ 7569 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 7570 { 7571 PetscErrorCode ierr; 7572 7573 PetscFunctionBegin; 7574 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7575 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7576 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2Diff",((PetscObject)dm)->type_name); 7577 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 7578 PetscFunctionReturn(0); 7579 } 7580 7581 /*@C 7582 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 7583 7584 Collective on dm 7585 7586 Input Parameters: 7587 + dm - The DM 7588 , time - The time 7589 . funcs - The gradient functions to evaluate for each field component 7590 . ctxs - Optional array of contexts to pass to each function, or NULL. 7591 . X - The coefficient vector u_h, a global vector 7592 - n - The vector to project along 7593 7594 Output Parameter: 7595 . diff - The diff ||(grad u - grad u_h) . n||_2 7596 7597 Level: developer 7598 7599 .seealso: DMProjectFunction(), DMComputeL2Diff() 7600 @*/ 7601 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) 7602 { 7603 PetscErrorCode ierr; 7604 7605 PetscFunctionBegin; 7606 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7607 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7608 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 7609 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 7610 PetscFunctionReturn(0); 7611 } 7612 7613 /*@C 7614 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 7615 7616 Collective on dm 7617 7618 Input Parameters: 7619 + dm - The DM 7620 . time - The time 7621 . funcs - The functions to evaluate for each field component 7622 . ctxs - Optional array of contexts to pass to each function, or NULL. 7623 - X - The coefficient vector u_h, a global vector 7624 7625 Output Parameter: 7626 . diff - The array of differences, ||u^f - u^f_h||_2 7627 7628 Level: developer 7629 7630 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 7631 @*/ 7632 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 7633 { 7634 PetscErrorCode ierr; 7635 7636 PetscFunctionBegin; 7637 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7638 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 7639 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 7640 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 7641 PetscFunctionReturn(0); 7642 } 7643 7644 /*@C 7645 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 7646 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 7647 7648 Collective on dm 7649 7650 Input parameters: 7651 + dm - the pre-adaptation DM object 7652 - label - label with the flags 7653 7654 Output parameters: 7655 . dmAdapt - the adapted DM object: may be NULL if an adapted DM could not be produced. 7656 7657 Level: intermediate 7658 7659 .seealso: DMAdaptMetric(), DMCoarsen(), DMRefine() 7660 @*/ 7661 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *dmAdapt) 7662 { 7663 PetscErrorCode ierr; 7664 7665 PetscFunctionBegin; 7666 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7667 PetscValidPointer(label,2); 7668 PetscValidPointer(dmAdapt,3); 7669 *dmAdapt = NULL; 7670 if (!dm->ops->adaptlabel) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptLabel",((PetscObject)dm)->type_name); 7671 ierr = (dm->ops->adaptlabel)(dm, label, dmAdapt);CHKERRQ(ierr); 7672 PetscFunctionReturn(0); 7673 } 7674 7675 /*@C 7676 DMAdaptMetric - Generates a mesh adapted to the specified metric field using the pragmatic library. 7677 7678 Input Parameters: 7679 + dm - The DM object 7680 . metric - The metric to which the mesh is adapted, defined vertex-wise. 7681 - 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_". 7682 7683 Output Parameter: 7684 . dmAdapt - Pointer to the DM object containing the adapted mesh 7685 7686 Note: The label in the adapted mesh will be registered under the name of the input DMLabel object 7687 7688 Level: advanced 7689 7690 .seealso: DMAdaptLabel(), DMCoarsen(), DMRefine() 7691 @*/ 7692 PetscErrorCode DMAdaptMetric(DM dm, Vec metric, DMLabel bdLabel, DM *dmAdapt) 7693 { 7694 PetscErrorCode ierr; 7695 7696 PetscFunctionBegin; 7697 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7698 PetscValidHeaderSpecific(metric, VEC_CLASSID, 2); 7699 if (bdLabel) PetscValidPointer(bdLabel, 3); 7700 PetscValidPointer(dmAdapt, 4); 7701 *dmAdapt = NULL; 7702 if (!dm->ops->adaptmetric) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMAdaptMetric",((PetscObject)dm)->type_name); 7703 ierr = (dm->ops->adaptmetric)(dm, metric, bdLabel, dmAdapt);CHKERRQ(ierr); 7704 PetscFunctionReturn(0); 7705 } 7706 7707 /*@C 7708 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 7709 7710 Not Collective 7711 7712 Input Parameter: 7713 . dm - The DM 7714 7715 Output Parameter: 7716 . nranks - the number of neighbours 7717 . ranks - the neighbors ranks 7718 7719 Notes: 7720 Do not free the array, it is freed when the DM is destroyed. 7721 7722 Level: beginner 7723 7724 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 7725 @*/ 7726 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 7727 { 7728 PetscErrorCode ierr; 7729 7730 PetscFunctionBegin; 7731 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7732 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMGetNeighbors",((PetscObject)dm)->type_name); 7733 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 7734 PetscFunctionReturn(0); 7735 } 7736 7737 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 7738 7739 /* 7740 Converts the input vector to a ghosted vector and then calls the standard coloring code. 7741 This has be a different function because it requires DM which is not defined in the Mat library 7742 */ 7743 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 7744 { 7745 PetscErrorCode ierr; 7746 7747 PetscFunctionBegin; 7748 if (coloring->ctype == IS_COLORING_LOCAL) { 7749 Vec x1local; 7750 DM dm; 7751 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 7752 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 7753 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 7754 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 7755 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 7756 x1 = x1local; 7757 } 7758 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 7759 if (coloring->ctype == IS_COLORING_LOCAL) { 7760 DM dm; 7761 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 7762 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 7763 } 7764 PetscFunctionReturn(0); 7765 } 7766 7767 /*@ 7768 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 7769 7770 Input Parameter: 7771 . coloring - the MatFDColoring object 7772 7773 Developer Notes: 7774 this routine exists because the PETSc Mat library does not know about the DM objects 7775 7776 Level: advanced 7777 7778 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 7779 @*/ 7780 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 7781 { 7782 PetscFunctionBegin; 7783 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 7784 PetscFunctionReturn(0); 7785 } 7786 7787 /*@ 7788 DMGetCompatibility - determine if two DMs are compatible 7789 7790 Collective 7791 7792 Input Parameters: 7793 + dm - the first DM 7794 - dm2 - the second DM 7795 7796 Output Parameters: 7797 + compatible - whether or not the two DMs are compatible 7798 - set - whether or not the compatible value was set 7799 7800 Notes: 7801 Two DMs are deemed compatible if they represent the same parallel decomposition 7802 of the same topology. This implies that the section (field data) on one 7803 "makes sense" with respect to the topology and parallel decomposition of the other. 7804 Loosely speaking, compatible DMs represent the same domain and parallel 7805 decomposition, but hold different data. 7806 7807 Typically, one would confirm compatibility if intending to simultaneously iterate 7808 over a pair of vectors obtained from different DMs. 7809 7810 For example, two DMDA objects are compatible if they have the same local 7811 and global sizes and the same stencil width. They can have different numbers 7812 of degrees of freedom per node. Thus, one could use the node numbering from 7813 either DM in bounds for a loop over vectors derived from either DM. 7814 7815 Consider the operation of summing data living on a 2-dof DMDA to data living 7816 on a 1-dof DMDA, which should be compatible, as in the following snippet. 7817 .vb 7818 ... 7819 ierr = DMGetCompatibility(da1,da2,&compatible,&set);CHKERRQ(ierr); 7820 if (set && compatible) { 7821 ierr = DMDAVecGetArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 7822 ierr = DMDAVecGetArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 7823 ierr = DMDAGetCorners(da1,&x,&y,NULL,&m,&n,NULL);CHKERRQ(ierr); 7824 for (j=y; j<y+n; ++j) { 7825 for (i=x; i<x+m, ++i) { 7826 arr1[j][i][0] = arr2[j][i][0] + arr2[j][i][1]; 7827 } 7828 } 7829 ierr = DMDAVecRestoreArrayDOF(da1,vec1,&arr1);CHKERRQ(ierr); 7830 ierr = DMDAVecRestoreArrayDOF(da2,vec2,&arr2);CHKERRQ(ierr); 7831 } else { 7832 SETERRQ(PetscObjectComm((PetscObject)da1,PETSC_ERR_ARG_INCOMP,"DMDA objects incompatible"); 7833 } 7834 ... 7835 .ve 7836 7837 Checking compatibility might be expensive for a given implementation of DM, 7838 or might be impossible to unambiguously confirm or deny. For this reason, 7839 this function may decline to determine compatibility, and hence users should 7840 always check the "set" output parameter. 7841 7842 A DM is always compatible with itself. 7843 7844 In the current implementation, DMs which live on "unequal" communicators 7845 (MPI_UNEQUAL in the terminology of MPI_Comm_compare()) are always deemed 7846 incompatible. 7847 7848 This function is labeled "Collective," as information about all subdomains 7849 is required on each rank. However, in DM implementations which store all this 7850 information locally, this function may be merely "Logically Collective". 7851 7852 Developer Notes: 7853 Compatibility is assumed to be a symmetric concept; DM A is compatible with DM B 7854 iff B is compatible with A. Thus, this function checks the implementations 7855 of both dm and dm2 (if they are of different types), attempting to determine 7856 compatibility. It is left to DM implementers to ensure that symmetry is 7857 preserved. The simplest way to do this is, when implementing type-specific 7858 logic for this function, is to check for existing logic in the implementation 7859 of other DM types and let *set = PETSC_FALSE if found. 7860 7861 Level: advanced 7862 7863 .seealso: DM, DMDACreateCompatibleDMDA(), DMStagCreateCompatibleDMStag() 7864 @*/ 7865 7866 PetscErrorCode DMGetCompatibility(DM dm,DM dm2,PetscBool *compatible,PetscBool *set) 7867 { 7868 PetscErrorCode ierr; 7869 PetscMPIInt compareResult; 7870 DMType type,type2; 7871 PetscBool sameType; 7872 7873 PetscFunctionBegin; 7874 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 7875 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 7876 7877 /* Declare a DM compatible with itself */ 7878 if (dm == dm2) { 7879 *set = PETSC_TRUE; 7880 *compatible = PETSC_TRUE; 7881 PetscFunctionReturn(0); 7882 } 7883 7884 /* Declare a DM incompatible with a DM that lives on an "unequal" 7885 communicator. Note that this does not preclude compatibility with 7886 DMs living on "congruent" or "similar" communicators, but this must be 7887 determined by the implementation-specific logic */ 7888 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)dm),PetscObjectComm((PetscObject)dm2),&compareResult);CHKERRQ(ierr); 7889 if (compareResult == MPI_UNEQUAL) { 7890 *set = PETSC_TRUE; 7891 *compatible = PETSC_FALSE; 7892 PetscFunctionReturn(0); 7893 } 7894 7895 /* Pass to the implementation-specific routine, if one exists. */ 7896 if (dm->ops->getcompatibility) { 7897 ierr = (*dm->ops->getcompatibility)(dm,dm2,compatible,set);CHKERRQ(ierr); 7898 if (*set) { 7899 PetscFunctionReturn(0); 7900 } 7901 } 7902 7903 /* If dm and dm2 are of different types, then attempt to check compatibility 7904 with an implementation of this function from dm2 */ 7905 ierr = DMGetType(dm,&type);CHKERRQ(ierr); 7906 ierr = DMGetType(dm2,&type2);CHKERRQ(ierr); 7907 ierr = PetscStrcmp(type,type2,&sameType);CHKERRQ(ierr); 7908 if (!sameType && dm2->ops->getcompatibility) { 7909 ierr = (*dm2->ops->getcompatibility)(dm2,dm,compatible,set);CHKERRQ(ierr); /* Note argument order */ 7910 } else { 7911 *set = PETSC_FALSE; 7912 } 7913 PetscFunctionReturn(0); 7914 } 7915