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