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