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 = PetscMalloc(sizeof(struct _DMRefineHookLink),&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 = PetscMalloc(sizeof(struct _DMGlobalToLocalHookLink),&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 = PetscMalloc(sizeof(struct _DMLocalToGlobalHookLink),&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 = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&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 = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&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,4); 4913 if (*cellSF) { 4914 PetscMPIInt result; 4915 4916 PetscValidHeaderSpecific(*cellSF,PETSCSF_CLASSID,4); 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 } else { 4920 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 4921 } 4922 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4923 if (dm->ops->locatepoints) { 4924 ierr = (*dm->ops->locatepoints)(dm,v,ltype,*cellSF);CHKERRQ(ierr); 4925 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4926 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4927 PetscFunctionReturn(0); 4928 } 4929 4930 #undef __FUNCT__ 4931 #define __FUNCT__ "DMGetOutputDM" 4932 /*@ 4933 DMGetOutputDM - Retrieve the DM associated with the layout for output 4934 4935 Input Parameter: 4936 . dm - The original DM 4937 4938 Output Parameter: 4939 . odm - The DM which provides the layout for output 4940 4941 Level: intermediate 4942 4943 .seealso: VecView(), DMGetDefaultGlobalSection() 4944 @*/ 4945 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4946 { 4947 PetscSection section; 4948 PetscBool hasConstraints; 4949 PetscErrorCode ierr; 4950 4951 PetscFunctionBegin; 4952 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4953 PetscValidPointer(odm,2); 4954 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4955 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4956 if (!hasConstraints) { 4957 *odm = dm; 4958 PetscFunctionReturn(0); 4959 } 4960 if (!dm->dmBC) { 4961 PetscDS ds; 4962 PetscSection newSection, gsection; 4963 PetscSF sf; 4964 4965 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4966 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 4967 ierr = DMSetDS(dm->dmBC, ds);CHKERRQ(ierr); 4968 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4969 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4970 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4971 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4972 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 4973 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4974 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4975 } 4976 *odm = dm->dmBC; 4977 PetscFunctionReturn(0); 4978 } 4979 4980 #undef __FUNCT__ 4981 #define __FUNCT__ "DMGetOutputSequenceNumber" 4982 /*@ 4983 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 4984 4985 Input Parameter: 4986 . dm - The original DM 4987 4988 Output Parameters: 4989 + num - The output sequence number 4990 - val - The output sequence value 4991 4992 Level: intermediate 4993 4994 Note: This is intended for output that should appear in sequence, for instance 4995 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4996 4997 .seealso: VecView() 4998 @*/ 4999 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 5000 { 5001 PetscFunctionBegin; 5002 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5003 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 5004 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 5005 PetscFunctionReturn(0); 5006 } 5007 5008 #undef __FUNCT__ 5009 #define __FUNCT__ "DMSetOutputSequenceNumber" 5010 /*@ 5011 DMSetOutputSequenceNumber - Set the sequence number/value for output 5012 5013 Input Parameters: 5014 + dm - The original DM 5015 . num - The output sequence number 5016 - val - The output sequence value 5017 5018 Level: intermediate 5019 5020 Note: This is intended for output that should appear in sequence, for instance 5021 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5022 5023 .seealso: VecView() 5024 @*/ 5025 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 5026 { 5027 PetscFunctionBegin; 5028 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5029 dm->outputSequenceNum = num; 5030 dm->outputSequenceVal = val; 5031 PetscFunctionReturn(0); 5032 } 5033 5034 #undef __FUNCT__ 5035 #define __FUNCT__ "DMOutputSequenceLoad" 5036 /*@C 5037 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 5038 5039 Input Parameters: 5040 + dm - The original DM 5041 . name - The sequence name 5042 - num - The output sequence number 5043 5044 Output Parameter: 5045 . val - The output sequence value 5046 5047 Level: intermediate 5048 5049 Note: This is intended for output that should appear in sequence, for instance 5050 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5051 5052 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 5053 @*/ 5054 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 5055 { 5056 PetscBool ishdf5; 5057 PetscErrorCode ierr; 5058 5059 PetscFunctionBegin; 5060 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5061 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 5062 PetscValidPointer(val,4); 5063 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 5064 if (ishdf5) { 5065 #if defined(PETSC_HAVE_HDF5) 5066 PetscScalar value; 5067 5068 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 5069 *val = PetscRealPart(value); 5070 #endif 5071 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 5072 PetscFunctionReturn(0); 5073 } 5074 5075 #undef __FUNCT__ 5076 #define __FUNCT__ "DMGetUseNatural" 5077 /*@ 5078 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 5079 5080 Not collective 5081 5082 Input Parameter: 5083 . dm - The DM 5084 5085 Output Parameter: 5086 . useNatural - The flag to build the mapping to a natural order during distribution 5087 5088 Level: beginner 5089 5090 .seealso: DMSetUseNatural(), DMCreate() 5091 @*/ 5092 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 5093 { 5094 PetscFunctionBegin; 5095 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5096 PetscValidPointer(useNatural, 2); 5097 *useNatural = dm->useNatural; 5098 PetscFunctionReturn(0); 5099 } 5100 5101 #undef __FUNCT__ 5102 #define __FUNCT__ "DMSetUseNatural" 5103 /*@ 5104 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 5105 5106 Collective on dm 5107 5108 Input Parameters: 5109 + dm - The DM 5110 - useNatural - The flag to build the mapping to a natural order during distribution 5111 5112 Level: beginner 5113 5114 .seealso: DMGetUseNatural(), DMCreate() 5115 @*/ 5116 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 5117 { 5118 PetscFunctionBegin; 5119 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5120 PetscValidLogicalCollectiveInt(dm, useNatural, 2); 5121 dm->useNatural = useNatural; 5122 PetscFunctionReturn(0); 5123 } 5124 5125 #undef __FUNCT__ 5126 #define __FUNCT__ 5127 5128 #undef __FUNCT__ 5129 #define __FUNCT__ "DMCreateLabel" 5130 /*@C 5131 DMCreateLabel - Create a label of the given name if it does not already exist 5132 5133 Not Collective 5134 5135 Input Parameters: 5136 + dm - The DM object 5137 - name - The label name 5138 5139 Level: intermediate 5140 5141 .keywords: mesh 5142 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5143 @*/ 5144 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 5145 { 5146 DMLabelLink next = dm->labels->next; 5147 PetscBool flg = PETSC_FALSE; 5148 PetscErrorCode ierr; 5149 5150 PetscFunctionBegin; 5151 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5152 PetscValidCharPointer(name, 2); 5153 while (next) { 5154 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5155 if (flg) break; 5156 next = next->next; 5157 } 5158 if (!flg) { 5159 DMLabelLink tmpLabel; 5160 5161 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5162 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 5163 tmpLabel->output = PETSC_TRUE; 5164 tmpLabel->next = dm->labels->next; 5165 dm->labels->next = tmpLabel; 5166 } 5167 PetscFunctionReturn(0); 5168 } 5169 5170 #undef __FUNCT__ 5171 #define __FUNCT__ "DMGetLabelValue" 5172 /*@C 5173 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 5174 5175 Not Collective 5176 5177 Input Parameters: 5178 + dm - The DM object 5179 . name - The label name 5180 - point - The mesh point 5181 5182 Output Parameter: 5183 . value - The label value for this point, or -1 if the point is not in the label 5184 5185 Level: beginner 5186 5187 .keywords: mesh 5188 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 5189 @*/ 5190 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 5191 { 5192 DMLabel label; 5193 PetscErrorCode ierr; 5194 5195 PetscFunctionBegin; 5196 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5197 PetscValidCharPointer(name, 2); 5198 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5199 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);CHKERRQ(ierr); 5200 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5201 PetscFunctionReturn(0); 5202 } 5203 5204 #undef __FUNCT__ 5205 #define __FUNCT__ "DMSetLabelValue" 5206 /*@C 5207 DMSetLabelValue - Add a point to a Sieve Label with given value 5208 5209 Not Collective 5210 5211 Input Parameters: 5212 + dm - The DM object 5213 . name - The label name 5214 . point - The mesh point 5215 - value - The label value for this point 5216 5217 Output Parameter: 5218 5219 Level: beginner 5220 5221 .keywords: mesh 5222 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5223 @*/ 5224 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5225 { 5226 DMLabel label; 5227 PetscErrorCode ierr; 5228 5229 PetscFunctionBegin; 5230 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5231 PetscValidCharPointer(name, 2); 5232 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5233 if (!label) { 5234 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5235 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5236 } 5237 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5238 PetscFunctionReturn(0); 5239 } 5240 5241 #undef __FUNCT__ 5242 #define __FUNCT__ "DMClearLabelValue" 5243 /*@C 5244 DMClearLabelValue - Remove a point from a Sieve Label with given value 5245 5246 Not Collective 5247 5248 Input Parameters: 5249 + dm - The DM object 5250 . name - The label name 5251 . point - The mesh point 5252 - value - The label value for this point 5253 5254 Output Parameter: 5255 5256 Level: beginner 5257 5258 .keywords: mesh 5259 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5260 @*/ 5261 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5262 { 5263 DMLabel label; 5264 PetscErrorCode ierr; 5265 5266 PetscFunctionBegin; 5267 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5268 PetscValidCharPointer(name, 2); 5269 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5270 if (!label) PetscFunctionReturn(0); 5271 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5272 PetscFunctionReturn(0); 5273 } 5274 5275 #undef __FUNCT__ 5276 #define __FUNCT__ "DMGetLabelSize" 5277 /*@C 5278 DMGetLabelSize - Get the number of different integer ids in a Label 5279 5280 Not Collective 5281 5282 Input Parameters: 5283 + dm - The DM object 5284 - name - The label name 5285 5286 Output Parameter: 5287 . size - The number of different integer ids, or 0 if the label does not exist 5288 5289 Level: beginner 5290 5291 .keywords: mesh 5292 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 5293 @*/ 5294 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5295 { 5296 DMLabel label; 5297 PetscErrorCode ierr; 5298 5299 PetscFunctionBegin; 5300 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5301 PetscValidCharPointer(name, 2); 5302 PetscValidPointer(size, 3); 5303 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5304 *size = 0; 5305 if (!label) PetscFunctionReturn(0); 5306 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5307 PetscFunctionReturn(0); 5308 } 5309 5310 #undef __FUNCT__ 5311 #define __FUNCT__ "DMGetLabelIdIS" 5312 /*@C 5313 DMGetLabelIdIS - Get the integer ids in a label 5314 5315 Not Collective 5316 5317 Input Parameters: 5318 + mesh - The DM object 5319 - name - The label name 5320 5321 Output Parameter: 5322 . ids - The integer ids, or NULL if the label does not exist 5323 5324 Level: beginner 5325 5326 .keywords: mesh 5327 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5328 @*/ 5329 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5330 { 5331 DMLabel label; 5332 PetscErrorCode ierr; 5333 5334 PetscFunctionBegin; 5335 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5336 PetscValidCharPointer(name, 2); 5337 PetscValidPointer(ids, 3); 5338 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5339 *ids = NULL; 5340 if (!label) PetscFunctionReturn(0); 5341 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5342 PetscFunctionReturn(0); 5343 } 5344 5345 #undef __FUNCT__ 5346 #define __FUNCT__ "DMGetStratumSize" 5347 /*@C 5348 DMGetStratumSize - Get the number of points in a label stratum 5349 5350 Not Collective 5351 5352 Input Parameters: 5353 + dm - The DM object 5354 . name - The label name 5355 - value - The stratum value 5356 5357 Output Parameter: 5358 . size - The stratum size 5359 5360 Level: beginner 5361 5362 .keywords: mesh 5363 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5364 @*/ 5365 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5366 { 5367 DMLabel label; 5368 PetscErrorCode ierr; 5369 5370 PetscFunctionBegin; 5371 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5372 PetscValidCharPointer(name, 2); 5373 PetscValidPointer(size, 4); 5374 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5375 *size = 0; 5376 if (!label) PetscFunctionReturn(0); 5377 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5378 PetscFunctionReturn(0); 5379 } 5380 5381 #undef __FUNCT__ 5382 #define __FUNCT__ "DMGetStratumIS" 5383 /*@C 5384 DMGetStratumIS - Get the points in a label stratum 5385 5386 Not Collective 5387 5388 Input Parameters: 5389 + dm - The DM object 5390 . name - The label name 5391 - value - The stratum value 5392 5393 Output Parameter: 5394 . points - The stratum points, or NULL if the label does not exist or does not have that value 5395 5396 Level: beginner 5397 5398 .keywords: mesh 5399 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5400 @*/ 5401 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5402 { 5403 DMLabel label; 5404 PetscErrorCode ierr; 5405 5406 PetscFunctionBegin; 5407 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5408 PetscValidCharPointer(name, 2); 5409 PetscValidPointer(points, 4); 5410 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5411 *points = NULL; 5412 if (!label) PetscFunctionReturn(0); 5413 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5414 PetscFunctionReturn(0); 5415 } 5416 5417 #undef __FUNCT__ 5418 #define __FUNCT__ "DMClearLabelStratum" 5419 /*@C 5420 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 5421 5422 Not Collective 5423 5424 Input Parameters: 5425 + dm - The DM object 5426 . name - The label name 5427 - value - The label value for this point 5428 5429 Output Parameter: 5430 5431 Level: beginner 5432 5433 .keywords: mesh 5434 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 5435 @*/ 5436 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 5437 { 5438 DMLabel label; 5439 PetscErrorCode ierr; 5440 5441 PetscFunctionBegin; 5442 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5443 PetscValidCharPointer(name, 2); 5444 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5445 if (!label) PetscFunctionReturn(0); 5446 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 5447 PetscFunctionReturn(0); 5448 } 5449 5450 #undef __FUNCT__ 5451 #define __FUNCT__ "DMGetNumLabels" 5452 /*@ 5453 DMGetNumLabels - Return the number of labels defined by the mesh 5454 5455 Not Collective 5456 5457 Input Parameter: 5458 . dm - The DM object 5459 5460 Output Parameter: 5461 . numLabels - the number of Labels 5462 5463 Level: intermediate 5464 5465 .keywords: mesh 5466 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5467 @*/ 5468 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 5469 { 5470 DMLabelLink next = dm->labels->next; 5471 PetscInt n = 0; 5472 5473 PetscFunctionBegin; 5474 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5475 PetscValidPointer(numLabels, 2); 5476 while (next) {++n; next = next->next;} 5477 *numLabels = n; 5478 PetscFunctionReturn(0); 5479 } 5480 5481 #undef __FUNCT__ 5482 #define __FUNCT__ "DMGetLabelName" 5483 /*@C 5484 DMGetLabelName - Return the name of nth label 5485 5486 Not Collective 5487 5488 Input Parameters: 5489 + dm - The DM object 5490 - n - the label number 5491 5492 Output Parameter: 5493 . name - the label name 5494 5495 Level: intermediate 5496 5497 .keywords: mesh 5498 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5499 @*/ 5500 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 5501 { 5502 DMLabelLink next = dm->labels->next; 5503 PetscInt l = 0; 5504 5505 PetscFunctionBegin; 5506 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5507 PetscValidPointer(name, 3); 5508 while (next) { 5509 if (l == n) { 5510 *name = next->label->name; 5511 PetscFunctionReturn(0); 5512 } 5513 ++l; 5514 next = next->next; 5515 } 5516 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5517 } 5518 5519 #undef __FUNCT__ 5520 #define __FUNCT__ "DMHasLabel" 5521 /*@C 5522 DMHasLabel - Determine whether the mesh has a label of a given name 5523 5524 Not Collective 5525 5526 Input Parameters: 5527 + dm - The DM object 5528 - name - The label name 5529 5530 Output Parameter: 5531 . hasLabel - PETSC_TRUE if the label is present 5532 5533 Level: intermediate 5534 5535 .keywords: mesh 5536 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5537 @*/ 5538 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 5539 { 5540 DMLabelLink next = dm->labels->next; 5541 PetscErrorCode ierr; 5542 5543 PetscFunctionBegin; 5544 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5545 PetscValidCharPointer(name, 2); 5546 PetscValidPointer(hasLabel, 3); 5547 *hasLabel = PETSC_FALSE; 5548 while (next) { 5549 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 5550 if (*hasLabel) break; 5551 next = next->next; 5552 } 5553 PetscFunctionReturn(0); 5554 } 5555 5556 #undef __FUNCT__ 5557 #define __FUNCT__ "DMGetLabel" 5558 /*@C 5559 DMGetLabel - Return the label of a given name, or NULL 5560 5561 Not Collective 5562 5563 Input Parameters: 5564 + dm - The DM object 5565 - name - The label name 5566 5567 Output Parameter: 5568 . label - The DMLabel, or NULL if the label is absent 5569 5570 Level: intermediate 5571 5572 .keywords: mesh 5573 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5574 @*/ 5575 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 5576 { 5577 DMLabelLink next = dm->labels->next; 5578 PetscBool hasLabel; 5579 PetscErrorCode ierr; 5580 5581 PetscFunctionBegin; 5582 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5583 PetscValidCharPointer(name, 2); 5584 PetscValidPointer(label, 3); 5585 *label = NULL; 5586 while (next) { 5587 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5588 if (hasLabel) { 5589 *label = next->label; 5590 break; 5591 } 5592 next = next->next; 5593 } 5594 PetscFunctionReturn(0); 5595 } 5596 5597 #undef __FUNCT__ 5598 #define __FUNCT__ "DMGetLabelByNum" 5599 /*@C 5600 DMGetLabelByNum - Return the nth label 5601 5602 Not Collective 5603 5604 Input Parameters: 5605 + dm - The DM object 5606 - n - the label number 5607 5608 Output Parameter: 5609 . label - the label 5610 5611 Level: intermediate 5612 5613 .keywords: mesh 5614 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5615 @*/ 5616 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5617 { 5618 DMLabelLink next = dm->labels->next; 5619 PetscInt l = 0; 5620 5621 PetscFunctionBegin; 5622 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5623 PetscValidPointer(label, 3); 5624 while (next) { 5625 if (l == n) { 5626 *label = next->label; 5627 PetscFunctionReturn(0); 5628 } 5629 ++l; 5630 next = next->next; 5631 } 5632 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5633 } 5634 5635 #undef __FUNCT__ 5636 #define __FUNCT__ "DMAddLabel" 5637 /*@C 5638 DMAddLabel - Add the label to this mesh 5639 5640 Not Collective 5641 5642 Input Parameters: 5643 + dm - The DM object 5644 - label - The DMLabel 5645 5646 Level: developer 5647 5648 .keywords: mesh 5649 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5650 @*/ 5651 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5652 { 5653 DMLabelLink tmpLabel; 5654 PetscBool hasLabel; 5655 PetscErrorCode ierr; 5656 5657 PetscFunctionBegin; 5658 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5659 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5660 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5661 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5662 tmpLabel->label = label; 5663 tmpLabel->output = PETSC_TRUE; 5664 tmpLabel->next = dm->labels->next; 5665 dm->labels->next = tmpLabel; 5666 PetscFunctionReturn(0); 5667 } 5668 5669 #undef __FUNCT__ 5670 #define __FUNCT__ "DMRemoveLabel" 5671 /*@C 5672 DMRemoveLabel - Remove the label from this mesh 5673 5674 Not Collective 5675 5676 Input Parameters: 5677 + dm - The DM object 5678 - name - The label name 5679 5680 Output Parameter: 5681 . label - The DMLabel, or NULL if the label is absent 5682 5683 Level: developer 5684 5685 .keywords: mesh 5686 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5687 @*/ 5688 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5689 { 5690 DMLabelLink next = dm->labels->next; 5691 DMLabelLink last = NULL; 5692 PetscBool hasLabel; 5693 PetscErrorCode ierr; 5694 5695 PetscFunctionBegin; 5696 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5697 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5698 *label = NULL; 5699 if (!hasLabel) PetscFunctionReturn(0); 5700 while (next) { 5701 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5702 if (hasLabel) { 5703 if (last) last->next = next->next; 5704 else dm->labels->next = next->next; 5705 next->next = NULL; 5706 *label = next->label; 5707 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5708 if (hasLabel) { 5709 dm->depthLabel = NULL; 5710 } 5711 ierr = PetscFree(next);CHKERRQ(ierr); 5712 break; 5713 } 5714 last = next; 5715 next = next->next; 5716 } 5717 PetscFunctionReturn(0); 5718 } 5719 5720 #undef __FUNCT__ 5721 #define __FUNCT__ "DMGetLabelOutput" 5722 /*@C 5723 DMGetLabelOutput - Get the output flag for a given label 5724 5725 Not Collective 5726 5727 Input Parameters: 5728 + dm - The DM object 5729 - name - The label name 5730 5731 Output Parameter: 5732 . output - The flag for output 5733 5734 Level: developer 5735 5736 .keywords: mesh 5737 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5738 @*/ 5739 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5740 { 5741 DMLabelLink next = dm->labels->next; 5742 PetscErrorCode ierr; 5743 5744 PetscFunctionBegin; 5745 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5746 PetscValidPointer(name, 2); 5747 PetscValidPointer(output, 3); 5748 while (next) { 5749 PetscBool flg; 5750 5751 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5752 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5753 next = next->next; 5754 } 5755 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5756 } 5757 5758 #undef __FUNCT__ 5759 #define __FUNCT__ "DMSetLabelOutput" 5760 /*@C 5761 DMSetLabelOutput - Set the output flag for a given label 5762 5763 Not Collective 5764 5765 Input Parameters: 5766 + dm - The DM object 5767 . name - The label name 5768 - output - The flag for output 5769 5770 Level: developer 5771 5772 .keywords: mesh 5773 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5774 @*/ 5775 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 5776 { 5777 DMLabelLink next = dm->labels->next; 5778 PetscErrorCode ierr; 5779 5780 PetscFunctionBegin; 5781 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5782 PetscValidPointer(name, 2); 5783 while (next) { 5784 PetscBool flg; 5785 5786 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5787 if (flg) {next->output = output; PetscFunctionReturn(0);} 5788 next = next->next; 5789 } 5790 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5791 } 5792 5793 5794 #undef __FUNCT__ 5795 #define __FUNCT__ "DMCopyLabels" 5796 /*@ 5797 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 5798 5799 Collective on DM 5800 5801 Input Parameter: 5802 . dmA - The DM object with initial labels 5803 5804 Output Parameter: 5805 . dmB - The DM object with copied labels 5806 5807 Level: intermediate 5808 5809 Note: This is typically used when interpolating or otherwise adding to a mesh 5810 5811 .keywords: mesh 5812 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 5813 @*/ 5814 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 5815 { 5816 PetscInt numLabels, l; 5817 PetscErrorCode ierr; 5818 5819 PetscFunctionBegin; 5820 if (dmA == dmB) PetscFunctionReturn(0); 5821 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 5822 for (l = 0; l < numLabels; ++l) { 5823 DMLabel label, labelNew; 5824 const char *name; 5825 PetscBool flg; 5826 5827 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 5828 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 5829 if (flg) continue; 5830 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 5831 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 5832 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 5833 } 5834 PetscFunctionReturn(0); 5835 } 5836 5837 #undef __FUNCT__ 5838 #define __FUNCT__ "DMGetCoarseDM" 5839 /*@ 5840 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5841 5842 Input Parameter: 5843 . dm - The DM object 5844 5845 Output Parameter: 5846 . cdm - The coarse DM 5847 5848 Level: intermediate 5849 5850 .seealso: DMSetCoarseDM() 5851 @*/ 5852 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 5853 { 5854 PetscFunctionBegin; 5855 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5856 PetscValidPointer(cdm, 2); 5857 *cdm = dm->coarseMesh; 5858 PetscFunctionReturn(0); 5859 } 5860 5861 #undef __FUNCT__ 5862 #define __FUNCT__ "DMSetCoarseDM" 5863 /*@ 5864 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5865 5866 Input Parameters: 5867 + dm - The DM object 5868 - cdm - The coarse DM 5869 5870 Level: intermediate 5871 5872 .seealso: DMGetCoarseDM() 5873 @*/ 5874 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 5875 { 5876 PetscErrorCode ierr; 5877 5878 PetscFunctionBegin; 5879 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5880 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5881 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5882 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 5883 dm->coarseMesh = cdm; 5884 PetscFunctionReturn(0); 5885 } 5886 5887 #undef __FUNCT__ 5888 #define __FUNCT__ "DMGetFineDM" 5889 /*@ 5890 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 5891 5892 Input Parameter: 5893 . dm - The DM object 5894 5895 Output Parameter: 5896 . fdm - The fine DM 5897 5898 Level: intermediate 5899 5900 .seealso: DMSetFineDM() 5901 @*/ 5902 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 5903 { 5904 PetscFunctionBegin; 5905 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5906 PetscValidPointer(fdm, 2); 5907 *fdm = dm->fineMesh; 5908 PetscFunctionReturn(0); 5909 } 5910 5911 #undef __FUNCT__ 5912 #define __FUNCT__ "DMSetFineDM" 5913 /*@ 5914 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 5915 5916 Input Parameters: 5917 + dm - The DM object 5918 - fdm - The fine DM 5919 5920 Level: intermediate 5921 5922 .seealso: DMGetFineDM() 5923 @*/ 5924 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 5925 { 5926 PetscErrorCode ierr; 5927 5928 PetscFunctionBegin; 5929 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5930 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 5931 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 5932 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 5933 dm->fineMesh = fdm; 5934 PetscFunctionReturn(0); 5935 } 5936 5937 /*=== DMBoundary code ===*/ 5938 5939 #undef __FUNCT__ 5940 #define __FUNCT__ "DMBoundaryDuplicate" 5941 PetscErrorCode DMBoundaryDuplicate(DMBoundaryLinkList bd, DMBoundaryLinkList *boundary) 5942 { 5943 DMBoundary b = bd->next, b2, bold = NULL; 5944 PetscErrorCode ierr; 5945 5946 PetscFunctionBegin; 5947 ierr = PetscNew(boundary);CHKERRQ(ierr); 5948 (*boundary)->refct = 1; 5949 (*boundary)->next = NULL; 5950 for (; b; b = b->next, bold = b2) { 5951 ierr = PetscNew(&b2);CHKERRQ(ierr); 5952 ierr = PetscStrallocpy(b->name, (char **) &b2->name);CHKERRQ(ierr); 5953 ierr = PetscStrallocpy(b->labelname, (char **) &b2->labelname);CHKERRQ(ierr); 5954 ierr = PetscMalloc1(b->numids, &b2->ids);CHKERRQ(ierr); 5955 ierr = PetscMemcpy(b2->ids, b->ids, b->numids*sizeof(PetscInt));CHKERRQ(ierr); 5956 ierr = PetscMalloc1(b->numcomps, &b2->comps);CHKERRQ(ierr); 5957 ierr = PetscMemcpy(b2->comps, b->comps, b->numcomps*sizeof(PetscInt));CHKERRQ(ierr); 5958 b2->label = NULL; 5959 b2->essential = b->essential; 5960 b2->field = b->field; 5961 b2->numcomps = b->numcomps; 5962 b2->func = b->func; 5963 b2->numids = b->numids; 5964 b2->ctx = b->ctx; 5965 b2->next = NULL; 5966 if (!(*boundary)->next) (*boundary)->next = b2; 5967 if (bold) bold->next = b2; 5968 } 5969 PetscFunctionReturn(0); 5970 } 5971 5972 #undef __FUNCT__ 5973 #define __FUNCT__ "DMBoundaryDestroy" 5974 PetscErrorCode DMBoundaryDestroy(DMBoundaryLinkList *boundary) 5975 { 5976 DMBoundary b, next; 5977 PetscErrorCode ierr; 5978 5979 PetscFunctionBegin; 5980 if (!boundary) PetscFunctionReturn(0); 5981 if (--((*boundary)->refct)) { 5982 *boundary = NULL; 5983 PetscFunctionReturn(0); 5984 } 5985 b = (*boundary)->next; 5986 for (; b; b = next) { 5987 next = b->next; 5988 ierr = PetscFree(b->comps);CHKERRQ(ierr); 5989 ierr = PetscFree(b->ids);CHKERRQ(ierr); 5990 ierr = PetscFree(b->name);CHKERRQ(ierr); 5991 ierr = PetscFree(b->labelname);CHKERRQ(ierr); 5992 ierr = PetscFree(b);CHKERRQ(ierr); 5993 } 5994 ierr = PetscFree(*boundary);CHKERRQ(ierr); 5995 PetscFunctionReturn(0); 5996 } 5997 5998 #undef __FUNCT__ 5999 #define __FUNCT__ "DMCopyBoundary" 6000 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 6001 { 6002 DMBoundary b; 6003 PetscErrorCode ierr; 6004 6005 PetscFunctionBegin; 6006 ierr = DMBoundaryDestroy(&dmNew->boundary);CHKERRQ(ierr); 6007 ierr = DMBoundaryDuplicate(dm->boundary, &dmNew->boundary);CHKERRQ(ierr); 6008 for (b = dmNew->boundary->next; b; b = b->next) { 6009 if (b->labelname) { 6010 ierr = DMGetLabel(dmNew, b->labelname, &b->label);CHKERRQ(ierr); 6011 if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 6012 } 6013 } 6014 PetscFunctionReturn(0); 6015 } 6016 6017 #undef __FUNCT__ 6018 #define __FUNCT__ "DMAddBoundary" 6019 /*@C 6020 DMAddBoundary - Add a boundary condition to the model 6021 6022 Input Parameters: 6023 + dm - The mesh object 6024 . isEssential - Flag for an essential (Dirichlet) condition, as opposed to a natural (Neumann) condition 6025 . name - The BC name 6026 . labelname - The label defining constrained points 6027 . field - The field to constrain 6028 . numcomps - The number of constrained field components 6029 . comps - An array of constrained component numbers 6030 . bcFunc - A pointwise function giving boundary values 6031 . numids - The number of DMLabel ids for constrained points 6032 . ids - An array of ids for constrained points 6033 - ctx - An optional user context for bcFunc 6034 6035 Options Database Keys: 6036 + -bc_<boundary name> <num> - Overrides the boundary ids 6037 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6038 6039 Level: developer 6040 6041 .seealso: DMGetBoundary() 6042 @*/ 6043 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) 6044 { 6045 DMBoundary b; 6046 PetscErrorCode ierr; 6047 6048 PetscFunctionBegin; 6049 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6050 ierr = PetscNew(&b);CHKERRQ(ierr); 6051 ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); 6052 ierr = PetscStrallocpy(labelname, (char **) &b->labelname);CHKERRQ(ierr); 6053 ierr = PetscMalloc1(numcomps, &b->comps);CHKERRQ(ierr); 6054 if (numcomps) {ierr = PetscMemcpy(b->comps, comps, numcomps*sizeof(PetscInt));CHKERRQ(ierr);} 6055 ierr = PetscMalloc1(numids, &b->ids);CHKERRQ(ierr); 6056 if (numids) {ierr = PetscMemcpy(b->ids, ids, numids*sizeof(PetscInt));CHKERRQ(ierr);} 6057 if (b->labelname) { 6058 ierr = DMGetLabel(dm, b->labelname, &b->label);CHKERRQ(ierr); 6059 if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 6060 } 6061 b->essential = isEssential; 6062 b->field = field; 6063 b->numcomps = numcomps; 6064 b->func = bcFunc; 6065 b->numids = numids; 6066 b->ctx = ctx; 6067 b->next = dm->boundary->next; 6068 dm->boundary->next = b; 6069 PetscFunctionReturn(0); 6070 } 6071 6072 #undef __FUNCT__ 6073 #define __FUNCT__ "DMGetNumBoundary" 6074 /*@ 6075 DMGetNumBoundary - Get the number of registered BC 6076 6077 Input Parameters: 6078 . dm - The mesh object 6079 6080 Output Parameters: 6081 . numBd - The number of BC 6082 6083 Level: intermediate 6084 6085 .seealso: DMAddBoundary(), DMGetBoundary() 6086 @*/ 6087 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 6088 { 6089 DMBoundary b = dm->boundary->next; 6090 6091 PetscFunctionBegin; 6092 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6093 PetscValidPointer(numBd, 2); 6094 *numBd = 0; 6095 while (b) {++(*numBd); b = b->next;} 6096 PetscFunctionReturn(0); 6097 } 6098 6099 #undef __FUNCT__ 6100 #define __FUNCT__ "DMGetBoundary" 6101 /*@C 6102 DMGetBoundary - Add a boundary condition to the model 6103 6104 Input Parameters: 6105 + dm - The mesh object 6106 - bd - The BC number 6107 6108 Output Parameters: 6109 + isEssential - Flag for an essential (Dirichlet) condition, as opposed to a natural (Neumann) condition 6110 . name - The BC name 6111 . labelname - The label defining constrained points 6112 . field - The field to constrain 6113 . numcomps - The number of constrained field components 6114 . comps - An array of constrained component numbers 6115 . bcFunc - A pointwise function giving boundary values 6116 . numids - The number of DMLabel ids for constrained points 6117 . ids - An array of ids for constrained points 6118 - ctx - An optional user context for bcFunc 6119 6120 Options Database Keys: 6121 + -bc_<boundary name> <num> - Overrides the boundary ids 6122 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6123 6124 Level: developer 6125 6126 .seealso: DMAddBoundary() 6127 @*/ 6128 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) 6129 { 6130 DMBoundary b = dm->boundary->next; 6131 PetscInt n = 0; 6132 6133 PetscFunctionBegin; 6134 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6135 while (b) { 6136 if (n == bd) break; 6137 b = b->next; 6138 ++n; 6139 } 6140 if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n); 6141 if (isEssential) { 6142 PetscValidPointer(isEssential, 3); 6143 *isEssential = b->essential; 6144 } 6145 if (name) { 6146 PetscValidPointer(name, 4); 6147 *name = b->name; 6148 } 6149 if (labelname) { 6150 PetscValidPointer(labelname, 5); 6151 *labelname = b->labelname; 6152 } 6153 if (field) { 6154 PetscValidPointer(field, 6); 6155 *field = b->field; 6156 } 6157 if (numcomps) { 6158 PetscValidPointer(numcomps, 7); 6159 *numcomps = b->numcomps; 6160 } 6161 if (comps) { 6162 PetscValidPointer(comps, 8); 6163 *comps = b->comps; 6164 } 6165 if (func) { 6166 PetscValidPointer(func, 9); 6167 *func = b->func; 6168 } 6169 if (numids) { 6170 PetscValidPointer(numids, 10); 6171 *numids = b->numids; 6172 } 6173 if (ids) { 6174 PetscValidPointer(ids, 11); 6175 *ids = b->ids; 6176 } 6177 if (ctx) { 6178 PetscValidPointer(ctx, 12); 6179 *ctx = b->ctx; 6180 } 6181 PetscFunctionReturn(0); 6182 } 6183 6184 #undef __FUNCT__ 6185 #define __FUNCT__ "DMIsBoundaryPoint" 6186 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 6187 { 6188 DMBoundary b = dm->boundary->next; 6189 PetscErrorCode ierr; 6190 6191 PetscFunctionBegin; 6192 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6193 PetscValidPointer(isBd, 3); 6194 *isBd = PETSC_FALSE; 6195 while (b && !(*isBd)) { 6196 if (b->label) { 6197 PetscInt i; 6198 6199 for (i = 0; i < b->numids && !(*isBd); ++i) { 6200 ierr = DMLabelStratumHasPoint(b->label, b->ids[i], point, isBd);CHKERRQ(ierr); 6201 } 6202 } 6203 b = b->next; 6204 } 6205 PetscFunctionReturn(0); 6206 } 6207 6208 #undef __FUNCT__ 6209 #define __FUNCT__ "DMProjectFunction" 6210 /*@C 6211 DMProjectFunction - This projects the given function into the function space provided. 6212 6213 Input Parameters: 6214 + dm - The DM 6215 . time - The time 6216 . funcs - The coordinate functions to evaluate, one per field 6217 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6218 - mode - The insertion mode for values 6219 6220 Output Parameter: 6221 . X - vector 6222 6223 Calling sequence of func: 6224 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6225 6226 + dim - The spatial dimension 6227 . x - The coordinates 6228 . Nf - The number of fields 6229 . u - The output field values 6230 - ctx - optional user-defined function context 6231 6232 Level: developer 6233 6234 .seealso: DMComputeL2Diff() 6235 @*/ 6236 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6237 { 6238 Vec localX; 6239 PetscErrorCode ierr; 6240 6241 PetscFunctionBegin; 6242 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6243 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6244 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6245 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6246 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6247 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6248 PetscFunctionReturn(0); 6249 } 6250 6251 #undef __FUNCT__ 6252 #define __FUNCT__ "DMProjectFunctionLocal" 6253 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6254 { 6255 PetscErrorCode ierr; 6256 6257 PetscFunctionBegin; 6258 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6259 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6260 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6261 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6262 PetscFunctionReturn(0); 6263 } 6264 6265 #undef __FUNCT__ 6266 #define __FUNCT__ "DMProjectFieldLocal" 6267 PetscErrorCode DMProjectFieldLocal(DM dm, Vec localU, 6268 void (**funcs)(PetscInt, PetscInt, PetscInt, 6269 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6270 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6271 PetscReal, const PetscReal[], PetscScalar[]), 6272 InsertMode mode, Vec localX) 6273 { 6274 PetscErrorCode ierr; 6275 6276 PetscFunctionBegin; 6277 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6278 PetscValidHeaderSpecific(localU,VEC_CLASSID,2); 6279 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6280 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFieldLocal",((PetscObject)dm)->type_name); 6281 ierr = (dm->ops->projectfieldlocal) (dm, localU, funcs, mode, localX);CHKERRQ(ierr); 6282 PetscFunctionReturn(0); 6283 } 6284 6285 #undef __FUNCT__ 6286 #define __FUNCT__ "DMProjectFunctionLabelLocal" 6287 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) 6288 { 6289 PetscErrorCode ierr; 6290 6291 PetscFunctionBegin; 6292 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6293 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6294 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6295 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6296 PetscFunctionReturn(0); 6297 } 6298 6299 #undef __FUNCT__ 6300 #define __FUNCT__ "DMComputeL2Diff" 6301 /*@C 6302 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6303 6304 Input Parameters: 6305 + dm - The DM 6306 . time - The time 6307 . funcs - The functions to evaluate for each field component 6308 . ctxs - Optional array of contexts to pass to each function, or NULL. 6309 - X - The coefficient vector u_h 6310 6311 Output Parameter: 6312 . diff - The diff ||u - u_h||_2 6313 6314 Level: developer 6315 6316 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6317 @*/ 6318 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6319 { 6320 PetscErrorCode ierr; 6321 6322 PetscFunctionBegin; 6323 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6324 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6325 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2Diff",((PetscObject)dm)->type_name); 6326 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6327 PetscFunctionReturn(0); 6328 } 6329 6330 #undef __FUNCT__ 6331 #define __FUNCT__ "DMComputeL2GradientDiff" 6332 /*@C 6333 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6334 6335 Input Parameters: 6336 + dm - The DM 6337 , time - The time 6338 . funcs - The gradient functions to evaluate for each field component 6339 . ctxs - Optional array of contexts to pass to each function, or NULL. 6340 . X - The coefficient vector u_h 6341 - n - The vector to project along 6342 6343 Output Parameter: 6344 . diff - The diff ||(grad u - grad u_h) . n||_2 6345 6346 Level: developer 6347 6348 .seealso: DMProjectFunction(), DMComputeL2Diff() 6349 @*/ 6350 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) 6351 { 6352 PetscErrorCode ierr; 6353 6354 PetscFunctionBegin; 6355 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6356 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6357 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6358 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6359 PetscFunctionReturn(0); 6360 } 6361 6362 #undef __FUNCT__ 6363 #define __FUNCT__ "DMComputeL2FieldDiff" 6364 /*@C 6365 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 6366 6367 Input Parameters: 6368 + dm - The DM 6369 . time - The time 6370 . funcs - The functions to evaluate for each field component 6371 . ctxs - Optional array of contexts to pass to each function, or NULL. 6372 - X - The coefficient vector u_h 6373 6374 Output Parameter: 6375 . diff - The array of differences, ||u^f - u^f_h||_2 6376 6377 Level: developer 6378 6379 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6380 @*/ 6381 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 6382 { 6383 PetscErrorCode ierr; 6384 6385 PetscFunctionBegin; 6386 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6387 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6388 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6389 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6390 PetscFunctionReturn(0); 6391 } 6392 6393 #undef __FUNCT__ 6394 #define __FUNCT__ "DMGetNeighbors" 6395 /*@C 6396 DMGetNeighbors - Gets an array containing the MPI rank of all the processes neighbors 6397 6398 Not Collective 6399 6400 Input Parameter: 6401 . dm - The DM 6402 6403 Output Parameter: 6404 . nranks - the number of neighbours 6405 . ranks - the neighbors ranks 6406 6407 Notes: 6408 Do not free the array, it is freed when the DM is destroyed. 6409 6410 Level: beginner 6411 6412 .seealso: DMDAGetNeighbors(), PetscSFGetRanks() 6413 @*/ 6414 PetscErrorCode DMGetNeighbors(DM dm,PetscInt *nranks,const PetscMPIInt *ranks[]) 6415 { 6416 PetscErrorCode ierr; 6417 6418 PetscFunctionBegin; 6419 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6420 if (!dm->ops->getneighbors) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMGetNeighbors",((PetscObject)dm)->type_name); 6421 ierr = (dm->ops->getneighbors)(dm,nranks,ranks);CHKERRQ(ierr); 6422 PetscFunctionReturn(0); 6423 } 6424 6425