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