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