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