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_Refine, 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 DMSetMatrixPreallocateOnly() 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 && *dmlist) { 1614 for (i = 0; i < l; i++) { 1615 for (link=dm->subdomainhook; link; link=link->next) { 1616 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);} 1617 } 1618 if (dm->ctx) (*dmlist)[i]->ctx = dm->ctx; 1619 } 1620 } 1621 if (len) *len = l; 1622 } 1623 PetscFunctionReturn(0); 1624 } 1625 1626 1627 #undef __FUNCT__ 1628 #define __FUNCT__ "DMCreateDomainDecompositionScatters" 1629 /*@C 1630 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector 1631 1632 Not collective 1633 1634 Input Parameters: 1635 + dm - the DM object 1636 . n - the number of subdomain scatters 1637 - subdms - the local subdomains 1638 1639 Output Parameters: 1640 + n - the number of scatters returned 1641 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain 1642 . oscat - scatter from global vector to overlapping global vector entries on subdomain 1643 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts) 1644 1645 Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution 1646 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets 1647 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of 1648 solution and residual data. 1649 1650 Level: developer 1651 1652 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1653 @*/ 1654 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat) 1655 { 1656 PetscErrorCode ierr; 1657 1658 PetscFunctionBegin; 1659 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1660 PetscValidPointer(subdms,3); 1661 if (dm->ops->createddscatters) { 1662 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr); 1663 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionScatter implementation defined"); 1664 PetscFunctionReturn(0); 1665 } 1666 1667 #undef __FUNCT__ 1668 #define __FUNCT__ "DMRefine" 1669 /*@ 1670 DMRefine - Refines a DM object 1671 1672 Collective on DM 1673 1674 Input Parameter: 1675 + dm - the DM object 1676 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1677 1678 Output Parameter: 1679 . dmf - the refined DM, or NULL 1680 1681 Note: If no refinement was done, the return value is NULL 1682 1683 Level: developer 1684 1685 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1686 @*/ 1687 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 1688 { 1689 PetscErrorCode ierr; 1690 DMRefineHookLink link; 1691 1692 PetscFunctionBegin; 1693 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1694 ierr = PetscLogEventBegin(DM_Refine,dm,0,0,0);CHKERRQ(ierr); 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 ierr = PetscLogEventEnd(DM_Refine,dm,0,0,0);CHKERRQ(ierr); 1714 PetscFunctionReturn(0); 1715 } 1716 1717 #undef __FUNCT__ 1718 #define __FUNCT__ "DMRefineHookAdd" 1719 /*@C 1720 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 1721 1722 Logically Collective 1723 1724 Input Arguments: 1725 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1726 . refinehook - function to run when setting up a coarser level 1727 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1728 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1729 1730 Calling sequence of refinehook: 1731 $ refinehook(DM coarse,DM fine,void *ctx); 1732 1733 + coarse - coarse level DM 1734 . fine - fine level DM to interpolate problem to 1735 - ctx - optional user-defined function context 1736 1737 Calling sequence for interphook: 1738 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 1739 1740 + coarse - coarse level DM 1741 . interp - matrix interpolating a coarse-level solution to the finer grid 1742 . fine - fine level DM to update 1743 - ctx - optional user-defined function context 1744 1745 Level: advanced 1746 1747 Notes: 1748 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 1749 1750 If this function is called multiple times, the hooks will be run in the order they are added. 1751 1752 This function is currently not available from Fortran. 1753 1754 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1755 @*/ 1756 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1757 { 1758 PetscErrorCode ierr; 1759 DMRefineHookLink link,*p; 1760 1761 PetscFunctionBegin; 1762 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1763 for (p=&coarse->refinehook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1764 ierr = PetscNew(&link);CHKERRQ(ierr); 1765 link->refinehook = refinehook; 1766 link->interphook = interphook; 1767 link->ctx = ctx; 1768 link->next = NULL; 1769 *p = link; 1770 PetscFunctionReturn(0); 1771 } 1772 1773 #undef __FUNCT__ 1774 #define __FUNCT__ "DMInterpolate" 1775 /*@ 1776 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 1777 1778 Collective if any hooks are 1779 1780 Input Arguments: 1781 + coarse - coarser DM to use as a base 1782 . restrct - interpolation matrix, apply using MatInterpolate() 1783 - fine - finer DM to update 1784 1785 Level: developer 1786 1787 .seealso: DMRefineHookAdd(), MatInterpolate() 1788 @*/ 1789 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 1790 { 1791 PetscErrorCode ierr; 1792 DMRefineHookLink link; 1793 1794 PetscFunctionBegin; 1795 for (link=fine->refinehook; link; link=link->next) { 1796 if (link->interphook) { 1797 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr); 1798 } 1799 } 1800 PetscFunctionReturn(0); 1801 } 1802 1803 #undef __FUNCT__ 1804 #define __FUNCT__ "DMGetRefineLevel" 1805 /*@ 1806 DMGetRefineLevel - Get's the number of refinements that have generated this DM. 1807 1808 Not Collective 1809 1810 Input Parameter: 1811 . dm - the DM object 1812 1813 Output Parameter: 1814 . level - number of refinements 1815 1816 Level: developer 1817 1818 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1819 1820 @*/ 1821 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 1822 { 1823 PetscFunctionBegin; 1824 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1825 *level = dm->levelup; 1826 PetscFunctionReturn(0); 1827 } 1828 1829 #undef __FUNCT__ 1830 #define __FUNCT__ "DMSetRefineLevel" 1831 /*@ 1832 DMSetRefineLevel - Set's the number of refinements that have generated this DM. 1833 1834 Not Collective 1835 1836 Input Parameter: 1837 + dm - the DM object 1838 - level - number of refinements 1839 1840 Level: advanced 1841 1842 Notes: This value is used by PCMG to determine how many multigrid levels to use 1843 1844 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1845 1846 @*/ 1847 PetscErrorCode DMSetRefineLevel(DM dm,PetscInt level) 1848 { 1849 PetscFunctionBegin; 1850 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1851 dm->levelup = level; 1852 PetscFunctionReturn(0); 1853 } 1854 1855 #undef __FUNCT__ 1856 #define __FUNCT__ "DMGlobalToLocalHookAdd" 1857 /*@C 1858 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called 1859 1860 Logically Collective 1861 1862 Input Arguments: 1863 + dm - the DM 1864 . beginhook - function to run at the beginning of DMGlobalToLocalBegin() 1865 . endhook - function to run after DMGlobalToLocalEnd() has completed 1866 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1867 1868 Calling sequence for beginhook: 1869 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1870 1871 + dm - global DM 1872 . g - global vector 1873 . mode - mode 1874 . l - local vector 1875 - ctx - optional user-defined function context 1876 1877 1878 Calling sequence for endhook: 1879 $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1880 1881 + global - global DM 1882 - ctx - optional user-defined function context 1883 1884 Level: advanced 1885 1886 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1887 @*/ 1888 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 1889 { 1890 PetscErrorCode ierr; 1891 DMGlobalToLocalHookLink link,*p; 1892 1893 PetscFunctionBegin; 1894 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1895 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1896 ierr = PetscNew(&link);CHKERRQ(ierr); 1897 link->beginhook = beginhook; 1898 link->endhook = endhook; 1899 link->ctx = ctx; 1900 link->next = NULL; 1901 *p = link; 1902 PetscFunctionReturn(0); 1903 } 1904 1905 #undef __FUNCT__ 1906 #define __FUNCT__ "DMGlobalToLocalHook_Constraints" 1907 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx) 1908 { 1909 Mat cMat; 1910 Vec cVec; 1911 PetscSection section, cSec; 1912 PetscInt pStart, pEnd, p, dof; 1913 PetscErrorCode ierr; 1914 1915 PetscFunctionBegin; 1916 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1917 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 1918 if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) { 1919 PetscInt nRows; 1920 1921 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 1922 if (nRows <= 0) PetscFunctionReturn(0); 1923 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 1924 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 1925 ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr); 1926 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 1927 for (p = pStart; p < pEnd; p++) { 1928 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 1929 if (dof) { 1930 PetscScalar *vals; 1931 ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr); 1932 ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr); 1933 } 1934 } 1935 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 1936 } 1937 PetscFunctionReturn(0); 1938 } 1939 1940 #undef __FUNCT__ 1941 #define __FUNCT__ "DMGlobalToLocalBegin" 1942 /*@ 1943 DMGlobalToLocalBegin - Begins updating local vectors from global vector 1944 1945 Neighbor-wise Collective on DM 1946 1947 Input Parameters: 1948 + dm - the DM object 1949 . g - the global vector 1950 . mode - INSERT_VALUES or ADD_VALUES 1951 - l - the local vector 1952 1953 1954 Level: beginner 1955 1956 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1957 1958 @*/ 1959 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 1960 { 1961 PetscSF sf; 1962 PetscErrorCode ierr; 1963 DMGlobalToLocalHookLink link; 1964 1965 PetscFunctionBegin; 1966 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1967 for (link=dm->gtolhook; link; link=link->next) { 1968 if (link->beginhook) { 1969 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 1970 } 1971 } 1972 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1973 if (sf) { 1974 const PetscScalar *gArray; 1975 PetscScalar *lArray; 1976 1977 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1978 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1979 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 1980 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1981 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1982 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 1983 } else { 1984 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1985 } 1986 PetscFunctionReturn(0); 1987 } 1988 1989 #undef __FUNCT__ 1990 #define __FUNCT__ "DMGlobalToLocalEnd" 1991 /*@ 1992 DMGlobalToLocalEnd - Ends updating local vectors from global vector 1993 1994 Neighbor-wise Collective on DM 1995 1996 Input Parameters: 1997 + dm - the DM object 1998 . g - the global vector 1999 . mode - INSERT_VALUES or ADD_VALUES 2000 - l - the local vector 2001 2002 2003 Level: beginner 2004 2005 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2006 2007 @*/ 2008 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2009 { 2010 PetscSF sf; 2011 PetscErrorCode ierr; 2012 const PetscScalar *gArray; 2013 PetscScalar *lArray; 2014 DMGlobalToLocalHookLink link; 2015 2016 PetscFunctionBegin; 2017 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2018 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2019 if (sf) { 2020 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2021 2022 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 2023 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 2024 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 2025 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 2026 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 2027 } else { 2028 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2029 } 2030 ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr); 2031 for (link=dm->gtolhook; link; link=link->next) { 2032 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2033 } 2034 PetscFunctionReturn(0); 2035 } 2036 2037 #undef __FUNCT__ 2038 #define __FUNCT__ "DMLocalToGlobalHookAdd" 2039 /*@C 2040 DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called 2041 2042 Logically Collective 2043 2044 Input Arguments: 2045 + dm - the DM 2046 . beginhook - function to run at the beginning of DMLocalToGlobalBegin() 2047 . endhook - function to run after DMLocalToGlobalEnd() has completed 2048 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2049 2050 Calling sequence for beginhook: 2051 $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2052 2053 + dm - global DM 2054 . l - local vector 2055 . mode - mode 2056 . g - global vector 2057 - ctx - optional user-defined function context 2058 2059 2060 Calling sequence for endhook: 2061 $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 2062 2063 + global - global DM 2064 . l - local vector 2065 . mode - mode 2066 . g - global vector 2067 - ctx - optional user-defined function context 2068 2069 Level: advanced 2070 2071 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2072 @*/ 2073 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 2074 { 2075 PetscErrorCode ierr; 2076 DMLocalToGlobalHookLink link,*p; 2077 2078 PetscFunctionBegin; 2079 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2080 for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2081 ierr = PetscNew(&link);CHKERRQ(ierr); 2082 link->beginhook = beginhook; 2083 link->endhook = endhook; 2084 link->ctx = ctx; 2085 link->next = NULL; 2086 *p = link; 2087 PetscFunctionReturn(0); 2088 } 2089 2090 #undef __FUNCT__ 2091 #define __FUNCT__ "DMLocalToGlobalHook_Constraints" 2092 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx) 2093 { 2094 Mat cMat; 2095 Vec cVec; 2096 PetscSection section, cSec; 2097 PetscInt pStart, pEnd, p, dof; 2098 PetscErrorCode ierr; 2099 2100 PetscFunctionBegin; 2101 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2102 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 2103 if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) { 2104 PetscInt nRows; 2105 2106 ierr = MatGetSize(cMat,&nRows,NULL);CHKERRQ(ierr); 2107 if (nRows <= 0) PetscFunctionReturn(0); 2108 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 2109 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 2110 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 2111 for (p = pStart; p < pEnd; p++) { 2112 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 2113 if (dof) { 2114 PetscInt d; 2115 PetscScalar *vals; 2116 ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr); 2117 ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr); 2118 /* for this to be the true transpose, we have to zero the values that 2119 * we just extracted */ 2120 for (d = 0; d < dof; d++) { 2121 vals[d] = 0.; 2122 } 2123 } 2124 } 2125 ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr); 2126 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2127 } 2128 PetscFunctionReturn(0); 2129 } 2130 2131 #undef __FUNCT__ 2132 #define __FUNCT__ "DMLocalToGlobalBegin" 2133 /*@ 2134 DMLocalToGlobalBegin - updates global vectors from local vectors 2135 2136 Neighbor-wise Collective on DM 2137 2138 Input Parameters: 2139 + dm - the DM object 2140 . l - the local vector 2141 . 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. 2142 - g - the global vector 2143 2144 Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 2145 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one. 2146 2147 Level: beginner 2148 2149 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 2150 2151 @*/ 2152 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 2153 { 2154 PetscSF sf; 2155 PetscSection s, gs; 2156 DMLocalToGlobalHookLink link; 2157 const PetscScalar *lArray; 2158 PetscScalar *gArray; 2159 PetscBool isInsert; 2160 PetscErrorCode ierr; 2161 2162 PetscFunctionBegin; 2163 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2164 for (link=dm->ltoghook; link; link=link->next) { 2165 if (link->beginhook) { 2166 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr); 2167 } 2168 } 2169 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr); 2170 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2171 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 2172 switch (mode) { 2173 case INSERT_VALUES: 2174 case INSERT_ALL_VALUES: 2175 case INSERT_BC_VALUES: 2176 isInsert = PETSC_TRUE; break; 2177 case ADD_VALUES: 2178 case ADD_ALL_VALUES: 2179 case ADD_BC_VALUES: 2180 isInsert = PETSC_FALSE; break; 2181 default: 2182 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2183 } 2184 if (sf && !isInsert) { 2185 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2186 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2187 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2188 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2189 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2190 } else if (s && isInsert) { 2191 PetscInt gStart, pStart, pEnd, p; 2192 2193 ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr); 2194 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 2195 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 2196 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2197 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2198 for (p = pStart; p < pEnd; ++p) { 2199 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 2200 2201 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 2202 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 2203 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 2204 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 2205 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 2206 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 2207 /* Ignore off-process data and points with no global data */ 2208 if (!gdof || goff < 0) continue; 2209 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); 2210 /* If no constraints are enforced in the global vector */ 2211 if (!gcdof) { 2212 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 2213 /* If constraints are enforced in the global vector */ 2214 } else if (cdof == gcdof) { 2215 const PetscInt *cdofs; 2216 PetscInt cind = 0; 2217 2218 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 2219 for (d = 0, e = 0; d < dof; ++d) { 2220 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 2221 gArray[goff-gStart+e++] = lArray[off+d]; 2222 } 2223 } 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); 2224 } 2225 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2226 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2227 } else { 2228 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2229 } 2230 PetscFunctionReturn(0); 2231 } 2232 2233 #undef __FUNCT__ 2234 #define __FUNCT__ "DMLocalToGlobalEnd" 2235 /*@ 2236 DMLocalToGlobalEnd - updates global vectors from local vectors 2237 2238 Neighbor-wise Collective on DM 2239 2240 Input Parameters: 2241 + dm - the DM object 2242 . l - the local vector 2243 . mode - INSERT_VALUES or ADD_VALUES 2244 - g - the global vector 2245 2246 2247 Level: beginner 2248 2249 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 2250 2251 @*/ 2252 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 2253 { 2254 PetscSF sf; 2255 PetscSection s; 2256 DMLocalToGlobalHookLink link; 2257 PetscBool isInsert; 2258 PetscErrorCode ierr; 2259 2260 PetscFunctionBegin; 2261 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2262 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2263 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 2264 switch (mode) { 2265 case INSERT_VALUES: 2266 case INSERT_ALL_VALUES: 2267 isInsert = PETSC_TRUE; break; 2268 case ADD_VALUES: 2269 case ADD_ALL_VALUES: 2270 isInsert = PETSC_FALSE; break; 2271 default: 2272 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2273 } 2274 if (sf && !isInsert) { 2275 const PetscScalar *lArray; 2276 PetscScalar *gArray; 2277 2278 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2279 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2280 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2281 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2282 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2283 } else if (s && isInsert) { 2284 } else { 2285 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2286 } 2287 for (link=dm->ltoghook; link; link=link->next) { 2288 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2289 } 2290 PetscFunctionReturn(0); 2291 } 2292 2293 #undef __FUNCT__ 2294 #define __FUNCT__ "DMLocalToLocalBegin" 2295 /*@ 2296 DMLocalToLocalBegin - Maps from a local vector (including ghost points 2297 that contain irrelevant values) to another local vector where the ghost 2298 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 2299 2300 Neighbor-wise Collective on DM and Vec 2301 2302 Input Parameters: 2303 + dm - the DM object 2304 . g - the original local vector 2305 - mode - one of INSERT_VALUES or ADD_VALUES 2306 2307 Output Parameter: 2308 . l - the local vector with correct ghost values 2309 2310 Level: intermediate 2311 2312 Notes: 2313 The local vectors used here need not be the same as those 2314 obtained from DMCreateLocalVector(), BUT they 2315 must have the same parallel data layout; they could, for example, be 2316 obtained with VecDuplicate() from the DM originating vectors. 2317 2318 .keywords: DM, local-to-local, begin 2319 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2320 2321 @*/ 2322 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2323 { 2324 PetscErrorCode ierr; 2325 2326 PetscFunctionBegin; 2327 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2328 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2329 PetscFunctionReturn(0); 2330 } 2331 2332 #undef __FUNCT__ 2333 #define __FUNCT__ "DMLocalToLocalEnd" 2334 /*@ 2335 DMLocalToLocalEnd - Maps from a local vector (including ghost points 2336 that contain irrelevant values) to another local vector where the ghost 2337 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 2338 2339 Neighbor-wise Collective on DM and Vec 2340 2341 Input Parameters: 2342 + da - the DM object 2343 . g - the original local vector 2344 - mode - one of INSERT_VALUES or ADD_VALUES 2345 2346 Output Parameter: 2347 . l - the local vector with correct ghost values 2348 2349 Level: intermediate 2350 2351 Notes: 2352 The local vectors used here need not be the same as those 2353 obtained from DMCreateLocalVector(), BUT they 2354 must have the same parallel data layout; they could, for example, be 2355 obtained with VecDuplicate() from the DM originating vectors. 2356 2357 .keywords: DM, local-to-local, end 2358 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2359 2360 @*/ 2361 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2362 { 2363 PetscErrorCode ierr; 2364 2365 PetscFunctionBegin; 2366 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2367 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2368 PetscFunctionReturn(0); 2369 } 2370 2371 2372 #undef __FUNCT__ 2373 #define __FUNCT__ "DMCoarsen" 2374 /*@ 2375 DMCoarsen - Coarsens a DM object 2376 2377 Collective on DM 2378 2379 Input Parameter: 2380 + dm - the DM object 2381 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2382 2383 Output Parameter: 2384 . dmc - the coarsened DM 2385 2386 Level: developer 2387 2388 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2389 2390 @*/ 2391 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 2392 { 2393 PetscErrorCode ierr; 2394 DMCoarsenHookLink link; 2395 2396 PetscFunctionBegin; 2397 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2398 if (!dm->ops->coarsen) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"This DM cannot coarsen"); 2399 ierr = PetscLogEventBegin(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2400 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 2401 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 2402 ierr = DMSetCoarseDM(dm,*dmc);CHKERRQ(ierr); 2403 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2404 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2405 (*dmc)->ctx = dm->ctx; 2406 (*dmc)->levelup = dm->levelup; 2407 (*dmc)->leveldown = dm->leveldown + 1; 2408 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2409 for (link=dm->coarsenhook; link; link=link->next) { 2410 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2411 } 2412 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2413 PetscFunctionReturn(0); 2414 } 2415 2416 #undef __FUNCT__ 2417 #define __FUNCT__ "DMCoarsenHookAdd" 2418 /*@C 2419 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2420 2421 Logically Collective 2422 2423 Input Arguments: 2424 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2425 . coarsenhook - function to run when setting up a coarser level 2426 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2427 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2428 2429 Calling sequence of coarsenhook: 2430 $ coarsenhook(DM fine,DM coarse,void *ctx); 2431 2432 + fine - fine level DM 2433 . coarse - coarse level DM to restrict problem to 2434 - ctx - optional user-defined function context 2435 2436 Calling sequence for restricthook: 2437 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2438 2439 + fine - fine level DM 2440 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2441 . rscale - scaling vector for restriction 2442 . inject - matrix restricting by injection 2443 . coarse - coarse level DM to update 2444 - ctx - optional user-defined function context 2445 2446 Level: advanced 2447 2448 Notes: 2449 This function is only needed if auxiliary data needs to be set up on coarse grids. 2450 2451 If this function is called multiple times, the hooks will be run in the order they are added. 2452 2453 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2454 extract the finest level information from its context (instead of from the SNES). 2455 2456 This function is currently not available from Fortran. 2457 2458 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2459 @*/ 2460 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2461 { 2462 PetscErrorCode ierr; 2463 DMCoarsenHookLink link,*p; 2464 2465 PetscFunctionBegin; 2466 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2467 for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2468 ierr = PetscNew(&link);CHKERRQ(ierr); 2469 link->coarsenhook = coarsenhook; 2470 link->restricthook = restricthook; 2471 link->ctx = ctx; 2472 link->next = NULL; 2473 *p = link; 2474 PetscFunctionReturn(0); 2475 } 2476 2477 #undef __FUNCT__ 2478 #define __FUNCT__ "DMRestrict" 2479 /*@ 2480 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 2481 2482 Collective if any hooks are 2483 2484 Input Arguments: 2485 + fine - finer DM to use as a base 2486 . restrct - restriction matrix, apply using MatRestrict() 2487 . inject - injection matrix, also use MatRestrict() 2488 - coarse - coarer DM to update 2489 2490 Level: developer 2491 2492 .seealso: DMCoarsenHookAdd(), MatRestrict() 2493 @*/ 2494 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 2495 { 2496 PetscErrorCode ierr; 2497 DMCoarsenHookLink link; 2498 2499 PetscFunctionBegin; 2500 for (link=fine->coarsenhook; link; link=link->next) { 2501 if (link->restricthook) { 2502 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 2503 } 2504 } 2505 PetscFunctionReturn(0); 2506 } 2507 2508 #undef __FUNCT__ 2509 #define __FUNCT__ "DMSubDomainHookAdd" 2510 /*@C 2511 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 2512 2513 Logically Collective 2514 2515 Input Arguments: 2516 + global - global DM 2517 . ddhook - function to run to pass data to the decomposition DM upon its creation 2518 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2519 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2520 2521 2522 Calling sequence for ddhook: 2523 $ ddhook(DM global,DM block,void *ctx) 2524 2525 + global - global DM 2526 . block - block DM 2527 - ctx - optional user-defined function context 2528 2529 Calling sequence for restricthook: 2530 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 2531 2532 + global - global DM 2533 . out - scatter to the outer (with ghost and overlap points) block vector 2534 . in - scatter to block vector values only owned locally 2535 . block - block DM 2536 - ctx - optional user-defined function context 2537 2538 Level: advanced 2539 2540 Notes: 2541 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 2542 2543 If this function is called multiple times, the hooks will be run in the order they are added. 2544 2545 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2546 extract the global information from its context (instead of from the SNES). 2547 2548 This function is currently not available from Fortran. 2549 2550 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2551 @*/ 2552 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2553 { 2554 PetscErrorCode ierr; 2555 DMSubDomainHookLink link,*p; 2556 2557 PetscFunctionBegin; 2558 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2559 for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2560 ierr = PetscNew(&link);CHKERRQ(ierr); 2561 link->restricthook = restricthook; 2562 link->ddhook = ddhook; 2563 link->ctx = ctx; 2564 link->next = NULL; 2565 *p = link; 2566 PetscFunctionReturn(0); 2567 } 2568 2569 #undef __FUNCT__ 2570 #define __FUNCT__ "DMSubDomainRestrict" 2571 /*@ 2572 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 2573 2574 Collective if any hooks are 2575 2576 Input Arguments: 2577 + fine - finer DM to use as a base 2578 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 2579 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 2580 - coarse - coarer DM to update 2581 2582 Level: developer 2583 2584 .seealso: DMCoarsenHookAdd(), MatRestrict() 2585 @*/ 2586 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 2587 { 2588 PetscErrorCode ierr; 2589 DMSubDomainHookLink link; 2590 2591 PetscFunctionBegin; 2592 for (link=global->subdomainhook; link; link=link->next) { 2593 if (link->restricthook) { 2594 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2595 } 2596 } 2597 PetscFunctionReturn(0); 2598 } 2599 2600 #undef __FUNCT__ 2601 #define __FUNCT__ "DMGetCoarsenLevel" 2602 /*@ 2603 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2604 2605 Not Collective 2606 2607 Input Parameter: 2608 . dm - the DM object 2609 2610 Output Parameter: 2611 . level - number of coarsenings 2612 2613 Level: developer 2614 2615 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2616 2617 @*/ 2618 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2619 { 2620 PetscFunctionBegin; 2621 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2622 *level = dm->leveldown; 2623 PetscFunctionReturn(0); 2624 } 2625 2626 2627 2628 #undef __FUNCT__ 2629 #define __FUNCT__ "DMRefineHierarchy" 2630 /*@C 2631 DMRefineHierarchy - Refines a DM object, all levels at once 2632 2633 Collective on DM 2634 2635 Input Parameter: 2636 + dm - the DM object 2637 - nlevels - the number of levels of refinement 2638 2639 Output Parameter: 2640 . dmf - the refined DM hierarchy 2641 2642 Level: developer 2643 2644 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2645 2646 @*/ 2647 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 2648 { 2649 PetscErrorCode ierr; 2650 2651 PetscFunctionBegin; 2652 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2653 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2654 if (nlevels == 0) PetscFunctionReturn(0); 2655 if (dm->ops->refinehierarchy) { 2656 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2657 } else if (dm->ops->refine) { 2658 PetscInt i; 2659 2660 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2661 for (i=1; i<nlevels; i++) { 2662 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2663 } 2664 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2665 PetscFunctionReturn(0); 2666 } 2667 2668 #undef __FUNCT__ 2669 #define __FUNCT__ "DMCoarsenHierarchy" 2670 /*@C 2671 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2672 2673 Collective on DM 2674 2675 Input Parameter: 2676 + dm - the DM object 2677 - nlevels - the number of levels of coarsening 2678 2679 Output Parameter: 2680 . dmc - the coarsened DM hierarchy 2681 2682 Level: developer 2683 2684 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2685 2686 @*/ 2687 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 2688 { 2689 PetscErrorCode ierr; 2690 2691 PetscFunctionBegin; 2692 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2693 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2694 if (nlevels == 0) PetscFunctionReturn(0); 2695 PetscValidPointer(dmc,3); 2696 if (dm->ops->coarsenhierarchy) { 2697 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 2698 } else if (dm->ops->coarsen) { 2699 PetscInt i; 2700 2701 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 2702 for (i=1; i<nlevels; i++) { 2703 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 2704 } 2705 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 2706 PetscFunctionReturn(0); 2707 } 2708 2709 #undef __FUNCT__ 2710 #define __FUNCT__ "DMCreateAggregates" 2711 /*@ 2712 DMCreateAggregates - Gets the aggregates that map between 2713 grids associated with two DMs. 2714 2715 Collective on DM 2716 2717 Input Parameters: 2718 + dmc - the coarse grid DM 2719 - dmf - the fine grid DM 2720 2721 Output Parameters: 2722 . rest - the restriction matrix (transpose of the projection matrix) 2723 2724 Level: intermediate 2725 2726 .keywords: interpolation, restriction, multigrid 2727 2728 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 2729 @*/ 2730 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 2731 { 2732 PetscErrorCode ierr; 2733 2734 PetscFunctionBegin; 2735 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 2736 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 2737 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 2738 PetscFunctionReturn(0); 2739 } 2740 2741 #undef __FUNCT__ 2742 #define __FUNCT__ "DMSetApplicationContextDestroy" 2743 /*@C 2744 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 2745 2746 Not Collective 2747 2748 Input Parameters: 2749 + dm - the DM object 2750 - destroy - the destroy function 2751 2752 Level: intermediate 2753 2754 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2755 2756 @*/ 2757 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 2758 { 2759 PetscFunctionBegin; 2760 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2761 dm->ctxdestroy = destroy; 2762 PetscFunctionReturn(0); 2763 } 2764 2765 #undef __FUNCT__ 2766 #define __FUNCT__ "DMSetApplicationContext" 2767 /*@ 2768 DMSetApplicationContext - Set a user context into a DM object 2769 2770 Not Collective 2771 2772 Input Parameters: 2773 + dm - the DM object 2774 - ctx - the user context 2775 2776 Level: intermediate 2777 2778 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2779 2780 @*/ 2781 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 2782 { 2783 PetscFunctionBegin; 2784 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2785 dm->ctx = ctx; 2786 PetscFunctionReturn(0); 2787 } 2788 2789 #undef __FUNCT__ 2790 #define __FUNCT__ "DMGetApplicationContext" 2791 /*@ 2792 DMGetApplicationContext - Gets a user context from a DM object 2793 2794 Not Collective 2795 2796 Input Parameter: 2797 . dm - the DM object 2798 2799 Output Parameter: 2800 . ctx - the user context 2801 2802 Level: intermediate 2803 2804 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2805 2806 @*/ 2807 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 2808 { 2809 PetscFunctionBegin; 2810 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2811 *(void**)ctx = dm->ctx; 2812 PetscFunctionReturn(0); 2813 } 2814 2815 #undef __FUNCT__ 2816 #define __FUNCT__ "DMSetVariableBounds" 2817 /*@C 2818 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 2819 2820 Logically Collective on DM 2821 2822 Input Parameter: 2823 + dm - the DM object 2824 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 2825 2826 Level: intermediate 2827 2828 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 2829 DMSetJacobian() 2830 2831 @*/ 2832 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 2833 { 2834 PetscFunctionBegin; 2835 dm->ops->computevariablebounds = f; 2836 PetscFunctionReturn(0); 2837 } 2838 2839 #undef __FUNCT__ 2840 #define __FUNCT__ "DMHasVariableBounds" 2841 /*@ 2842 DMHasVariableBounds - does the DM object have a variable bounds function? 2843 2844 Not Collective 2845 2846 Input Parameter: 2847 . dm - the DM object to destroy 2848 2849 Output Parameter: 2850 . flg - PETSC_TRUE if the variable bounds function exists 2851 2852 Level: developer 2853 2854 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2855 2856 @*/ 2857 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 2858 { 2859 PetscFunctionBegin; 2860 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 2861 PetscFunctionReturn(0); 2862 } 2863 2864 #undef __FUNCT__ 2865 #define __FUNCT__ "DMComputeVariableBounds" 2866 /*@C 2867 DMComputeVariableBounds - compute variable bounds used by SNESVI. 2868 2869 Logically Collective on DM 2870 2871 Input Parameters: 2872 . dm - the DM object 2873 2874 Output parameters: 2875 + xl - lower bound 2876 - xu - upper bound 2877 2878 Level: advanced 2879 2880 Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 2881 2882 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2883 2884 @*/ 2885 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 2886 { 2887 PetscErrorCode ierr; 2888 2889 PetscFunctionBegin; 2890 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 2891 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 2892 if (dm->ops->computevariablebounds) { 2893 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 2894 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 2895 PetscFunctionReturn(0); 2896 } 2897 2898 #undef __FUNCT__ 2899 #define __FUNCT__ "DMHasColoring" 2900 /*@ 2901 DMHasColoring - does the DM object have a method of providing a coloring? 2902 2903 Not Collective 2904 2905 Input Parameter: 2906 . dm - the DM object 2907 2908 Output Parameter: 2909 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 2910 2911 Level: developer 2912 2913 .seealso DMHasFunction(), DMCreateColoring() 2914 2915 @*/ 2916 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 2917 { 2918 PetscFunctionBegin; 2919 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 2920 PetscFunctionReturn(0); 2921 } 2922 2923 #undef __FUNCT__ 2924 #define __FUNCT__ "DMHasCreateRestriction" 2925 /*@ 2926 DMHasCreateRestriction - does the DM object have a method of providing a restriction? 2927 2928 Not Collective 2929 2930 Input Parameter: 2931 . dm - the DM object 2932 2933 Output Parameter: 2934 . flg - PETSC_TRUE if the DM has facilities for DMCreateRestriction(). 2935 2936 Level: developer 2937 2938 .seealso DMHasFunction(), DMCreateRestriction() 2939 2940 @*/ 2941 PetscErrorCode DMHasCreateRestriction(DM dm,PetscBool *flg) 2942 { 2943 PetscFunctionBegin; 2944 *flg = (dm->ops->createrestriction) ? PETSC_TRUE : PETSC_FALSE; 2945 PetscFunctionReturn(0); 2946 } 2947 2948 #undef __FUNCT__ 2949 #define __FUNCT__ "DMSetVec" 2950 /*@C 2951 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 2952 2953 Collective on DM 2954 2955 Input Parameter: 2956 + dm - the DM object 2957 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 2958 2959 Level: developer 2960 2961 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2962 2963 @*/ 2964 PetscErrorCode DMSetVec(DM dm,Vec x) 2965 { 2966 PetscErrorCode ierr; 2967 2968 PetscFunctionBegin; 2969 if (x) { 2970 if (!dm->x) { 2971 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 2972 } 2973 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 2974 } else if (dm->x) { 2975 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 2976 } 2977 PetscFunctionReturn(0); 2978 } 2979 2980 PetscFunctionList DMList = NULL; 2981 PetscBool DMRegisterAllCalled = PETSC_FALSE; 2982 2983 #undef __FUNCT__ 2984 #define __FUNCT__ "DMSetType" 2985 /*@C 2986 DMSetType - Builds a DM, for a particular DM implementation. 2987 2988 Collective on DM 2989 2990 Input Parameters: 2991 + dm - The DM object 2992 - method - The name of the DM type 2993 2994 Options Database Key: 2995 . -dm_type <type> - Sets the DM type; use -help for a list of available types 2996 2997 Notes: 2998 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 2999 3000 Level: intermediate 3001 3002 .keywords: DM, set, type 3003 .seealso: DMGetType(), DMCreate() 3004 @*/ 3005 PetscErrorCode DMSetType(DM dm, DMType method) 3006 { 3007 PetscErrorCode (*r)(DM); 3008 PetscBool match; 3009 PetscErrorCode ierr; 3010 3011 PetscFunctionBegin; 3012 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3013 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 3014 if (match) PetscFunctionReturn(0); 3015 3016 ierr = DMRegisterAll();CHKERRQ(ierr); 3017 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 3018 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 3019 3020 if (dm->ops->destroy) { 3021 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 3022 dm->ops->destroy = NULL; 3023 } 3024 ierr = (*r)(dm);CHKERRQ(ierr); 3025 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 3026 PetscFunctionReturn(0); 3027 } 3028 3029 #undef __FUNCT__ 3030 #define __FUNCT__ "DMGetType" 3031 /*@C 3032 DMGetType - Gets the DM type name (as a string) from the DM. 3033 3034 Not Collective 3035 3036 Input Parameter: 3037 . dm - The DM 3038 3039 Output Parameter: 3040 . type - The DM type name 3041 3042 Level: intermediate 3043 3044 .keywords: DM, get, type, name 3045 .seealso: DMSetType(), DMCreate() 3046 @*/ 3047 PetscErrorCode DMGetType(DM dm, DMType *type) 3048 { 3049 PetscErrorCode ierr; 3050 3051 PetscFunctionBegin; 3052 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 3053 PetscValidPointer(type,2); 3054 ierr = DMRegisterAll();CHKERRQ(ierr); 3055 *type = ((PetscObject)dm)->type_name; 3056 PetscFunctionReturn(0); 3057 } 3058 3059 #undef __FUNCT__ 3060 #define __FUNCT__ "DMConvert" 3061 /*@C 3062 DMConvert - Converts a DM to another DM, either of the same or different type. 3063 3064 Collective on DM 3065 3066 Input Parameters: 3067 + dm - the DM 3068 - newtype - new DM type (use "same" for the same type) 3069 3070 Output Parameter: 3071 . M - pointer to new DM 3072 3073 Notes: 3074 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 3075 the MPI communicator of the generated DM is always the same as the communicator 3076 of the input DM. 3077 3078 Level: intermediate 3079 3080 .seealso: DMCreate() 3081 @*/ 3082 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 3083 { 3084 DM B; 3085 char convname[256]; 3086 PetscBool sametype/*, issame */; 3087 PetscErrorCode ierr; 3088 3089 PetscFunctionBegin; 3090 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3091 PetscValidType(dm,1); 3092 PetscValidPointer(M,3); 3093 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 3094 /* ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); */ 3095 if (sametype) { 3096 *M = dm; 3097 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 3098 PetscFunctionReturn(0); 3099 } else { 3100 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 3101 3102 /* 3103 Order of precedence: 3104 1) See if a specialized converter is known to the current DM. 3105 2) See if a specialized converter is known to the desired DM class. 3106 3) See if a good general converter is registered for the desired class 3107 4) See if a good general converter is known for the current matrix. 3108 5) Use a really basic converter. 3109 */ 3110 3111 /* 1) See if a specialized converter is known to the current DM and the desired class */ 3112 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 3113 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 3114 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 3115 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 3116 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 3117 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 3118 if (conv) goto foundconv; 3119 3120 /* 2) See if a specialized converter is known to the desired DM class. */ 3121 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 3122 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 3123 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 3124 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 3125 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 3126 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 3127 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 3128 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 3129 if (conv) { 3130 ierr = DMDestroy(&B);CHKERRQ(ierr); 3131 goto foundconv; 3132 } 3133 3134 #if 0 3135 /* 3) See if a good general converter is registered for the desired class */ 3136 conv = B->ops->convertfrom; 3137 ierr = DMDestroy(&B);CHKERRQ(ierr); 3138 if (conv) goto foundconv; 3139 3140 /* 4) See if a good general converter is known for the current matrix */ 3141 if (dm->ops->convert) { 3142 conv = dm->ops->convert; 3143 } 3144 if (conv) goto foundconv; 3145 #endif 3146 3147 /* 5) Use a really basic converter. */ 3148 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 3149 3150 foundconv: 3151 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3152 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 3153 /* Things that are independent of DM type: We should consult DMClone() here */ 3154 if (dm->maxCell) { 3155 const PetscReal *maxCell, *L; 3156 const DMBoundaryType *bd; 3157 ierr = DMGetPeriodicity(dm, &maxCell, &L, &bd);CHKERRQ(ierr); 3158 ierr = DMSetPeriodicity(*M, maxCell, L, bd);CHKERRQ(ierr); 3159 } 3160 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 3161 } 3162 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 3163 PetscFunctionReturn(0); 3164 } 3165 3166 /*--------------------------------------------------------------------------------------------------------------------*/ 3167 3168 #undef __FUNCT__ 3169 #define __FUNCT__ "DMRegister" 3170 /*@C 3171 DMRegister - Adds a new DM component implementation 3172 3173 Not Collective 3174 3175 Input Parameters: 3176 + name - The name of a new user-defined creation routine 3177 - create_func - The creation routine itself 3178 3179 Notes: 3180 DMRegister() may be called multiple times to add several user-defined DMs 3181 3182 3183 Sample usage: 3184 .vb 3185 DMRegister("my_da", MyDMCreate); 3186 .ve 3187 3188 Then, your DM type can be chosen with the procedural interface via 3189 .vb 3190 DMCreate(MPI_Comm, DM *); 3191 DMSetType(DM,"my_da"); 3192 .ve 3193 or at runtime via the option 3194 .vb 3195 -da_type my_da 3196 .ve 3197 3198 Level: advanced 3199 3200 .keywords: DM, register 3201 .seealso: DMRegisterAll(), DMRegisterDestroy() 3202 3203 @*/ 3204 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 3205 { 3206 PetscErrorCode ierr; 3207 3208 PetscFunctionBegin; 3209 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 3210 PetscFunctionReturn(0); 3211 } 3212 3213 #undef __FUNCT__ 3214 #define __FUNCT__ "DMLoad" 3215 /*@C 3216 DMLoad - Loads a DM that has been stored in binary with DMView(). 3217 3218 Collective on PetscViewer 3219 3220 Input Parameters: 3221 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 3222 some related function before a call to DMLoad(). 3223 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 3224 HDF5 file viewer, obtained from PetscViewerHDF5Open() 3225 3226 Level: intermediate 3227 3228 Notes: 3229 The type is determined by the data in the file, any type set into the DM before this call is ignored. 3230 3231 Notes for advanced users: 3232 Most users should not need to know the details of the binary storage 3233 format, since DMLoad() and DMView() completely hide these details. 3234 But for anyone who's interested, the standard binary matrix storage 3235 format is 3236 .vb 3237 has not yet been determined 3238 .ve 3239 3240 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 3241 @*/ 3242 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 3243 { 3244 PetscBool isbinary, ishdf5; 3245 PetscErrorCode ierr; 3246 3247 PetscFunctionBegin; 3248 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 3249 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3250 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 3251 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 3252 if (isbinary) { 3253 PetscInt classid; 3254 char type[256]; 3255 3256 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3257 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3258 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3259 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3260 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3261 } else if (ishdf5) { 3262 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3263 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3264 PetscFunctionReturn(0); 3265 } 3266 3267 /******************************** FEM Support **********************************/ 3268 3269 #undef __FUNCT__ 3270 #define __FUNCT__ "DMPrintCellVector" 3271 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3272 { 3273 PetscInt f; 3274 PetscErrorCode ierr; 3275 3276 PetscFunctionBegin; 3277 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3278 for (f = 0; f < len; ++f) { 3279 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3280 } 3281 PetscFunctionReturn(0); 3282 } 3283 3284 #undef __FUNCT__ 3285 #define __FUNCT__ "DMPrintCellMatrix" 3286 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3287 { 3288 PetscInt f, g; 3289 PetscErrorCode ierr; 3290 3291 PetscFunctionBegin; 3292 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3293 for (f = 0; f < rows; ++f) { 3294 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3295 for (g = 0; g < cols; ++g) { 3296 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3297 } 3298 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3299 } 3300 PetscFunctionReturn(0); 3301 } 3302 3303 #undef __FUNCT__ 3304 #define __FUNCT__ "DMPrintLocalVec" 3305 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3306 { 3307 PetscMPIInt rank, numProcs; 3308 PetscInt p; 3309 PetscErrorCode ierr; 3310 3311 PetscFunctionBegin; 3312 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 3313 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 3314 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr); 3315 for (p = 0; p < numProcs; ++p) { 3316 if (p == rank) { 3317 Vec x; 3318 3319 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3320 ierr = VecCopy(X, x);CHKERRQ(ierr); 3321 ierr = VecChop(x, tol);CHKERRQ(ierr); 3322 ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3323 ierr = VecDestroy(&x);CHKERRQ(ierr); 3324 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3325 } 3326 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 3327 } 3328 PetscFunctionReturn(0); 3329 } 3330 3331 #undef __FUNCT__ 3332 #define __FUNCT__ "DMGetDefaultSection" 3333 /*@ 3334 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 3335 3336 Input Parameter: 3337 . dm - The DM 3338 3339 Output Parameter: 3340 . section - The PetscSection 3341 3342 Level: intermediate 3343 3344 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3345 3346 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3347 @*/ 3348 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 3349 { 3350 PetscErrorCode ierr; 3351 3352 PetscFunctionBegin; 3353 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3354 PetscValidPointer(section, 2); 3355 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3356 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3357 if (dm->defaultSection) {ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr);} 3358 } 3359 *section = dm->defaultSection; 3360 PetscFunctionReturn(0); 3361 } 3362 3363 #undef __FUNCT__ 3364 #define __FUNCT__ "DMSetDefaultSection" 3365 /*@ 3366 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3367 3368 Input Parameters: 3369 + dm - The DM 3370 - section - The PetscSection 3371 3372 Level: intermediate 3373 3374 Note: Any existing Section will be destroyed 3375 3376 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3377 @*/ 3378 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 3379 { 3380 PetscInt numFields = 0; 3381 PetscInt f; 3382 PetscErrorCode ierr; 3383 3384 PetscFunctionBegin; 3385 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3386 if (section) { 3387 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3388 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3389 } 3390 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3391 dm->defaultSection = section; 3392 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3393 if (numFields) { 3394 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3395 for (f = 0; f < numFields; ++f) { 3396 PetscObject disc; 3397 const char *name; 3398 3399 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3400 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3401 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3402 } 3403 } 3404 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3405 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3406 PetscFunctionReturn(0); 3407 } 3408 3409 #undef __FUNCT__ 3410 #define __FUNCT__ "DMGetDefaultConstraints" 3411 /*@ 3412 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3413 3414 not collective 3415 3416 Input Parameter: 3417 . dm - The DM 3418 3419 Output Parameter: 3420 + 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. 3421 - 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. 3422 3423 Level: advanced 3424 3425 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3426 3427 .seealso: DMSetDefaultConstraints() 3428 @*/ 3429 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3430 { 3431 PetscErrorCode ierr; 3432 3433 PetscFunctionBegin; 3434 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3435 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3436 if (section) {*section = dm->defaultConstraintSection;} 3437 if (mat) {*mat = dm->defaultConstraintMat;} 3438 PetscFunctionReturn(0); 3439 } 3440 3441 #undef __FUNCT__ 3442 #define __FUNCT__ "DMSetDefaultConstraints" 3443 /*@ 3444 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3445 3446 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(). 3447 3448 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. 3449 3450 collective on dm 3451 3452 Input Parameters: 3453 + dm - The DM 3454 + 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). 3455 - 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). 3456 3457 Level: advanced 3458 3459 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3460 3461 .seealso: DMGetDefaultConstraints() 3462 @*/ 3463 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3464 { 3465 PetscMPIInt result; 3466 PetscErrorCode ierr; 3467 3468 PetscFunctionBegin; 3469 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3470 if (section) { 3471 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3472 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3473 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3474 } 3475 if (mat) { 3476 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3477 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3478 if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3479 } 3480 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3481 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3482 dm->defaultConstraintSection = section; 3483 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3484 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3485 dm->defaultConstraintMat = mat; 3486 PetscFunctionReturn(0); 3487 } 3488 3489 #ifdef PETSC_USE_DEBUG 3490 #undef __FUNCT__ 3491 #define __FUNCT__ "DMDefaultSectionCheckConsistency_Internal" 3492 /* 3493 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3494 3495 Input Parameters: 3496 + dm - The DM 3497 . localSection - PetscSection describing the local data layout 3498 - globalSection - PetscSection describing the global data layout 3499 3500 Level: intermediate 3501 3502 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3503 */ 3504 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3505 { 3506 MPI_Comm comm; 3507 PetscLayout layout; 3508 const PetscInt *ranges; 3509 PetscInt pStart, pEnd, p, nroots; 3510 PetscMPIInt size, rank; 3511 PetscBool valid = PETSC_TRUE, gvalid; 3512 PetscErrorCode ierr; 3513 3514 PetscFunctionBegin; 3515 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3516 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3517 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3518 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3519 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3520 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3521 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3522 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3523 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3524 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3525 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3526 for (p = pStart; p < pEnd; ++p) { 3527 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3528 3529 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3530 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3531 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3532 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3533 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3534 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3535 if (!gdof) continue; /* Censored point */ 3536 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;} 3537 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;} 3538 if (gdof < 0) { 3539 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3540 for (d = 0; d < gsize; ++d) { 3541 PetscInt offset = -(goff+1) + d, r; 3542 3543 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3544 if (r < 0) r = -(r+2); 3545 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;} 3546 } 3547 } 3548 } 3549 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3550 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3551 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3552 if (!gvalid) { 3553 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3554 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3555 } 3556 PetscFunctionReturn(0); 3557 } 3558 #endif 3559 3560 #undef __FUNCT__ 3561 #define __FUNCT__ "DMGetDefaultGlobalSection" 3562 /*@ 3563 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3564 3565 Collective on DM 3566 3567 Input Parameter: 3568 . dm - The DM 3569 3570 Output Parameter: 3571 . section - The PetscSection 3572 3573 Level: intermediate 3574 3575 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3576 3577 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3578 @*/ 3579 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3580 { 3581 PetscErrorCode ierr; 3582 3583 PetscFunctionBegin; 3584 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3585 PetscValidPointer(section, 2); 3586 if (!dm->defaultGlobalSection) { 3587 PetscSection s; 3588 3589 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3590 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3591 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3592 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3593 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3594 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3595 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 3596 } 3597 *section = dm->defaultGlobalSection; 3598 PetscFunctionReturn(0); 3599 } 3600 3601 #undef __FUNCT__ 3602 #define __FUNCT__ "DMSetDefaultGlobalSection" 3603 /*@ 3604 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3605 3606 Input Parameters: 3607 + dm - The DM 3608 - section - The PetscSection, or NULL 3609 3610 Level: intermediate 3611 3612 Note: Any existing Section will be destroyed 3613 3614 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3615 @*/ 3616 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3617 { 3618 PetscErrorCode ierr; 3619 3620 PetscFunctionBegin; 3621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3622 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3623 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3624 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3625 dm->defaultGlobalSection = section; 3626 #ifdef PETSC_USE_DEBUG 3627 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3628 #endif 3629 PetscFunctionReturn(0); 3630 } 3631 3632 #undef __FUNCT__ 3633 #define __FUNCT__ "DMGetDefaultSF" 3634 /*@ 3635 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3636 it is created from the default PetscSection layouts in the DM. 3637 3638 Input Parameter: 3639 . dm - The DM 3640 3641 Output Parameter: 3642 . sf - The PetscSF 3643 3644 Level: intermediate 3645 3646 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3647 3648 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3649 @*/ 3650 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3651 { 3652 PetscInt nroots; 3653 PetscErrorCode ierr; 3654 3655 PetscFunctionBegin; 3656 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3657 PetscValidPointer(sf, 2); 3658 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3659 if (nroots < 0) { 3660 PetscSection section, gSection; 3661 3662 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3663 if (section) { 3664 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3665 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3666 } else { 3667 *sf = NULL; 3668 PetscFunctionReturn(0); 3669 } 3670 } 3671 *sf = dm->defaultSF; 3672 PetscFunctionReturn(0); 3673 } 3674 3675 #undef __FUNCT__ 3676 #define __FUNCT__ "DMSetDefaultSF" 3677 /*@ 3678 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3679 3680 Input Parameters: 3681 + dm - The DM 3682 - sf - The PetscSF 3683 3684 Level: intermediate 3685 3686 Note: Any previous SF is destroyed 3687 3688 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3689 @*/ 3690 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3691 { 3692 PetscErrorCode ierr; 3693 3694 PetscFunctionBegin; 3695 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3696 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3697 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3698 dm->defaultSF = sf; 3699 PetscFunctionReturn(0); 3700 } 3701 3702 #undef __FUNCT__ 3703 #define __FUNCT__ "DMCreateDefaultSF" 3704 /*@C 3705 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3706 describing the data layout. 3707 3708 Input Parameters: 3709 + dm - The DM 3710 . localSection - PetscSection describing the local data layout 3711 - globalSection - PetscSection describing the global data layout 3712 3713 Level: intermediate 3714 3715 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3716 @*/ 3717 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3718 { 3719 MPI_Comm comm; 3720 PetscLayout layout; 3721 const PetscInt *ranges; 3722 PetscInt *local; 3723 PetscSFNode *remote; 3724 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3725 PetscMPIInt size, rank; 3726 PetscErrorCode ierr; 3727 3728 PetscFunctionBegin; 3729 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3730 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3731 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3732 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3733 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3734 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3735 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3736 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3737 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3738 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3739 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3740 for (p = pStart; p < pEnd; ++p) { 3741 PetscInt gdof, gcdof; 3742 3743 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3744 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3745 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)); 3746 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3747 } 3748 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3749 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3750 for (p = pStart, l = 0; p < pEnd; ++p) { 3751 const PetscInt *cind; 3752 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3753 3754 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3755 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3756 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3757 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3758 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3759 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3760 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3761 if (!gdof) continue; /* Censored point */ 3762 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3763 if (gsize != dof-cdof) { 3764 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); 3765 cdof = 0; /* Ignore constraints */ 3766 } 3767 for (d = 0, c = 0; d < dof; ++d) { 3768 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3769 local[l+d-c] = off+d; 3770 } 3771 if (gdof < 0) { 3772 for (d = 0; d < gsize; ++d, ++l) { 3773 PetscInt offset = -(goff+1) + d, r; 3774 3775 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3776 if (r < 0) r = -(r+2); 3777 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); 3778 remote[l].rank = r; 3779 remote[l].index = offset - ranges[r]; 3780 } 3781 } else { 3782 for (d = 0; d < gsize; ++d, ++l) { 3783 remote[l].rank = rank; 3784 remote[l].index = goff+d - ranges[rank]; 3785 } 3786 } 3787 } 3788 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3789 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3790 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3791 PetscFunctionReturn(0); 3792 } 3793 3794 #undef __FUNCT__ 3795 #define __FUNCT__ "DMGetPointSF" 3796 /*@ 3797 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3798 3799 Input Parameter: 3800 . dm - The DM 3801 3802 Output Parameter: 3803 . sf - The PetscSF 3804 3805 Level: intermediate 3806 3807 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3808 3809 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3810 @*/ 3811 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3812 { 3813 PetscFunctionBegin; 3814 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3815 PetscValidPointer(sf, 2); 3816 *sf = dm->sf; 3817 PetscFunctionReturn(0); 3818 } 3819 3820 #undef __FUNCT__ 3821 #define __FUNCT__ "DMSetPointSF" 3822 /*@ 3823 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3824 3825 Input Parameters: 3826 + dm - The DM 3827 - sf - The PetscSF 3828 3829 Level: intermediate 3830 3831 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3832 @*/ 3833 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3834 { 3835 PetscErrorCode ierr; 3836 3837 PetscFunctionBegin; 3838 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3839 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3840 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3841 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3842 dm->sf = sf; 3843 PetscFunctionReturn(0); 3844 } 3845 3846 #undef __FUNCT__ 3847 #define __FUNCT__ "DMGetDS" 3848 /*@ 3849 DMGetDS - Get the PetscDS 3850 3851 Input Parameter: 3852 . dm - The DM 3853 3854 Output Parameter: 3855 . prob - The PetscDS 3856 3857 Level: developer 3858 3859 .seealso: DMSetDS() 3860 @*/ 3861 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3862 { 3863 PetscFunctionBegin; 3864 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3865 PetscValidPointer(prob, 2); 3866 *prob = dm->prob; 3867 PetscFunctionReturn(0); 3868 } 3869 3870 #undef __FUNCT__ 3871 #define __FUNCT__ "DMSetDS" 3872 /*@ 3873 DMSetDS - Set the PetscDS 3874 3875 Input Parameters: 3876 + dm - The DM 3877 - prob - The PetscDS 3878 3879 Level: developer 3880 3881 .seealso: DMGetDS() 3882 @*/ 3883 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3884 { 3885 PetscErrorCode ierr; 3886 3887 PetscFunctionBegin; 3888 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3889 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3890 ierr = PetscObjectReference((PetscObject) prob);CHKERRQ(ierr); 3891 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3892 dm->prob = prob; 3893 PetscFunctionReturn(0); 3894 } 3895 3896 #undef __FUNCT__ 3897 #define __FUNCT__ "DMGetNumFields" 3898 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3899 { 3900 PetscErrorCode ierr; 3901 3902 PetscFunctionBegin; 3903 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3904 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3905 PetscFunctionReturn(0); 3906 } 3907 3908 #undef __FUNCT__ 3909 #define __FUNCT__ "DMSetNumFields" 3910 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3911 { 3912 PetscInt Nf, f; 3913 PetscErrorCode ierr; 3914 3915 PetscFunctionBegin; 3916 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3917 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3918 for (f = Nf; f < numFields; ++f) { 3919 PetscContainer obj; 3920 3921 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3922 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3923 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3924 } 3925 PetscFunctionReturn(0); 3926 } 3927 3928 #undef __FUNCT__ 3929 #define __FUNCT__ "DMGetField" 3930 /*@ 3931 DMGetField - Return the discretization object for a given DM field 3932 3933 Not collective 3934 3935 Input Parameters: 3936 + dm - The DM 3937 - f - The field number 3938 3939 Output Parameter: 3940 . field - The discretization object 3941 3942 Level: developer 3943 3944 .seealso: DMSetField() 3945 @*/ 3946 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3947 { 3948 PetscErrorCode ierr; 3949 3950 PetscFunctionBegin; 3951 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3952 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3953 PetscFunctionReturn(0); 3954 } 3955 3956 #undef __FUNCT__ 3957 #define __FUNCT__ "DMSetField" 3958 /*@ 3959 DMSetField - Set the discretization object for a given DM field 3960 3961 Logically collective on DM 3962 3963 Input Parameters: 3964 + dm - The DM 3965 . f - The field number 3966 - field - The discretization object 3967 3968 Level: developer 3969 3970 .seealso: DMGetField() 3971 @*/ 3972 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3973 { 3974 PetscErrorCode ierr; 3975 3976 PetscFunctionBegin; 3977 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3978 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3979 PetscFunctionReturn(0); 3980 } 3981 3982 #undef __FUNCT__ 3983 #define __FUNCT__ "DMRestrictHook_Coordinates" 3984 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3985 { 3986 DM dm_coord,dmc_coord; 3987 PetscErrorCode ierr; 3988 Vec coords,ccoords; 3989 Mat inject; 3990 PetscFunctionBegin; 3991 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3992 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3993 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3994 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3995 if (coords && !ccoords) { 3996 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3997 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 3998 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 3999 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 4000 ierr = MatDestroy(&inject);CHKERRQ(ierr); 4001 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 4002 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4003 } 4004 PetscFunctionReturn(0); 4005 } 4006 4007 #undef __FUNCT__ 4008 #define __FUNCT__ "DMSubDomainHook_Coordinates" 4009 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 4010 { 4011 DM dm_coord,subdm_coord; 4012 PetscErrorCode ierr; 4013 Vec coords,ccoords,clcoords; 4014 VecScatter *scat_i,*scat_g; 4015 PetscFunctionBegin; 4016 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 4017 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 4018 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 4019 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 4020 if (coords && !ccoords) { 4021 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 4022 ierr = PetscObjectSetName((PetscObject)ccoords,"coordinates");CHKERRQ(ierr); 4023 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 4024 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 4025 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 4026 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4027 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4028 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4029 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4030 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 4031 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 4032 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 4033 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 4034 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4035 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 4036 ierr = PetscFree(scat_i);CHKERRQ(ierr); 4037 ierr = PetscFree(scat_g);CHKERRQ(ierr); 4038 } 4039 PetscFunctionReturn(0); 4040 } 4041 4042 #undef __FUNCT__ 4043 #define __FUNCT__ "DMGetDimension" 4044 /*@ 4045 DMGetDimension - Return the topological dimension of the DM 4046 4047 Not collective 4048 4049 Input Parameter: 4050 . dm - The DM 4051 4052 Output Parameter: 4053 . dim - The topological dimension 4054 4055 Level: beginner 4056 4057 .seealso: DMSetDimension(), DMCreate() 4058 @*/ 4059 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 4060 { 4061 PetscFunctionBegin; 4062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4063 PetscValidPointer(dim, 2); 4064 *dim = dm->dim; 4065 PetscFunctionReturn(0); 4066 } 4067 4068 #undef __FUNCT__ 4069 #define __FUNCT__ "DMSetDimension" 4070 /*@ 4071 DMSetDimension - Set the topological dimension of the DM 4072 4073 Collective on dm 4074 4075 Input Parameters: 4076 + dm - The DM 4077 - dim - The topological dimension 4078 4079 Level: beginner 4080 4081 .seealso: DMGetDimension(), DMCreate() 4082 @*/ 4083 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 4084 { 4085 PetscFunctionBegin; 4086 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4087 PetscValidLogicalCollectiveInt(dm, dim, 2); 4088 dm->dim = dim; 4089 PetscFunctionReturn(0); 4090 } 4091 4092 #undef __FUNCT__ 4093 #define __FUNCT__ "DMGetDimPoints" 4094 /*@ 4095 DMGetDimPoints - Get the half-open interval for all points of a given dimension 4096 4097 Collective on DM 4098 4099 Input Parameters: 4100 + dm - the DM 4101 - dim - the dimension 4102 4103 Output Parameters: 4104 + pStart - The first point of the given dimension 4105 . pEnd - The first point following points of the given dimension 4106 4107 Note: 4108 The points are vertices in the Hasse diagram encoding the topology. This is explained in 4109 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 4110 then the interval is empty. 4111 4112 Level: intermediate 4113 4114 .keywords: point, Hasse Diagram, dimension 4115 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 4116 @*/ 4117 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4118 { 4119 PetscInt d; 4120 PetscErrorCode ierr; 4121 4122 PetscFunctionBegin; 4123 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4124 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 4125 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 4126 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 4127 PetscFunctionReturn(0); 4128 } 4129 4130 #undef __FUNCT__ 4131 #define __FUNCT__ "DMSetCoordinates" 4132 /*@ 4133 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 4134 4135 Collective on DM 4136 4137 Input Parameters: 4138 + dm - the DM 4139 - c - coordinate vector 4140 4141 Note: 4142 The coordinates do include those for ghost points, which are in the local vector 4143 4144 Level: intermediate 4145 4146 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4147 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 4148 @*/ 4149 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 4150 { 4151 PetscErrorCode ierr; 4152 4153 PetscFunctionBegin; 4154 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4155 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4156 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4157 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4158 dm->coordinates = c; 4159 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4160 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4161 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4162 PetscFunctionReturn(0); 4163 } 4164 4165 #undef __FUNCT__ 4166 #define __FUNCT__ "DMSetCoordinatesLocal" 4167 /*@ 4168 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 4169 4170 Collective on DM 4171 4172 Input Parameters: 4173 + dm - the DM 4174 - c - coordinate vector 4175 4176 Note: 4177 The coordinates of ghost points can be set using DMSetCoordinates() 4178 followed by DMGetCoordinatesLocal(). This is intended to enable the 4179 setting of ghost coordinates outside of the domain. 4180 4181 Level: intermediate 4182 4183 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4184 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 4185 @*/ 4186 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 4187 { 4188 PetscErrorCode ierr; 4189 4190 PetscFunctionBegin; 4191 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4192 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4193 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4194 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4195 4196 dm->coordinatesLocal = c; 4197 4198 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4199 PetscFunctionReturn(0); 4200 } 4201 4202 #undef __FUNCT__ 4203 #define __FUNCT__ "DMGetCoordinates" 4204 /*@ 4205 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 4206 4207 Not Collective 4208 4209 Input Parameter: 4210 . dm - the DM 4211 4212 Output Parameter: 4213 . c - global coordinate vector 4214 4215 Note: 4216 This is a borrowed reference, so the user should NOT destroy this vector 4217 4218 Each process has only the local coordinates (does NOT have the ghost coordinates). 4219 4220 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4221 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4222 4223 Level: intermediate 4224 4225 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4226 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4227 @*/ 4228 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4229 { 4230 PetscErrorCode ierr; 4231 4232 PetscFunctionBegin; 4233 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4234 PetscValidPointer(c,2); 4235 if (!dm->coordinates && dm->coordinatesLocal) { 4236 DM cdm = NULL; 4237 4238 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4239 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4240 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4241 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4242 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4243 } 4244 *c = dm->coordinates; 4245 PetscFunctionReturn(0); 4246 } 4247 4248 #undef __FUNCT__ 4249 #define __FUNCT__ "DMGetCoordinatesLocal" 4250 /*@ 4251 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4252 4253 Collective on DM 4254 4255 Input Parameter: 4256 . dm - the DM 4257 4258 Output Parameter: 4259 . c - coordinate vector 4260 4261 Note: 4262 This is a borrowed reference, so the user should NOT destroy this vector 4263 4264 Each process has the local and ghost coordinates 4265 4266 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4267 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4268 4269 Level: intermediate 4270 4271 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4272 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4273 @*/ 4274 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4275 { 4276 PetscErrorCode ierr; 4277 4278 PetscFunctionBegin; 4279 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4280 PetscValidPointer(c,2); 4281 if (!dm->coordinatesLocal && dm->coordinates) { 4282 DM cdm = NULL; 4283 4284 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4285 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4286 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4287 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4288 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4289 } 4290 *c = dm->coordinatesLocal; 4291 PetscFunctionReturn(0); 4292 } 4293 4294 #undef __FUNCT__ 4295 #define __FUNCT__ "DMGetCoordinateDM" 4296 /*@ 4297 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4298 4299 Collective on DM 4300 4301 Input Parameter: 4302 . dm - the DM 4303 4304 Output Parameter: 4305 . cdm - coordinate DM 4306 4307 Level: intermediate 4308 4309 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4310 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4311 @*/ 4312 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4313 { 4314 PetscErrorCode ierr; 4315 4316 PetscFunctionBegin; 4317 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4318 PetscValidPointer(cdm,2); 4319 if (!dm->coordinateDM) { 4320 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4321 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 4322 } 4323 *cdm = dm->coordinateDM; 4324 PetscFunctionReturn(0); 4325 } 4326 4327 #undef __FUNCT__ 4328 #define __FUNCT__ "DMSetCoordinateDM" 4329 /*@ 4330 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4331 4332 Logically Collective on DM 4333 4334 Input Parameters: 4335 + dm - the DM 4336 - cdm - coordinate DM 4337 4338 Level: intermediate 4339 4340 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4341 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4342 @*/ 4343 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4344 { 4345 PetscErrorCode ierr; 4346 4347 PetscFunctionBegin; 4348 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4349 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4350 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 4351 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4352 dm->coordinateDM = cdm; 4353 PetscFunctionReturn(0); 4354 } 4355 4356 #undef __FUNCT__ 4357 #define __FUNCT__ "DMGetCoordinateDim" 4358 /*@ 4359 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4360 4361 Not Collective 4362 4363 Input Parameter: 4364 . dm - The DM object 4365 4366 Output Parameter: 4367 . dim - The embedding dimension 4368 4369 Level: intermediate 4370 4371 .keywords: mesh, coordinates 4372 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4373 @*/ 4374 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4375 { 4376 PetscFunctionBegin; 4377 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4378 PetscValidPointer(dim, 2); 4379 if (dm->dimEmbed == PETSC_DEFAULT) { 4380 dm->dimEmbed = dm->dim; 4381 } 4382 *dim = dm->dimEmbed; 4383 PetscFunctionReturn(0); 4384 } 4385 4386 #undef __FUNCT__ 4387 #define __FUNCT__ "DMSetCoordinateDim" 4388 /*@ 4389 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4390 4391 Not Collective 4392 4393 Input Parameters: 4394 + dm - The DM object 4395 - dim - The embedding dimension 4396 4397 Level: intermediate 4398 4399 .keywords: mesh, coordinates 4400 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4401 @*/ 4402 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4403 { 4404 PetscFunctionBegin; 4405 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4406 dm->dimEmbed = dim; 4407 PetscFunctionReturn(0); 4408 } 4409 4410 #undef __FUNCT__ 4411 #define __FUNCT__ "DMGetCoordinateSection" 4412 /*@ 4413 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4414 4415 Not Collective 4416 4417 Input Parameter: 4418 . dm - The DM object 4419 4420 Output Parameter: 4421 . section - The PetscSection object 4422 4423 Level: intermediate 4424 4425 .keywords: mesh, coordinates 4426 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4427 @*/ 4428 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4429 { 4430 DM cdm; 4431 PetscErrorCode ierr; 4432 4433 PetscFunctionBegin; 4434 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4435 PetscValidPointer(section, 2); 4436 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4437 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4438 PetscFunctionReturn(0); 4439 } 4440 4441 #undef __FUNCT__ 4442 #define __FUNCT__ "DMSetCoordinateSection" 4443 /*@ 4444 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4445 4446 Not Collective 4447 4448 Input Parameters: 4449 + dm - The DM object 4450 . dim - The embedding dimension, or PETSC_DETERMINE 4451 - section - The PetscSection object 4452 4453 Level: intermediate 4454 4455 .keywords: mesh, coordinates 4456 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4457 @*/ 4458 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4459 { 4460 DM cdm; 4461 PetscErrorCode ierr; 4462 4463 PetscFunctionBegin; 4464 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4465 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4466 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4467 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4468 if (dim == PETSC_DETERMINE) { 4469 PetscInt d = dim; 4470 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4471 4472 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4473 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4474 pStart = PetscMax(vStart, pStart); 4475 pEnd = PetscMin(vEnd, pEnd); 4476 for (v = pStart; v < pEnd; ++v) { 4477 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4478 if (dd) {d = dd; break;} 4479 } 4480 if (d < 0) d = PETSC_DEFAULT; 4481 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4482 } 4483 PetscFunctionReturn(0); 4484 } 4485 4486 #undef __FUNCT__ 4487 #define __FUNCT__ "DMGetPeriodicity" 4488 /*@C 4489 DMSetPeriodicity - Set the description of mesh periodicity 4490 4491 Input Parameters: 4492 + dm - The DM object 4493 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4494 . L - If we assume the mesh is a torus, this is the length of each coordinate 4495 - bd - This describes the type of periodicity in each topological dimension 4496 4497 Level: developer 4498 4499 .seealso: DMGetPeriodicity() 4500 @*/ 4501 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4502 { 4503 PetscFunctionBegin; 4504 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4505 if (L) *L = dm->L; 4506 if (maxCell) *maxCell = dm->maxCell; 4507 if (bd) *bd = dm->bdtype; 4508 PetscFunctionReturn(0); 4509 } 4510 4511 #undef __FUNCT__ 4512 #define __FUNCT__ "DMSetPeriodicity" 4513 /*@C 4514 DMSetPeriodicity - Set the description of mesh periodicity 4515 4516 Input Parameters: 4517 + dm - The DM object 4518 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4519 . L - If we assume the mesh is a torus, this is the length of each coordinate 4520 - bd - This describes the type of periodicity in each topological dimension 4521 4522 Level: developer 4523 4524 .seealso: DMGetPeriodicity() 4525 @*/ 4526 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4527 { 4528 PetscInt dim, d; 4529 PetscErrorCode ierr; 4530 4531 PetscFunctionBegin; 4532 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4533 PetscValidPointer(L,3);PetscValidPointer(maxCell,2);PetscValidPointer(bd,4); 4534 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4535 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4536 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4537 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4538 PetscFunctionReturn(0); 4539 } 4540 4541 #undef __FUNCT__ 4542 #define __FUNCT__ "DMLocalizeCoordinate" 4543 /*@ 4544 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. 4545 4546 Input Parameters: 4547 + dm - The DM 4548 - in - The input coordinate point (dim numbers) 4549 4550 Output Parameter: 4551 . out - The localized coordinate point 4552 4553 Level: developer 4554 4555 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4556 @*/ 4557 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscScalar out[]) 4558 { 4559 PetscInt dim, d; 4560 PetscErrorCode ierr; 4561 4562 PetscFunctionBegin; 4563 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 4564 if (!dm->maxCell) { 4565 for (d = 0; d < dim; ++d) out[d] = in[d]; 4566 } else { 4567 for (d = 0; d < dim; ++d) { 4568 out[d] = in[d] - dm->L[d]*floor(PetscRealPart(in[d])/dm->L[d]); 4569 } 4570 } 4571 PetscFunctionReturn(0); 4572 } 4573 4574 #undef __FUNCT__ 4575 #define __FUNCT__ "DMLocalizeCoordinate_Internal" 4576 /* 4577 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. 4578 4579 Input Parameters: 4580 + dm - The DM 4581 . dim - The spatial dimension 4582 . anchor - The anchor point, the input point can be no more than maxCell away from it 4583 - in - The input coordinate point (dim numbers) 4584 4585 Output Parameter: 4586 . out - The localized coordinate point 4587 4588 Level: developer 4589 4590 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 4591 4592 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4593 */ 4594 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4595 { 4596 PetscInt d; 4597 4598 PetscFunctionBegin; 4599 if (!dm->maxCell) { 4600 for (d = 0; d < dim; ++d) out[d] = in[d]; 4601 } else { 4602 for (d = 0; d < dim; ++d) { 4603 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 4604 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4605 } else { 4606 out[d] = in[d]; 4607 } 4608 } 4609 } 4610 PetscFunctionReturn(0); 4611 } 4612 #undef __FUNCT__ 4613 #define __FUNCT__ "DMLocalizeCoordinateReal_Internal" 4614 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 4615 { 4616 PetscInt d; 4617 4618 PetscFunctionBegin; 4619 if (!dm->maxCell) { 4620 for (d = 0; d < dim; ++d) out[d] = in[d]; 4621 } else { 4622 for (d = 0; d < dim; ++d) { 4623 if (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d]) { 4624 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4625 } else { 4626 out[d] = in[d]; 4627 } 4628 } 4629 } 4630 PetscFunctionReturn(0); 4631 } 4632 4633 #undef __FUNCT__ 4634 #define __FUNCT__ "DMLocalizeAddCoordinate_Internal" 4635 /* 4636 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. 4637 4638 Input Parameters: 4639 + dm - The DM 4640 . dim - The spatial dimension 4641 . anchor - The anchor point, the input point can be no more than maxCell away from it 4642 . in - The input coordinate delta (dim numbers) 4643 - out - The input coordinate point (dim numbers) 4644 4645 Output Parameter: 4646 . out - The localized coordinate in + out 4647 4648 Level: developer 4649 4650 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 4651 4652 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 4653 */ 4654 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4655 { 4656 PetscInt d; 4657 4658 PetscFunctionBegin; 4659 if (!dm->maxCell) { 4660 for (d = 0; d < dim; ++d) out[d] += in[d]; 4661 } else { 4662 for (d = 0; d < dim; ++d) { 4663 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 4664 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4665 } else { 4666 out[d] += in[d]; 4667 } 4668 } 4669 } 4670 PetscFunctionReturn(0); 4671 } 4672 4673 PETSC_EXTERN PetscErrorCode DMPlexGetDepthStratum(DM, PetscInt, PetscInt *, PetscInt *); 4674 PETSC_EXTERN PetscErrorCode DMPlexGetHeightStratum(DM, PetscInt, PetscInt *, PetscInt *); 4675 PETSC_EXTERN PetscErrorCode DMPlexVecGetClosure(DM, PetscSection, Vec, PetscInt, PetscInt *, PetscScalar *[]); 4676 PETSC_EXTERN PetscErrorCode DMPlexVecRestoreClosure(DM, PetscSection, Vec, PetscInt, PetscInt *, PetscScalar *[]); 4677 4678 #undef __FUNCT__ 4679 #define __FUNCT__ "DMGetCoordinatesLocalized" 4680 /*@ 4681 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 4682 4683 Input Parameter: 4684 . dm - The DM 4685 4686 Output Parameter: 4687 areLocalized - True if localized 4688 4689 Level: developer 4690 4691 .seealso: DMLocalizeCoordinates() 4692 @*/ 4693 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 4694 { 4695 DM cdm; 4696 PetscSection coordSection; 4697 PetscInt cStart, cEnd, c, sStart, sEnd, dof; 4698 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4699 PetscErrorCode ierr; 4700 4701 PetscFunctionBegin; 4702 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4703 if (!dm->maxCell) { 4704 *areLocalized = PETSC_FALSE; 4705 PetscFunctionReturn(0); 4706 } 4707 /* We need some generic way of refering to cells/vertices */ 4708 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4709 { 4710 PetscBool isplex; 4711 4712 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4713 if (isplex) { 4714 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4715 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4716 } 4717 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4718 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4719 alreadyLocalized = alreadyLocalizedGlobal = PETSC_FALSE; 4720 for (c = cStart; c < cEnd; ++c) { 4721 if (c < sStart || c >= sEnd) { 4722 alreadyLocalized = PETSC_FALSE; 4723 break; 4724 } 4725 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 4726 if (dof) { 4727 alreadyLocalized = PETSC_TRUE; 4728 break; 4729 } 4730 } 4731 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4732 *areLocalized = alreadyLocalizedGlobal; 4733 PetscFunctionReturn(0); 4734 } 4735 4736 4737 #undef __FUNCT__ 4738 #define __FUNCT__ "DMLocalizeCoordinates" 4739 /*@ 4740 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for each cell 4741 4742 Input Parameter: 4743 . dm - The DM 4744 4745 Level: developer 4746 4747 .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 4748 @*/ 4749 PetscErrorCode DMLocalizeCoordinates(DM dm) 4750 { 4751 DM cdm; 4752 PetscSection coordSection, cSection; 4753 Vec coordinates, cVec; 4754 PetscScalar *coords, *coords2, *anchor, *localized; 4755 PetscInt Nc, vStart, vEnd, v, sStart, sEnd, newStart = PETSC_MAX_INT, newEnd = PETSC_MIN_INT, dof, d, off, off2, bs, coordSize; 4756 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4757 PetscInt maxHeight = 0, h; 4758 PetscInt *pStart = NULL, *pEnd = NULL; 4759 PetscErrorCode ierr; 4760 4761 PetscFunctionBegin; 4762 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4763 if (!dm->maxCell) PetscFunctionReturn(0); 4764 /* We need some generic way of refering to cells/vertices */ 4765 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4766 { 4767 PetscBool isplex; 4768 4769 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4770 if (isplex) { 4771 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4772 ierr = DMPlexGetMaxProjectionHeight(cdm,&maxHeight);CHKERRQ(ierr); 4773 ierr = DMGetWorkArray(dm,2*(maxHeight + 1),PETSC_INT,&pStart);CHKERRQ(ierr); 4774 pEnd = &pStart[maxHeight + 1]; 4775 newStart = vStart; 4776 newEnd = vEnd; 4777 for (h = 0; h <= maxHeight; h++) { 4778 ierr = DMPlexGetHeightStratum(cdm, h, &pStart[h], &pEnd[h]);CHKERRQ(ierr); 4779 newStart = PetscMin(newStart,pStart[h]); 4780 newEnd = PetscMax(newEnd,pEnd[h]); 4781 } 4782 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4783 } 4784 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4785 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4786 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 4787 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4788 4789 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 4790 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 4791 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 4792 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 4793 ierr = PetscSectionSetChart(cSection, newStart, newEnd);CHKERRQ(ierr); 4794 4795 ierr = DMGetWorkArray(dm, 2 * bs, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 4796 localized = &anchor[bs]; 4797 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 4798 for (h = 0; h <= maxHeight; h++) { 4799 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 4800 4801 for (c = cStart; c < cEnd; ++c) { 4802 PetscScalar *cellCoords = NULL; 4803 PetscInt b; 4804 4805 if (c < sStart || c >= sEnd) alreadyLocalized = PETSC_FALSE; 4806 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4807 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4808 for (d = 0; d < dof/bs; ++d) { 4809 ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], localized);CHKERRQ(ierr); 4810 for (b = 0; b < bs; b++) { 4811 if (cellCoords[d*bs + b] != localized[b]) break; 4812 } 4813 if (b < bs) break; 4814 } 4815 if (d < dof/bs) { 4816 if (c >= sStart && c < sEnd) { 4817 PetscInt cdof; 4818 4819 ierr = PetscSectionGetDof(coordSection, c, &cdof);CHKERRQ(ierr); 4820 if (cdof != dof) alreadyLocalized = PETSC_FALSE; 4821 } 4822 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 4823 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 4824 } 4825 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4826 } 4827 } 4828 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4829 if (alreadyLocalizedGlobal) { 4830 ierr = DMRestoreWorkArray(dm, 2 * bs, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 4831 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4832 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),PETSC_INT,&pStart);CHKERRQ(ierr); 4833 PetscFunctionReturn(0); 4834 } 4835 for (v = vStart; v < vEnd; ++v) { 4836 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4837 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 4838 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 4839 } 4840 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 4841 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 4842 ierr = VecCreate(PETSC_COMM_SELF, &cVec);CHKERRQ(ierr); 4843 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 4844 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 4845 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4846 ierr = VecSetType(cVec, VECSTANDARD);CHKERRQ(ierr); 4847 ierr = VecGetArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 4848 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 4849 for (v = vStart; v < vEnd; ++v) { 4850 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4851 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4852 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 4853 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 4854 } 4855 for (h = 0; h <= maxHeight; h++) { 4856 PetscInt cStart = pStart[h], cEnd = pEnd[h], c; 4857 4858 for (c = cStart; c < cEnd; ++c) { 4859 PetscScalar *cellCoords = NULL; 4860 PetscInt b, cdof; 4861 4862 ierr = PetscSectionGetDof(cSection,c,&cdof);CHKERRQ(ierr); 4863 if (!cdof) continue; 4864 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4865 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 4866 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4867 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 4868 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4869 } 4870 } 4871 ierr = DMRestoreWorkArray(dm, 2 * bs, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 4872 ierr = DMRestoreWorkArray(dm,2*(maxHeight + 1),PETSC_INT,&pStart);CHKERRQ(ierr); 4873 ierr = VecRestoreArrayRead(coordinates, (const PetscScalar**)&coords);CHKERRQ(ierr); 4874 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 4875 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 4876 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 4877 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 4878 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4879 PetscFunctionReturn(0); 4880 } 4881 4882 #undef __FUNCT__ 4883 #define __FUNCT__ "DMLocatePoints" 4884 /*@ 4885 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 4886 4887 Collective on Vec v (see explanation below) 4888 4889 Input Parameters: 4890 + dm - The DM 4891 . v - The Vec of points 4892 . ltype - The type of point location, e.g. DM_POINTLOCATION_NONE or DM_POINTLOCATION_NEAREST 4893 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 4894 4895 Output Parameter: 4896 + v - The Vec of points, which now contains the nearest mesh points to the given points if DM_POINTLOCATION_NEAREST is used 4897 - cells - The PetscSF containing the ranks and local indices of the containing points. 4898 4899 4900 Level: developer 4901 4902 Notes: 4903 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 4904 To do a search of all the cells in the distributed mesh, v should have the same communicator as dm. 4905 4906 If *cellSF is NULL on input, a PetscSF will be created. 4907 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial guesses. 4908 4909 An array that maps each point to its containing cell can be obtained with 4910 4911 $ const PetscSFNode *cells; 4912 $ PetscInt nFound; 4913 $ const PetscSFNode *found; 4914 $ 4915 $ PetscSFGetGraph(cells,NULL,&nFound,&found,&cells); 4916 4917 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 4918 the index of the cell in its rank's local numbering. 4919 4920 .keywords: point location, mesh 4921 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMPointLocationType 4922 @*/ 4923 PetscErrorCode DMLocatePoints(DM dm, Vec v, DMPointLocationType ltype, PetscSF *cellSF) 4924 { 4925 PetscErrorCode ierr; 4926 4927 PetscFunctionBegin; 4928 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4929 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4930 PetscValidPointer(cellSF,4); 4931 if (*cellSF) { 4932 PetscMPIInt result; 4933 4934 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 4935 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)cellSF),&result);CHKERRQ(ierr); 4936 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 4937 } else { 4938 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 4939 } 4940 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4941 if (dm->ops->locatepoints) { 4942 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 4943 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4944 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4945 PetscFunctionReturn(0); 4946 } 4947 4948 #undef __FUNCT__ 4949 #define __FUNCT__ "DMGetOutputDM" 4950 /*@ 4951 DMGetOutputDM - Retrieve the DM associated with the layout for output 4952 4953 Input Parameter: 4954 . dm - The original DM 4955 4956 Output Parameter: 4957 . odm - The DM which provides the layout for output 4958 4959 Level: intermediate 4960 4961 .seealso: VecView(), DMGetDefaultGlobalSection() 4962 @*/ 4963 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4964 { 4965 PetscSection section; 4966 PetscBool hasConstraints, ghasConstraints; 4967 PetscErrorCode ierr; 4968 4969 PetscFunctionBegin; 4970 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4971 PetscValidPointer(odm,2); 4972 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4973 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4974 ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 4975 if (!ghasConstraints) { 4976 *odm = dm; 4977 PetscFunctionReturn(0); 4978 } 4979 if (!dm->dmBC) { 4980 PetscDS ds; 4981 PetscSection newSection, gsection; 4982 PetscSF sf; 4983 4984 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4985 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 4986 ierr = DMSetDS(dm->dmBC, ds);CHKERRQ(ierr); 4987 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4988 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4989 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4990 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4991 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 4992 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4993 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4994 } 4995 *odm = dm->dmBC; 4996 PetscFunctionReturn(0); 4997 } 4998 4999 #undef __FUNCT__ 5000 #define __FUNCT__ "DMGetOutputSequenceNumber" 5001 /*@ 5002 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 5003 5004 Input Parameter: 5005 . dm - The original DM 5006 5007 Output Parameters: 5008 + num - The output sequence number 5009 - val - The output sequence value 5010 5011 Level: intermediate 5012 5013 Note: This is intended for output that should appear in sequence, for instance 5014 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5015 5016 .seealso: VecView() 5017 @*/ 5018 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 5019 { 5020 PetscFunctionBegin; 5021 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5022 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 5023 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 5024 PetscFunctionReturn(0); 5025 } 5026 5027 #undef __FUNCT__ 5028 #define __FUNCT__ "DMSetOutputSequenceNumber" 5029 /*@ 5030 DMSetOutputSequenceNumber - Set the sequence number/value for output 5031 5032 Input Parameters: 5033 + dm - The original DM 5034 . num - The output sequence number 5035 - val - The output sequence value 5036 5037 Level: intermediate 5038 5039 Note: This is intended for output that should appear in sequence, for instance 5040 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5041 5042 .seealso: VecView() 5043 @*/ 5044 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 5045 { 5046 PetscFunctionBegin; 5047 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5048 dm->outputSequenceNum = num; 5049 dm->outputSequenceVal = val; 5050 PetscFunctionReturn(0); 5051 } 5052 5053 #undef __FUNCT__ 5054 #define __FUNCT__ "DMOutputSequenceLoad" 5055 /*@C 5056 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 5057 5058 Input Parameters: 5059 + dm - The original DM 5060 . name - The sequence name 5061 - num - The output sequence number 5062 5063 Output Parameter: 5064 . val - The output sequence value 5065 5066 Level: intermediate 5067 5068 Note: This is intended for output that should appear in sequence, for instance 5069 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5070 5071 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 5072 @*/ 5073 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 5074 { 5075 PetscBool ishdf5; 5076 PetscErrorCode ierr; 5077 5078 PetscFunctionBegin; 5079 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5080 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 5081 PetscValidPointer(val,4); 5082 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 5083 if (ishdf5) { 5084 #if defined(PETSC_HAVE_HDF5) 5085 PetscScalar value; 5086 5087 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 5088 *val = PetscRealPart(value); 5089 #endif 5090 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 5091 PetscFunctionReturn(0); 5092 } 5093 5094 #undef __FUNCT__ 5095 #define __FUNCT__ "DMGetUseNatural" 5096 /*@ 5097 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 5098 5099 Not collective 5100 5101 Input Parameter: 5102 . dm - The DM 5103 5104 Output Parameter: 5105 . useNatural - The flag to build the mapping to a natural order during distribution 5106 5107 Level: beginner 5108 5109 .seealso: DMSetUseNatural(), DMCreate() 5110 @*/ 5111 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 5112 { 5113 PetscFunctionBegin; 5114 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5115 PetscValidPointer(useNatural, 2); 5116 *useNatural = dm->useNatural; 5117 PetscFunctionReturn(0); 5118 } 5119 5120 #undef __FUNCT__ 5121 #define __FUNCT__ "DMSetUseNatural" 5122 /*@ 5123 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 5124 5125 Collective on dm 5126 5127 Input Parameters: 5128 + dm - The DM 5129 - useNatural - The flag to build the mapping to a natural order during distribution 5130 5131 Level: beginner 5132 5133 .seealso: DMGetUseNatural(), DMCreate() 5134 @*/ 5135 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 5136 { 5137 PetscFunctionBegin; 5138 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5139 PetscValidLogicalCollectiveInt(dm, useNatural, 2); 5140 dm->useNatural = useNatural; 5141 PetscFunctionReturn(0); 5142 } 5143 5144 #undef __FUNCT__ 5145 #define __FUNCT__ 5146 5147 #undef __FUNCT__ 5148 #define __FUNCT__ "DMCreateLabel" 5149 /*@C 5150 DMCreateLabel - Create a label of the given name if it does not already exist 5151 5152 Not Collective 5153 5154 Input Parameters: 5155 + dm - The DM object 5156 - name - The label name 5157 5158 Level: intermediate 5159 5160 .keywords: mesh 5161 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5162 @*/ 5163 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 5164 { 5165 DMLabelLink next = dm->labels->next; 5166 PetscBool flg = PETSC_FALSE; 5167 PetscErrorCode ierr; 5168 5169 PetscFunctionBegin; 5170 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5171 PetscValidCharPointer(name, 2); 5172 while (next) { 5173 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5174 if (flg) break; 5175 next = next->next; 5176 } 5177 if (!flg) { 5178 DMLabelLink tmpLabel; 5179 5180 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5181 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 5182 tmpLabel->output = PETSC_TRUE; 5183 tmpLabel->next = dm->labels->next; 5184 dm->labels->next = tmpLabel; 5185 } 5186 PetscFunctionReturn(0); 5187 } 5188 5189 #undef __FUNCT__ 5190 #define __FUNCT__ "DMGetLabelValue" 5191 /*@C 5192 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 5193 5194 Not Collective 5195 5196 Input Parameters: 5197 + dm - The DM object 5198 . name - The label name 5199 - point - The mesh point 5200 5201 Output Parameter: 5202 . value - The label value for this point, or -1 if the point is not in the label 5203 5204 Level: beginner 5205 5206 .keywords: mesh 5207 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 5208 @*/ 5209 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 5210 { 5211 DMLabel label; 5212 PetscErrorCode ierr; 5213 5214 PetscFunctionBegin; 5215 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5216 PetscValidCharPointer(name, 2); 5217 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5218 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);CHKERRQ(ierr); 5219 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5220 PetscFunctionReturn(0); 5221 } 5222 5223 #undef __FUNCT__ 5224 #define __FUNCT__ "DMSetLabelValue" 5225 /*@C 5226 DMSetLabelValue - Add a point to a Sieve Label with given value 5227 5228 Not Collective 5229 5230 Input Parameters: 5231 + dm - The DM object 5232 . name - The label name 5233 . point - The mesh point 5234 - value - The label value for this point 5235 5236 Output Parameter: 5237 5238 Level: beginner 5239 5240 .keywords: mesh 5241 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5242 @*/ 5243 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5244 { 5245 DMLabel label; 5246 PetscErrorCode ierr; 5247 5248 PetscFunctionBegin; 5249 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5250 PetscValidCharPointer(name, 2); 5251 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5252 if (!label) { 5253 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5254 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5255 } 5256 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5257 PetscFunctionReturn(0); 5258 } 5259 5260 #undef __FUNCT__ 5261 #define __FUNCT__ "DMClearLabelValue" 5262 /*@C 5263 DMClearLabelValue - Remove a point from a Sieve Label with given value 5264 5265 Not Collective 5266 5267 Input Parameters: 5268 + dm - The DM object 5269 . name - The label name 5270 . point - The mesh point 5271 - value - The label value for this point 5272 5273 Output Parameter: 5274 5275 Level: beginner 5276 5277 .keywords: mesh 5278 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5279 @*/ 5280 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5281 { 5282 DMLabel label; 5283 PetscErrorCode ierr; 5284 5285 PetscFunctionBegin; 5286 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5287 PetscValidCharPointer(name, 2); 5288 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5289 if (!label) PetscFunctionReturn(0); 5290 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5291 PetscFunctionReturn(0); 5292 } 5293 5294 #undef __FUNCT__ 5295 #define __FUNCT__ "DMGetLabelSize" 5296 /*@C 5297 DMGetLabelSize - Get the number of different integer ids in a Label 5298 5299 Not Collective 5300 5301 Input Parameters: 5302 + dm - The DM object 5303 - name - The label name 5304 5305 Output Parameter: 5306 . size - The number of different integer ids, or 0 if the label does not exist 5307 5308 Level: beginner 5309 5310 .keywords: mesh 5311 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 5312 @*/ 5313 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5314 { 5315 DMLabel label; 5316 PetscErrorCode ierr; 5317 5318 PetscFunctionBegin; 5319 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5320 PetscValidCharPointer(name, 2); 5321 PetscValidPointer(size, 3); 5322 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5323 *size = 0; 5324 if (!label) PetscFunctionReturn(0); 5325 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5326 PetscFunctionReturn(0); 5327 } 5328 5329 #undef __FUNCT__ 5330 #define __FUNCT__ "DMGetLabelIdIS" 5331 /*@C 5332 DMGetLabelIdIS - Get the integer ids in a label 5333 5334 Not Collective 5335 5336 Input Parameters: 5337 + mesh - The DM object 5338 - name - The label name 5339 5340 Output Parameter: 5341 . ids - The integer ids, or NULL if the label does not exist 5342 5343 Level: beginner 5344 5345 .keywords: mesh 5346 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5347 @*/ 5348 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5349 { 5350 DMLabel label; 5351 PetscErrorCode ierr; 5352 5353 PetscFunctionBegin; 5354 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5355 PetscValidCharPointer(name, 2); 5356 PetscValidPointer(ids, 3); 5357 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5358 *ids = NULL; 5359 if (!label) PetscFunctionReturn(0); 5360 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5361 PetscFunctionReturn(0); 5362 } 5363 5364 #undef __FUNCT__ 5365 #define __FUNCT__ "DMGetStratumSize" 5366 /*@C 5367 DMGetStratumSize - Get the number of points in a label stratum 5368 5369 Not Collective 5370 5371 Input Parameters: 5372 + dm - The DM object 5373 . name - The label name 5374 - value - The stratum value 5375 5376 Output Parameter: 5377 . size - The stratum size 5378 5379 Level: beginner 5380 5381 .keywords: mesh 5382 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5383 @*/ 5384 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5385 { 5386 DMLabel label; 5387 PetscErrorCode ierr; 5388 5389 PetscFunctionBegin; 5390 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5391 PetscValidCharPointer(name, 2); 5392 PetscValidPointer(size, 4); 5393 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5394 *size = 0; 5395 if (!label) PetscFunctionReturn(0); 5396 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5397 PetscFunctionReturn(0); 5398 } 5399 5400 #undef __FUNCT__ 5401 #define __FUNCT__ "DMGetStratumIS" 5402 /*@C 5403 DMGetStratumIS - Get the points in a label stratum 5404 5405 Not Collective 5406 5407 Input Parameters: 5408 + dm - The DM object 5409 . name - The label name 5410 - value - The stratum value 5411 5412 Output Parameter: 5413 . points - The stratum points, or NULL if the label does not exist or does not have that value 5414 5415 Level: beginner 5416 5417 .keywords: mesh 5418 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5419 @*/ 5420 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5421 { 5422 DMLabel label; 5423 PetscErrorCode ierr; 5424 5425 PetscFunctionBegin; 5426 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5427 PetscValidCharPointer(name, 2); 5428 PetscValidPointer(points, 4); 5429 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5430 *points = NULL; 5431 if (!label) PetscFunctionReturn(0); 5432 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5433 PetscFunctionReturn(0); 5434 } 5435 5436 #undef __FUNCT__ 5437 #define __FUNCT__ "DMSetStratumIS" 5438 /*@C 5439 DMGetStratumIS - Set the points in a label stratum 5440 5441 Not Collective 5442 5443 Input Parameters: 5444 + dm - The DM object 5445 . name - The label name 5446 . value - The stratum value 5447 - points - The stratum points 5448 5449 Level: beginner 5450 5451 .keywords: mesh 5452 .seealso: DMLabelSetStratumIS(), DMGetStratumSize() 5453 @*/ 5454 PetscErrorCode DMSetStratumIS(DM dm, const char name[], PetscInt value, IS points) 5455 { 5456 DMLabel label; 5457 PetscErrorCode ierr; 5458 5459 PetscFunctionBegin; 5460 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5461 PetscValidCharPointer(name, 2); 5462 PetscValidPointer(points, 4); 5463 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5464 if (!label) PetscFunctionReturn(0); 5465 ierr = DMLabelSetStratumIS(label, value, points);CHKERRQ(ierr); 5466 PetscFunctionReturn(0); 5467 } 5468 5469 #undef __FUNCT__ 5470 #define __FUNCT__ "DMClearLabelStratum" 5471 /*@C 5472 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 5473 5474 Not Collective 5475 5476 Input Parameters: 5477 + dm - The DM object 5478 . name - The label name 5479 - value - The label value for this point 5480 5481 Output Parameter: 5482 5483 Level: beginner 5484 5485 .keywords: mesh 5486 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 5487 @*/ 5488 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 5489 { 5490 DMLabel label; 5491 PetscErrorCode ierr; 5492 5493 PetscFunctionBegin; 5494 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5495 PetscValidCharPointer(name, 2); 5496 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5497 if (!label) PetscFunctionReturn(0); 5498 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 5499 PetscFunctionReturn(0); 5500 } 5501 5502 #undef __FUNCT__ 5503 #define __FUNCT__ "DMGetNumLabels" 5504 /*@ 5505 DMGetNumLabels - Return the number of labels defined by the mesh 5506 5507 Not Collective 5508 5509 Input Parameter: 5510 . dm - The DM object 5511 5512 Output Parameter: 5513 . numLabels - the number of Labels 5514 5515 Level: intermediate 5516 5517 .keywords: mesh 5518 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5519 @*/ 5520 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 5521 { 5522 DMLabelLink next = dm->labels->next; 5523 PetscInt n = 0; 5524 5525 PetscFunctionBegin; 5526 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5527 PetscValidPointer(numLabels, 2); 5528 while (next) {++n; next = next->next;} 5529 *numLabels = n; 5530 PetscFunctionReturn(0); 5531 } 5532 5533 #undef __FUNCT__ 5534 #define __FUNCT__ "DMGetLabelName" 5535 /*@C 5536 DMGetLabelName - Return the name of nth label 5537 5538 Not Collective 5539 5540 Input Parameters: 5541 + dm - The DM object 5542 - n - the label number 5543 5544 Output Parameter: 5545 . name - the label name 5546 5547 Level: intermediate 5548 5549 .keywords: mesh 5550 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5551 @*/ 5552 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 5553 { 5554 DMLabelLink next = dm->labels->next; 5555 PetscInt l = 0; 5556 5557 PetscFunctionBegin; 5558 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5559 PetscValidPointer(name, 3); 5560 while (next) { 5561 if (l == n) { 5562 *name = next->label->name; 5563 PetscFunctionReturn(0); 5564 } 5565 ++l; 5566 next = next->next; 5567 } 5568 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5569 } 5570 5571 #undef __FUNCT__ 5572 #define __FUNCT__ "DMHasLabel" 5573 /*@C 5574 DMHasLabel - Determine whether the mesh has a label of a given name 5575 5576 Not Collective 5577 5578 Input Parameters: 5579 + dm - The DM object 5580 - name - The label name 5581 5582 Output Parameter: 5583 . hasLabel - PETSC_TRUE if the label is present 5584 5585 Level: intermediate 5586 5587 .keywords: mesh 5588 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5589 @*/ 5590 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 5591 { 5592 DMLabelLink next = dm->labels->next; 5593 PetscErrorCode ierr; 5594 5595 PetscFunctionBegin; 5596 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5597 PetscValidCharPointer(name, 2); 5598 PetscValidPointer(hasLabel, 3); 5599 *hasLabel = PETSC_FALSE; 5600 while (next) { 5601 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 5602 if (*hasLabel) break; 5603 next = next->next; 5604 } 5605 PetscFunctionReturn(0); 5606 } 5607 5608 #undef __FUNCT__ 5609 #define __FUNCT__ "DMGetLabel" 5610 /*@C 5611 DMGetLabel - Return the label of a given name, or NULL 5612 5613 Not Collective 5614 5615 Input Parameters: 5616 + dm - The DM object 5617 - name - The label name 5618 5619 Output Parameter: 5620 . label - The DMLabel, or NULL if the label is absent 5621 5622 Level: intermediate 5623 5624 .keywords: mesh 5625 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5626 @*/ 5627 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 5628 { 5629 DMLabelLink next = dm->labels->next; 5630 PetscBool hasLabel; 5631 PetscErrorCode ierr; 5632 5633 PetscFunctionBegin; 5634 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5635 PetscValidCharPointer(name, 2); 5636 PetscValidPointer(label, 3); 5637 *label = NULL; 5638 while (next) { 5639 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5640 if (hasLabel) { 5641 *label = next->label; 5642 break; 5643 } 5644 next = next->next; 5645 } 5646 PetscFunctionReturn(0); 5647 } 5648 5649 #undef __FUNCT__ 5650 #define __FUNCT__ "DMGetLabelByNum" 5651 /*@C 5652 DMGetLabelByNum - Return the nth label 5653 5654 Not Collective 5655 5656 Input Parameters: 5657 + dm - The DM object 5658 - n - the label number 5659 5660 Output Parameter: 5661 . label - the label 5662 5663 Level: intermediate 5664 5665 .keywords: mesh 5666 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5667 @*/ 5668 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5669 { 5670 DMLabelLink next = dm->labels->next; 5671 PetscInt l = 0; 5672 5673 PetscFunctionBegin; 5674 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5675 PetscValidPointer(label, 3); 5676 while (next) { 5677 if (l == n) { 5678 *label = next->label; 5679 PetscFunctionReturn(0); 5680 } 5681 ++l; 5682 next = next->next; 5683 } 5684 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5685 } 5686 5687 #undef __FUNCT__ 5688 #define __FUNCT__ "DMAddLabel" 5689 /*@C 5690 DMAddLabel - Add the label to this mesh 5691 5692 Not Collective 5693 5694 Input Parameters: 5695 + dm - The DM object 5696 - label - The DMLabel 5697 5698 Level: developer 5699 5700 .keywords: mesh 5701 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5702 @*/ 5703 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5704 { 5705 DMLabelLink tmpLabel; 5706 PetscBool hasLabel; 5707 PetscErrorCode ierr; 5708 5709 PetscFunctionBegin; 5710 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5711 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5712 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5713 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5714 tmpLabel->label = label; 5715 tmpLabel->output = PETSC_TRUE; 5716 tmpLabel->next = dm->labels->next; 5717 dm->labels->next = tmpLabel; 5718 PetscFunctionReturn(0); 5719 } 5720 5721 #undef __FUNCT__ 5722 #define __FUNCT__ "DMRemoveLabel" 5723 /*@C 5724 DMRemoveLabel - Remove the label from this mesh 5725 5726 Not Collective 5727 5728 Input Parameters: 5729 + dm - The DM object 5730 - name - The label name 5731 5732 Output Parameter: 5733 . label - The DMLabel, or NULL if the label is absent 5734 5735 Level: developer 5736 5737 .keywords: mesh 5738 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5739 @*/ 5740 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5741 { 5742 DMLabelLink next = dm->labels->next; 5743 DMLabelLink last = NULL; 5744 PetscBool hasLabel; 5745 PetscErrorCode ierr; 5746 5747 PetscFunctionBegin; 5748 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5749 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5750 *label = NULL; 5751 if (!hasLabel) PetscFunctionReturn(0); 5752 while (next) { 5753 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5754 if (hasLabel) { 5755 if (last) last->next = next->next; 5756 else dm->labels->next = next->next; 5757 next->next = NULL; 5758 *label = next->label; 5759 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5760 if (hasLabel) { 5761 dm->depthLabel = NULL; 5762 } 5763 ierr = PetscFree(next);CHKERRQ(ierr); 5764 break; 5765 } 5766 last = next; 5767 next = next->next; 5768 } 5769 PetscFunctionReturn(0); 5770 } 5771 5772 #undef __FUNCT__ 5773 #define __FUNCT__ "DMGetLabelOutput" 5774 /*@C 5775 DMGetLabelOutput - Get the output flag for a given label 5776 5777 Not Collective 5778 5779 Input Parameters: 5780 + dm - The DM object 5781 - name - The label name 5782 5783 Output Parameter: 5784 . output - The flag for output 5785 5786 Level: developer 5787 5788 .keywords: mesh 5789 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5790 @*/ 5791 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5792 { 5793 DMLabelLink next = dm->labels->next; 5794 PetscErrorCode ierr; 5795 5796 PetscFunctionBegin; 5797 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5798 PetscValidPointer(name, 2); 5799 PetscValidPointer(output, 3); 5800 while (next) { 5801 PetscBool flg; 5802 5803 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5804 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5805 next = next->next; 5806 } 5807 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5808 } 5809 5810 #undef __FUNCT__ 5811 #define __FUNCT__ "DMSetLabelOutput" 5812 /*@C 5813 DMSetLabelOutput - Set the output flag for a given label 5814 5815 Not Collective 5816 5817 Input Parameters: 5818 + dm - The DM object 5819 . name - The label name 5820 - output - The flag for output 5821 5822 Level: developer 5823 5824 .keywords: mesh 5825 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5826 @*/ 5827 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 5828 { 5829 DMLabelLink next = dm->labels->next; 5830 PetscErrorCode ierr; 5831 5832 PetscFunctionBegin; 5833 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5834 PetscValidPointer(name, 2); 5835 while (next) { 5836 PetscBool flg; 5837 5838 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5839 if (flg) {next->output = output; PetscFunctionReturn(0);} 5840 next = next->next; 5841 } 5842 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5843 } 5844 5845 5846 #undef __FUNCT__ 5847 #define __FUNCT__ "DMCopyLabels" 5848 /*@ 5849 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 5850 5851 Collective on DM 5852 5853 Input Parameter: 5854 . dmA - The DM object with initial labels 5855 5856 Output Parameter: 5857 . dmB - The DM object with copied labels 5858 5859 Level: intermediate 5860 5861 Note: This is typically used when interpolating or otherwise adding to a mesh 5862 5863 .keywords: mesh 5864 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 5865 @*/ 5866 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 5867 { 5868 PetscInt numLabels, l; 5869 PetscErrorCode ierr; 5870 5871 PetscFunctionBegin; 5872 if (dmA == dmB) PetscFunctionReturn(0); 5873 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 5874 for (l = 0; l < numLabels; ++l) { 5875 DMLabel label, labelNew; 5876 const char *name; 5877 PetscBool flg; 5878 5879 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 5880 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 5881 if (flg) continue; 5882 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 5883 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 5884 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 5885 } 5886 PetscFunctionReturn(0); 5887 } 5888 5889 #undef __FUNCT__ 5890 #define __FUNCT__ "DMGetCoarseDM" 5891 /*@ 5892 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5893 5894 Input Parameter: 5895 . dm - The DM object 5896 5897 Output Parameter: 5898 . cdm - The coarse DM 5899 5900 Level: intermediate 5901 5902 .seealso: DMSetCoarseDM() 5903 @*/ 5904 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 5905 { 5906 PetscFunctionBegin; 5907 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5908 PetscValidPointer(cdm, 2); 5909 *cdm = dm->coarseMesh; 5910 PetscFunctionReturn(0); 5911 } 5912 5913 #undef __FUNCT__ 5914 #define __FUNCT__ "DMSetCoarseDM" 5915 /*@ 5916 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5917 5918 Input Parameters: 5919 + dm - The DM object 5920 - cdm - The coarse DM 5921 5922 Level: intermediate 5923 5924 .seealso: DMGetCoarseDM() 5925 @*/ 5926 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 5927 { 5928 PetscErrorCode ierr; 5929 5930 PetscFunctionBegin; 5931 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5932 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5933 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5934 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 5935 dm->coarseMesh = cdm; 5936 PetscFunctionReturn(0); 5937 } 5938 5939 #undef __FUNCT__ 5940 #define __FUNCT__ "DMGetFineDM" 5941 /*@ 5942 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 5943 5944 Input Parameter: 5945 . dm - The DM object 5946 5947 Output Parameter: 5948 . fdm - The fine DM 5949 5950 Level: intermediate 5951 5952 .seealso: DMSetFineDM() 5953 @*/ 5954 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 5955 { 5956 PetscFunctionBegin; 5957 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5958 PetscValidPointer(fdm, 2); 5959 *fdm = dm->fineMesh; 5960 PetscFunctionReturn(0); 5961 } 5962 5963 #undef __FUNCT__ 5964 #define __FUNCT__ "DMSetFineDM" 5965 /*@ 5966 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 5967 5968 Input Parameters: 5969 + dm - The DM object 5970 - fdm - The fine DM 5971 5972 Level: intermediate 5973 5974 .seealso: DMGetFineDM() 5975 @*/ 5976 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 5977 { 5978 PetscErrorCode ierr; 5979 5980 PetscFunctionBegin; 5981 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5982 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 5983 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 5984 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 5985 dm->fineMesh = fdm; 5986 PetscFunctionReturn(0); 5987 } 5988 5989 /*=== DMBoundary code ===*/ 5990 5991 #undef __FUNCT__ 5992 #define __FUNCT__ "DMCopyBoundary" 5993 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 5994 { 5995 PetscErrorCode ierr; 5996 5997 PetscFunctionBegin; 5998 ierr = PetscDSCopyBoundary(dm->prob,dmNew->prob);CHKERRQ(ierr); 5999 PetscFunctionReturn(0); 6000 } 6001 6002 #undef __FUNCT__ 6003 #define __FUNCT__ "DMAddBoundary" 6004 /*@C 6005 DMAddBoundary - Add a boundary condition to the model 6006 6007 Input Parameters: 6008 + dm - The DM, with a PetscDS that matches the problem being constrained 6009 . type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6010 . name - The BC name 6011 . labelname - The label defining constrained points 6012 . field - The field to constrain 6013 . numcomps - The number of constrained field components 6014 . comps - An array of constrained component numbers 6015 . bcFunc - A pointwise function giving boundary values 6016 . numids - The number of DMLabel ids for constrained points 6017 . ids - An array of ids for constrained points 6018 - ctx - An optional user context for bcFunc 6019 6020 Options Database Keys: 6021 + -bc_<boundary name> <num> - Overrides the boundary ids 6022 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6023 6024 Level: developer 6025 6026 .seealso: DMGetBoundary() 6027 @*/ 6028 PetscErrorCode DMAddBoundary(DM dm, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(), PetscInt numids, const PetscInt *ids, void *ctx) 6029 { 6030 PetscErrorCode ierr; 6031 6032 PetscFunctionBegin; 6033 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6034 ierr = PetscDSAddBoundary(dm->prob,type,name,labelname,field,numcomps,comps,bcFunc,numids,ids,ctx);CHKERRQ(ierr); 6035 PetscFunctionReturn(0); 6036 } 6037 6038 #undef __FUNCT__ 6039 #define __FUNCT__ "DMGetNumBoundary" 6040 /*@ 6041 DMGetNumBoundary - Get the number of registered BC 6042 6043 Input Parameters: 6044 . dm - The mesh object 6045 6046 Output Parameters: 6047 . numBd - The number of BC 6048 6049 Level: intermediate 6050 6051 .seealso: DMAddBoundary(), DMGetBoundary() 6052 @*/ 6053 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 6054 { 6055 PetscErrorCode ierr; 6056 6057 PetscFunctionBegin; 6058 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6059 ierr = PetscDSGetNumBoundary(dm->prob,numBd);CHKERRQ(ierr); 6060 PetscFunctionReturn(0); 6061 } 6062 6063 #undef __FUNCT__ 6064 #define __FUNCT__ "DMGetBoundary" 6065 /*@C 6066 DMGetBoundary - Add a boundary condition to the model 6067 6068 Input Parameters: 6069 + dm - The mesh object 6070 - bd - The BC number 6071 6072 Output Parameters: 6073 + type - The type of condition, e.g. DM_BC_ESSENTIAL_ANALYTIC/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 6074 . name - The BC name 6075 . labelname - The label defining constrained points 6076 . field - The field to constrain 6077 . numcomps - The number of constrained field components 6078 . comps - An array of constrained component numbers 6079 . bcFunc - A pointwise function giving boundary values 6080 . numids - The number of DMLabel ids for constrained points 6081 . ids - An array of ids for constrained points 6082 - ctx - An optional user context for bcFunc 6083 6084 Options Database Keys: 6085 + -bc_<boundary name> <num> - Overrides the boundary ids 6086 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6087 6088 Level: developer 6089 6090 .seealso: DMAddBoundary() 6091 @*/ 6092 PetscErrorCode DMGetBoundary(DM dm, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(), PetscInt *numids, const PetscInt **ids, void **ctx) 6093 { 6094 PetscErrorCode ierr; 6095 6096 PetscFunctionBegin; 6097 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6098 ierr = PetscDSGetBoundary(dm->prob,bd,type,name,labelname,field,numcomps,comps,func,numids,ids,ctx);CHKERRQ(ierr); 6099 PetscFunctionReturn(0); 6100 } 6101 6102 #undef __FUNCT__ 6103 #define __FUNCT__ "DMPopulateBoundary" 6104 static PetscErrorCode DMPopulateBoundary(DM dm) 6105 { 6106 DMBoundary *lastnext; 6107 DSBoundary dsbound; 6108 PetscErrorCode ierr; 6109 6110 PetscFunctionBegin; 6111 dsbound = dm->prob->boundary; 6112 if (dm->boundary) { 6113 DMBoundary next = dm->boundary; 6114 6115 /* quick check to see if the PetscDS has changed */ 6116 if (next->dsboundary == dsbound) PetscFunctionReturn(0); 6117 /* the PetscDS has changed: tear down and rebuild */ 6118 while (next) { 6119 DMBoundary b = next; 6120 6121 next = b->next; 6122 ierr = PetscFree(b);CHKERRQ(ierr); 6123 } 6124 dm->boundary = NULL; 6125 } 6126 6127 lastnext = &(dm->boundary); 6128 while (dsbound) { 6129 DMBoundary dmbound; 6130 6131 ierr = PetscNew(&dmbound);CHKERRQ(ierr); 6132 dmbound->dsboundary = dsbound; 6133 ierr = DMGetLabel(dm, dsbound->labelname, &(dmbound->label));CHKERRQ(ierr); 6134 if (!dmbound->label) PetscInfo2(dm, "DSBoundary %s wants label %s, which is not in this dm.\n",dsbound->name,dsbound->labelname);CHKERRQ(ierr); 6135 /* push on the back instead of the front so that it is in the same order as in the PetscDS */ 6136 *lastnext = dmbound; 6137 lastnext = &(dmbound->next); 6138 dsbound = dsbound->next; 6139 } 6140 PetscFunctionReturn(0); 6141 } 6142 6143 #undef __FUNCT__ 6144 #define __FUNCT__ "DMIsBoundaryPoint" 6145 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 6146 { 6147 DMBoundary b; 6148 PetscErrorCode ierr; 6149 6150 PetscFunctionBegin; 6151 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6152 PetscValidPointer(isBd, 3); 6153 *isBd = PETSC_FALSE; 6154 ierr = DMPopulateBoundary(dm);CHKERRQ(ierr); 6155 b = dm->boundary; 6156 while (b && !(*isBd)) { 6157 DMLabel label = b->label; 6158 DSBoundary dsb = b->dsboundary; 6159 6160 if (label) { 6161 PetscInt i; 6162 6163 for (i = 0; i < dsb->numids && !(*isBd); ++i) { 6164 ierr = DMLabelStratumHasPoint(label, dsb->ids[i], point, isBd);CHKERRQ(ierr); 6165 } 6166 } 6167 b = b->next; 6168 } 6169 PetscFunctionReturn(0); 6170 } 6171 6172 #undef __FUNCT__ 6173 #define __FUNCT__ "DMProjectFunction" 6174 /*@C 6175 DMProjectFunction - This projects the given function into the function space provided. 6176 6177 Input Parameters: 6178 + dm - The DM 6179 . time - The time 6180 . funcs - The coordinate functions to evaluate, one per field 6181 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6182 - mode - The insertion mode for values 6183 6184 Output Parameter: 6185 . X - vector 6186 6187 Calling sequence of func: 6188 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6189 6190 + dim - The spatial dimension 6191 . x - The coordinates 6192 . Nf - The number of fields 6193 . u - The output field values 6194 - ctx - optional user-defined function context 6195 6196 Level: developer 6197 6198 .seealso: DMComputeL2Diff() 6199 @*/ 6200 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6201 { 6202 Vec localX; 6203 PetscErrorCode ierr; 6204 6205 PetscFunctionBegin; 6206 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6207 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6208 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6209 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6210 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6211 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6212 PetscFunctionReturn(0); 6213 } 6214 6215 #undef __FUNCT__ 6216 #define __FUNCT__ "DMProjectFunctionLocal" 6217 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6218 { 6219 PetscErrorCode ierr; 6220 6221 PetscFunctionBegin; 6222 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6223 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6224 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6225 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6226 PetscFunctionReturn(0); 6227 } 6228 6229 #undef __FUNCT__ 6230 #define __FUNCT__ "DMProjectFunctionLabelLocal" 6231 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) 6232 { 6233 PetscErrorCode ierr; 6234 6235 PetscFunctionBegin; 6236 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6237 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6238 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6239 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6240 PetscFunctionReturn(0); 6241 } 6242 6243 #undef __FUNCT__ 6244 #define __FUNCT__ "DMProjectFieldLocal" 6245 PetscErrorCode DMProjectFieldLocal(DM dm, PetscReal time, Vec localU, 6246 void (**funcs)(PetscInt, PetscInt, PetscInt, 6247 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6248 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6249 PetscReal, const PetscReal[], PetscScalar[]), 6250 InsertMode mode, Vec localX) 6251 { 6252 PetscErrorCode ierr; 6253 6254 PetscFunctionBegin; 6255 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6256 PetscValidHeaderSpecific(localU,VEC_CLASSID,3); 6257 PetscValidHeaderSpecific(localX,VEC_CLASSID,6); 6258 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFieldLocal",((PetscObject)dm)->type_name); 6259 ierr = (dm->ops->projectfieldlocal) (dm, time, localU, funcs, mode, localX);CHKERRQ(ierr); 6260 PetscFunctionReturn(0); 6261 } 6262 6263 #undef __FUNCT__ 6264 #define __FUNCT__ "DMProjectFieldLabelLocal" 6265 PetscErrorCode DMProjectFieldLabelLocal(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], Vec localU, 6266 void (**funcs)(PetscInt, PetscInt, PetscInt, 6267 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6268 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6269 PetscReal, const PetscReal[], PetscScalar[]), 6270 InsertMode mode, Vec localX) 6271 { 6272 PetscErrorCode ierr; 6273 6274 PetscFunctionBegin; 6275 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6276 PetscValidHeaderSpecific(localU,VEC_CLASSID,6); 6277 PetscValidHeaderSpecific(localX,VEC_CLASSID,9); 6278 if (!dm->ops->projectfieldlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFieldLocal",((PetscObject)dm)->type_name); 6279 ierr = (dm->ops->projectfieldlabellocal)(dm, time, label, numIds, ids, localU, funcs, mode, localX);CHKERRQ(ierr); 6280 PetscFunctionReturn(0); 6281 } 6282 6283 #undef __FUNCT__ 6284 #define __FUNCT__ "DMComputeL2Diff" 6285 /*@C 6286 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6287 6288 Input Parameters: 6289 + dm - The DM 6290 . time - The time 6291 . funcs - The functions to evaluate for each field component 6292 . ctxs - Optional array of contexts to pass to each function, or NULL. 6293 - X - The coefficient vector u_h 6294 6295 Output Parameter: 6296 . diff - The diff ||u - u_h||_2 6297 6298 Level: developer 6299 6300 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6301 @*/ 6302 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6303 { 6304 PetscErrorCode ierr; 6305 6306 PetscFunctionBegin; 6307 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6308 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6309 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2Diff",((PetscObject)dm)->type_name); 6310 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6311 PetscFunctionReturn(0); 6312 } 6313 6314 #undef __FUNCT__ 6315 #define __FUNCT__ "DMComputeL2GradientDiff" 6316 /*@C 6317 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6318 6319 Input Parameters: 6320 + dm - The DM 6321 , time - The time 6322 . funcs - The gradient functions to evaluate for each field component 6323 . ctxs - Optional array of contexts to pass to each function, or NULL. 6324 . X - The coefficient vector u_h 6325 - n - The vector to project along 6326 6327 Output Parameter: 6328 . diff - The diff ||(grad u - grad u_h) . n||_2 6329 6330 Level: developer 6331 6332 .seealso: DMProjectFunction(), DMComputeL2Diff() 6333 @*/ 6334 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) 6335 { 6336 PetscErrorCode ierr; 6337 6338 PetscFunctionBegin; 6339 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6340 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6341 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6342 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6343 PetscFunctionReturn(0); 6344 } 6345 6346 #undef __FUNCT__ 6347 #define __FUNCT__ "DMComputeL2FieldDiff" 6348 /*@C 6349 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 6350 6351 Input Parameters: 6352 + dm - The DM 6353 . time - The time 6354 . funcs - The functions to evaluate for each field component 6355 . ctxs - Optional array of contexts to pass to each function, or NULL. 6356 - X - The coefficient vector u_h 6357 6358 Output Parameter: 6359 . diff - The array of differences, ||u^f - u^f_h||_2 6360 6361 Level: developer 6362 6363 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6364 @*/ 6365 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 6366 { 6367 PetscErrorCode ierr; 6368 6369 PetscFunctionBegin; 6370 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6371 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6372 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6373 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6374 PetscFunctionReturn(0); 6375 } 6376 6377 #undef __FUNCT__ 6378 #define __FUNCT__ "DMAdaptLabel" 6379 /*@C 6380 DMAdaptLabel - Adapt a dm based on a label with values interpreted as coarsening and refining flags. Specific implementations of DM maybe have 6381 specialized flags, but all implementations should accept flag values DM_ADAPT_DETERMINE, DM_ADAPT_KEEP, DM_ADAPT_REFINE, and DM_ADAPT_COARSEN. 6382 6383 Collective on dm 6384 6385 Input parameters: 6386 + dm - the pre-adaptation DM object 6387 - label - label with the flags 6388 6389 Output parameters: 6390 . adaptedDM - the adapted DM object: may be NULL if an adapted DM could not be produced. 6391 6392 Level: intermediate 6393 @*/ 6394 PetscErrorCode DMAdaptLabel(DM dm, DMLabel label, DM *adaptedDM) 6395 { 6396 PetscErrorCode ierr; 6397 6398 PetscFunctionBegin; 6399 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6400 PetscValidPointer(label,2); 6401 PetscValidPointer(adaptedDM,3); 6402 *adaptedDM = NULL; 6403 ierr = PetscTryMethod((PetscObject)dm,"DMAdaptLabel_C",(DM,DMLabel, DM*),(dm,label,adaptedDM));CHKERRQ(ierr); 6404 PetscFunctionReturn(0); 6405 } 6406 6407 #undef __FUNCT__ 6408 #define __FUNCT__ "DMGetNeighbors" 6409 /*@C 6410 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 6411 6412 Not Collective 6413 6414 Input Parameter: 6415 . dm - The DM 6416 6417 Output Parameter: 6418 . nranks - the number of neighbours 6419 . ranks - the neighbors ranks 6420 6421 Notes: 6422 Do not free the array, it is freed when the DM is destroyed. 6423 6424 Level: beginner 6425 6426 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 6427 @*/ 6428 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 6429 { 6430 PetscErrorCode ierr; 6431 6432 PetscFunctionBegin; 6433 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6434 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMGetNeighbors",((PetscObject)dm)->type_name); 6435 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 6436 PetscFunctionReturn(0); 6437 } 6438 6439 #include <petsc/private/matimpl.h> /* Needed because of coloring->ctype below */ 6440 6441 #undef __FUNCT__ 6442 #define __FUNCT__ "MatFDColoringApply_AIJDM" 6443 /* 6444 Converts the input vector to a ghosted vector and then calls the standard coloring code. 6445 This has be a different function because it requires DM which is not defined in the Mat library 6446 */ 6447 PetscErrorCode MatFDColoringApply_AIJDM(Mat J,MatFDColoring coloring,Vec x1,void *sctx) 6448 { 6449 PetscErrorCode ierr; 6450 6451 PetscFunctionBegin; 6452 if (coloring->ctype == IS_COLORING_LOCAL) { 6453 Vec x1local; 6454 DM dm; 6455 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6456 if (!dm) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_INCOMP,"IS_COLORING_LOCAL requires a DM"); 6457 ierr = DMGetLocalVector(dm,&x1local);CHKERRQ(ierr); 6458 ierr = DMGlobalToLocalBegin(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6459 ierr = DMGlobalToLocalEnd(dm,x1,INSERT_VALUES,x1local);CHKERRQ(ierr); 6460 x1 = x1local; 6461 } 6462 ierr = MatFDColoringApply_AIJ(J,coloring,x1,sctx);CHKERRQ(ierr); 6463 if (coloring->ctype == IS_COLORING_LOCAL) { 6464 DM dm; 6465 ierr = MatGetDM(J,&dm);CHKERRQ(ierr); 6466 ierr = DMRestoreLocalVector(dm,&x1);CHKERRQ(ierr); 6467 } 6468 PetscFunctionReturn(0); 6469 } 6470 6471 #undef __FUNCT__ 6472 #define __FUNCT__ "MatFDColoringUseDM" 6473 /*@ 6474 MatFDColoringUseDM - allows a MatFDColoring object to use the DM associated with the matrix to use a IS_COLORING_LOCAL coloring 6475 6476 Input Parameter: 6477 . coloring - the MatFDColoring object 6478 6479 Developer Notes: this routine exists because the PETSc Mat library does not know about the DM objects 6480 6481 .seealso: MatFDColoring, MatFDColoringCreate(), ISColoringType 6482 @*/ 6483 PetscErrorCode MatFDColoringUseDM(Mat coloring,MatFDColoring fdcoloring) 6484 { 6485 PetscFunctionBegin; 6486 coloring->ops->fdcoloringapply = MatFDColoringApply_AIJDM; 6487 PetscFunctionReturn(0); 6488 } 6489