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