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