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 DMCreateDomainDecompositionLocalScatter 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 = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 3970 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 3971 ierr = MatDestroy(&inject);CHKERRQ(ierr); 3972 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3973 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3974 } 3975 PetscFunctionReturn(0); 3976 } 3977 3978 #undef __FUNCT__ 3979 #define __FUNCT__ "DMSubDomainHook_Coordinates" 3980 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 3981 { 3982 DM dm_coord,subdm_coord; 3983 PetscErrorCode ierr; 3984 Vec coords,ccoords,clcoords; 3985 VecScatter *scat_i,*scat_g; 3986 PetscFunctionBegin; 3987 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3988 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 3989 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3990 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 3991 if (coords && !ccoords) { 3992 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 3993 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 3994 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 3995 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 3996 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3997 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3998 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3999 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 4000 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 4001 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 4002 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 4003 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 4004 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 4005 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 4006 ierr = PetscFree(scat_i);CHKERRQ(ierr); 4007 ierr = PetscFree(scat_g);CHKERRQ(ierr); 4008 } 4009 PetscFunctionReturn(0); 4010 } 4011 4012 #undef __FUNCT__ 4013 #define __FUNCT__ "DMGetDimension" 4014 /*@ 4015 DMGetDimension - Return the topological dimension of the DM 4016 4017 Not collective 4018 4019 Input Parameter: 4020 . dm - The DM 4021 4022 Output Parameter: 4023 . dim - The topological dimension 4024 4025 Level: beginner 4026 4027 .seealso: DMSetDimension(), DMCreate() 4028 @*/ 4029 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 4030 { 4031 PetscFunctionBegin; 4032 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4033 PetscValidPointer(dim, 2); 4034 *dim = dm->dim; 4035 PetscFunctionReturn(0); 4036 } 4037 4038 #undef __FUNCT__ 4039 #define __FUNCT__ "DMSetDimension" 4040 /*@ 4041 DMSetDimension - Set the topological dimension of the DM 4042 4043 Collective on dm 4044 4045 Input Parameters: 4046 + dm - The DM 4047 - dim - The topological dimension 4048 4049 Level: beginner 4050 4051 .seealso: DMGetDimension(), DMCreate() 4052 @*/ 4053 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 4054 { 4055 PetscFunctionBegin; 4056 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4057 PetscValidLogicalCollectiveInt(dm, dim, 2); 4058 dm->dim = dim; 4059 PetscFunctionReturn(0); 4060 } 4061 4062 #undef __FUNCT__ 4063 #define __FUNCT__ "DMGetDimPoints" 4064 /*@ 4065 DMGetDimPoints - Get the half-open interval for all points of a given dimension 4066 4067 Collective on DM 4068 4069 Input Parameters: 4070 + dm - the DM 4071 - dim - the dimension 4072 4073 Output Parameters: 4074 + pStart - The first point of the given dimension 4075 . pEnd - The first point following points of the given dimension 4076 4077 Note: 4078 The points are vertices in the Hasse diagram encoding the topology. This is explained in 4079 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 4080 then the interval is empty. 4081 4082 Level: intermediate 4083 4084 .keywords: point, Hasse Diagram, dimension 4085 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 4086 @*/ 4087 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 4088 { 4089 PetscInt d; 4090 PetscErrorCode ierr; 4091 4092 PetscFunctionBegin; 4093 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4094 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 4095 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 4096 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 4097 PetscFunctionReturn(0); 4098 } 4099 4100 #undef __FUNCT__ 4101 #define __FUNCT__ "DMSetCoordinates" 4102 /*@ 4103 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 4104 4105 Collective on DM 4106 4107 Input Parameters: 4108 + dm - the DM 4109 - c - coordinate vector 4110 4111 Note: 4112 The coordinates do include those for ghost points, which are in the local vector 4113 4114 Level: intermediate 4115 4116 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4117 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 4118 @*/ 4119 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 4120 { 4121 PetscErrorCode ierr; 4122 4123 PetscFunctionBegin; 4124 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4125 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4126 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4127 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4128 dm->coordinates = c; 4129 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4130 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4131 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 4132 PetscFunctionReturn(0); 4133 } 4134 4135 #undef __FUNCT__ 4136 #define __FUNCT__ "DMSetCoordinatesLocal" 4137 /*@ 4138 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 4139 4140 Collective on DM 4141 4142 Input Parameters: 4143 + dm - the DM 4144 - c - coordinate vector 4145 4146 Note: 4147 The coordinates of ghost points can be set using DMSetCoordinates() 4148 followed by DMGetCoordinatesLocal(). This is intended to enable the 4149 setting of ghost coordinates outside of the domain. 4150 4151 Level: intermediate 4152 4153 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4154 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 4155 @*/ 4156 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 4157 { 4158 PetscErrorCode ierr; 4159 4160 PetscFunctionBegin; 4161 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4162 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 4163 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 4164 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 4165 4166 dm->coordinatesLocal = c; 4167 4168 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 4169 PetscFunctionReturn(0); 4170 } 4171 4172 #undef __FUNCT__ 4173 #define __FUNCT__ "DMGetCoordinates" 4174 /*@ 4175 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 4176 4177 Not Collective 4178 4179 Input Parameter: 4180 . dm - the DM 4181 4182 Output Parameter: 4183 . c - global coordinate vector 4184 4185 Note: 4186 This is a borrowed reference, so the user should NOT destroy this vector 4187 4188 Each process has only the local coordinates (does NOT have the ghost coordinates). 4189 4190 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4191 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4192 4193 Level: intermediate 4194 4195 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4196 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 4197 @*/ 4198 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4199 { 4200 PetscErrorCode ierr; 4201 4202 PetscFunctionBegin; 4203 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4204 PetscValidPointer(c,2); 4205 if (!dm->coordinates && dm->coordinatesLocal) { 4206 DM cdm = NULL; 4207 4208 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4209 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4210 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4211 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4212 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4213 } 4214 *c = dm->coordinates; 4215 PetscFunctionReturn(0); 4216 } 4217 4218 #undef __FUNCT__ 4219 #define __FUNCT__ "DMGetCoordinatesLocal" 4220 /*@ 4221 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4222 4223 Collective on DM 4224 4225 Input Parameter: 4226 . dm - the DM 4227 4228 Output Parameter: 4229 . c - coordinate vector 4230 4231 Note: 4232 This is a borrowed reference, so the user should NOT destroy this vector 4233 4234 Each process has the local and ghost coordinates 4235 4236 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4237 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4238 4239 Level: intermediate 4240 4241 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4242 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4243 @*/ 4244 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4245 { 4246 PetscErrorCode ierr; 4247 4248 PetscFunctionBegin; 4249 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4250 PetscValidPointer(c,2); 4251 if (!dm->coordinatesLocal && dm->coordinates) { 4252 DM cdm = NULL; 4253 4254 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4255 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4256 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4257 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4258 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4259 } 4260 *c = dm->coordinatesLocal; 4261 PetscFunctionReturn(0); 4262 } 4263 4264 #undef __FUNCT__ 4265 #define __FUNCT__ "DMGetCoordinateDM" 4266 /*@ 4267 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4268 4269 Collective on DM 4270 4271 Input Parameter: 4272 . dm - the DM 4273 4274 Output Parameter: 4275 . cdm - coordinate DM 4276 4277 Level: intermediate 4278 4279 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4280 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4281 @*/ 4282 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4283 { 4284 PetscErrorCode ierr; 4285 4286 PetscFunctionBegin; 4287 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4288 PetscValidPointer(cdm,2); 4289 if (!dm->coordinateDM) { 4290 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4291 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 4292 } 4293 *cdm = dm->coordinateDM; 4294 PetscFunctionReturn(0); 4295 } 4296 4297 #undef __FUNCT__ 4298 #define __FUNCT__ "DMSetCoordinateDM" 4299 /*@ 4300 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4301 4302 Logically Collective on DM 4303 4304 Input Parameters: 4305 + dm - the DM 4306 - cdm - coordinate DM 4307 4308 Level: intermediate 4309 4310 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4311 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4312 @*/ 4313 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4314 { 4315 PetscErrorCode ierr; 4316 4317 PetscFunctionBegin; 4318 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4319 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4320 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4321 dm->coordinateDM = cdm; 4322 ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr); 4323 PetscFunctionReturn(0); 4324 } 4325 4326 #undef __FUNCT__ 4327 #define __FUNCT__ "DMGetCoordinateDim" 4328 /*@ 4329 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4330 4331 Not Collective 4332 4333 Input Parameter: 4334 . dm - The DM object 4335 4336 Output Parameter: 4337 . dim - The embedding dimension 4338 4339 Level: intermediate 4340 4341 .keywords: mesh, coordinates 4342 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4343 @*/ 4344 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4345 { 4346 PetscFunctionBegin; 4347 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4348 PetscValidPointer(dim, 2); 4349 if (dm->dimEmbed == PETSC_DEFAULT) { 4350 dm->dimEmbed = dm->dim; 4351 } 4352 *dim = dm->dimEmbed; 4353 PetscFunctionReturn(0); 4354 } 4355 4356 #undef __FUNCT__ 4357 #define __FUNCT__ "DMSetCoordinateDim" 4358 /*@ 4359 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4360 4361 Not Collective 4362 4363 Input Parameters: 4364 + dm - The DM object 4365 - dim - The embedding dimension 4366 4367 Level: intermediate 4368 4369 .keywords: mesh, coordinates 4370 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4371 @*/ 4372 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4373 { 4374 PetscFunctionBegin; 4375 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4376 dm->dimEmbed = dim; 4377 PetscFunctionReturn(0); 4378 } 4379 4380 #undef __FUNCT__ 4381 #define __FUNCT__ "DMGetCoordinateSection" 4382 /*@ 4383 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4384 4385 Not Collective 4386 4387 Input Parameter: 4388 . dm - The DM object 4389 4390 Output Parameter: 4391 . section - The PetscSection object 4392 4393 Level: intermediate 4394 4395 .keywords: mesh, coordinates 4396 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4397 @*/ 4398 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4399 { 4400 DM cdm; 4401 PetscErrorCode ierr; 4402 4403 PetscFunctionBegin; 4404 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4405 PetscValidPointer(section, 2); 4406 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4407 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4408 PetscFunctionReturn(0); 4409 } 4410 4411 #undef __FUNCT__ 4412 #define __FUNCT__ "DMSetCoordinateSection" 4413 /*@ 4414 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4415 4416 Not Collective 4417 4418 Input Parameters: 4419 + dm - The DM object 4420 . dim - The embedding dimension, or PETSC_DETERMINE 4421 - section - The PetscSection object 4422 4423 Level: intermediate 4424 4425 .keywords: mesh, coordinates 4426 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4427 @*/ 4428 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4429 { 4430 DM cdm; 4431 PetscErrorCode ierr; 4432 4433 PetscFunctionBegin; 4434 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4435 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4436 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4437 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4438 if (dim == PETSC_DETERMINE) { 4439 PetscInt d = dim; 4440 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4441 4442 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4443 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4444 pStart = PetscMax(vStart, pStart); 4445 pEnd = PetscMin(vEnd, pEnd); 4446 for (v = pStart; v < pEnd; ++v) { 4447 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4448 if (dd) {d = dd; break;} 4449 } 4450 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4451 } 4452 PetscFunctionReturn(0); 4453 } 4454 4455 #undef __FUNCT__ 4456 #define __FUNCT__ "DMGetPeriodicity" 4457 /*@C 4458 DMSetPeriodicity - Set the description of mesh periodicity 4459 4460 Input Parameters: 4461 + dm - The DM object 4462 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4463 . L - If we assume the mesh is a torus, this is the length of each coordinate 4464 - bd - This describes the type of periodicity in each topological dimension 4465 4466 Level: developer 4467 4468 .seealso: DMGetPeriodicity() 4469 @*/ 4470 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4471 { 4472 PetscFunctionBegin; 4473 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4474 if (L) *L = dm->L; 4475 if (maxCell) *maxCell = dm->maxCell; 4476 if (bd) *bd = dm->bdtype; 4477 PetscFunctionReturn(0); 4478 } 4479 4480 #undef __FUNCT__ 4481 #define __FUNCT__ "DMSetPeriodicity" 4482 /*@C 4483 DMSetPeriodicity - Set the description of mesh periodicity 4484 4485 Input Parameters: 4486 + dm - The DM object 4487 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4488 . L - If we assume the mesh is a torus, this is the length of each coordinate 4489 - bd - This describes the type of periodicity in each topological dimension 4490 4491 Level: developer 4492 4493 .seealso: DMGetPeriodicity() 4494 @*/ 4495 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4496 { 4497 PetscInt dim, d; 4498 PetscErrorCode ierr; 4499 4500 PetscFunctionBegin; 4501 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4502 PetscValidPointer(L,3);PetscValidPointer(maxCell,2);PetscValidPointer(bd,4); 4503 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4504 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4505 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4506 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4507 PetscFunctionReturn(0); 4508 } 4509 4510 #undef __FUNCT__ 4511 #define __FUNCT__ "DMLocalizeCoordinate" 4512 /*@ 4513 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. 4514 4515 Input Parameters: 4516 + dm - The DM 4517 - in - The input coordinate point (dim numbers) 4518 4519 Output Parameter: 4520 . out - The localized coordinate point 4521 4522 Level: developer 4523 4524 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4525 @*/ 4526 PetscErrorCode DMLocalizeCoordinate(DM dm, const PetscScalar in[], PetscScalar out[]) 4527 { 4528 PetscInt dim, d; 4529 PetscErrorCode ierr; 4530 4531 PetscFunctionBegin; 4532 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 4533 if (!dm->maxCell) { 4534 for (d = 0; d < dim; ++d) out[d] = in[d]; 4535 } else { 4536 for (d = 0; d < dim; ++d) { 4537 out[d] = in[d] - dm->L[d]*floor(PetscRealPart(in[d])/dm->L[d]); 4538 } 4539 } 4540 PetscFunctionReturn(0); 4541 } 4542 4543 #undef __FUNCT__ 4544 #define __FUNCT__ "DMLocalizeCoordinate_Internal" 4545 /* 4546 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. 4547 4548 Input Parameters: 4549 + dm - The DM 4550 . dim - The spatial dimension 4551 . anchor - The anchor point, the input point can be no more than maxCell away from it 4552 - in - The input coordinate point (dim numbers) 4553 4554 Output Parameter: 4555 . out - The localized coordinate point 4556 4557 Level: developer 4558 4559 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 4560 4561 .seealso: DMLocalizeCoordinates(), DMLocalizeAddCoordinate() 4562 */ 4563 PetscErrorCode DMLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4564 { 4565 PetscInt d; 4566 4567 PetscFunctionBegin; 4568 if (!dm->maxCell) { 4569 for (d = 0; d < dim; ++d) out[d] = in[d]; 4570 } else { 4571 for (d = 0; d < dim; ++d) { 4572 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 4573 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4574 } else { 4575 out[d] = in[d]; 4576 } 4577 } 4578 } 4579 PetscFunctionReturn(0); 4580 } 4581 #undef __FUNCT__ 4582 #define __FUNCT__ "DMLocalizeCoordinateReal_Internal" 4583 PetscErrorCode DMLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 4584 { 4585 PetscInt d; 4586 4587 PetscFunctionBegin; 4588 if (!dm->maxCell) { 4589 for (d = 0; d < dim; ++d) out[d] = in[d]; 4590 } else { 4591 for (d = 0; d < dim; ++d) { 4592 if (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d]) { 4593 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4594 } else { 4595 out[d] = in[d]; 4596 } 4597 } 4598 } 4599 PetscFunctionReturn(0); 4600 } 4601 4602 #undef __FUNCT__ 4603 #define __FUNCT__ "DMLocalizeAddCoordinate_Internal" 4604 /* 4605 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. 4606 4607 Input Parameters: 4608 + dm - The DM 4609 . dim - The spatial dimension 4610 . anchor - The anchor point, the input point can be no more than maxCell away from it 4611 . in - The input coordinate delta (dim numbers) 4612 - out - The input coordinate point (dim numbers) 4613 4614 Output Parameter: 4615 . out - The localized coordinate in + out 4616 4617 Level: developer 4618 4619 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 4620 4621 .seealso: DMLocalizeCoordinates(), DMLocalizeCoordinate() 4622 */ 4623 PetscErrorCode DMLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 4624 { 4625 PetscInt d; 4626 4627 PetscFunctionBegin; 4628 if (!dm->maxCell) { 4629 for (d = 0; d < dim; ++d) out[d] += in[d]; 4630 } else { 4631 for (d = 0; d < dim; ++d) { 4632 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 4633 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 4634 } else { 4635 out[d] += in[d]; 4636 } 4637 } 4638 } 4639 PetscFunctionReturn(0); 4640 } 4641 4642 PETSC_EXTERN PetscErrorCode DMPlexGetDepthStratum(DM, PetscInt, PetscInt *, PetscInt *); 4643 PETSC_EXTERN PetscErrorCode DMPlexGetHeightStratum(DM, PetscInt, PetscInt *, PetscInt *); 4644 PETSC_EXTERN PetscErrorCode DMPlexVecGetClosure(DM, PetscSection, Vec, PetscInt, PetscInt *, PetscScalar *[]); 4645 PETSC_EXTERN PetscErrorCode DMPlexVecRestoreClosure(DM, PetscSection, Vec, PetscInt, PetscInt *, PetscScalar *[]); 4646 4647 #undef __FUNCT__ 4648 #define __FUNCT__ "DMGetCoordinatesLocalized" 4649 /*@ 4650 DMGetCoordinatesLocalized - Check if the DM coordinates have been localized for cells 4651 4652 Input Parameter: 4653 . dm - The DM 4654 4655 Output Parameter: 4656 areLocalized - True if localized 4657 4658 Level: developer 4659 4660 .seealso: DMLocalizeCoordinates() 4661 @*/ 4662 PetscErrorCode DMGetCoordinatesLocalized(DM dm,PetscBool *areLocalized) 4663 { 4664 DM cdm; 4665 PetscSection coordSection; 4666 PetscInt cStart, cEnd, c, sStart, sEnd, dof; 4667 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4668 PetscErrorCode ierr; 4669 4670 PetscFunctionBegin; 4671 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4672 if (!dm->maxCell) { 4673 *areLocalized = PETSC_FALSE; 4674 PetscFunctionReturn(0); 4675 } 4676 /* We need some generic way of refering to cells/vertices */ 4677 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4678 { 4679 PetscBool isplex; 4680 4681 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4682 if (isplex) { 4683 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4684 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4685 } 4686 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4687 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4688 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 4689 for (c = cStart; c < cEnd; ++c) { 4690 if (c < sStart || c >= sEnd) { 4691 alreadyLocalized = PETSC_FALSE; 4692 break; 4693 } 4694 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 4695 if (!dof) { 4696 alreadyLocalized = PETSC_FALSE; 4697 break; 4698 } 4699 } 4700 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4701 *areLocalized = alreadyLocalizedGlobal; 4702 PetscFunctionReturn(0); 4703 } 4704 4705 4706 #undef __FUNCT__ 4707 #define __FUNCT__ "DMLocalizeCoordinates" 4708 /*@ 4709 DMLocalizeCoordinates - If a mesh is periodic, create local coordinates for each cell 4710 4711 Input Parameter: 4712 . dm - The DM 4713 4714 Level: developer 4715 4716 .seealso: DMLocalizeCoordinate(), DMLocalizeAddCoordinate() 4717 @*/ 4718 PetscErrorCode DMLocalizeCoordinates(DM dm) 4719 { 4720 DM cdm; 4721 PetscSection coordSection, cSection; 4722 Vec coordinates, cVec; 4723 PetscScalar *coords, *coords2, *anchor; 4724 PetscInt Nc, cStart, cEnd, c, vStart, vEnd, v, sStart, sEnd, dof, d, off, off2, bs, coordSize; 4725 PetscBool alreadyLocalized, alreadyLocalizedGlobal; 4726 PetscErrorCode ierr; 4727 4728 PetscFunctionBegin; 4729 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4730 if (!dm->maxCell) PetscFunctionReturn(0); 4731 /* We need some generic way of refering to cells/vertices */ 4732 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4733 { 4734 PetscBool isplex; 4735 4736 ierr = PetscObjectTypeCompare((PetscObject) cdm, DMPLEX, &isplex);CHKERRQ(ierr); 4737 if (isplex) { 4738 ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4739 ierr = DMPlexGetDepthStratum(cdm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4740 } else SETERRQ(PetscObjectComm((PetscObject) cdm), PETSC_ERR_ARG_WRONG, "Coordinate localization requires a DMPLEX coordinate DM"); 4741 } 4742 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4743 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4744 ierr = PetscSectionGetChart(coordSection,&sStart,&sEnd);CHKERRQ(ierr); 4745 alreadyLocalized = alreadyLocalizedGlobal = PETSC_TRUE; 4746 for (c = cStart; c < cEnd; ++c) { 4747 if (c < sStart || c >= sEnd) { 4748 alreadyLocalized = PETSC_FALSE; 4749 break; 4750 } 4751 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 4752 if (!dof) { 4753 alreadyLocalized = PETSC_FALSE; 4754 break; 4755 } 4756 } 4757 ierr = MPI_Allreduce(&alreadyLocalized,&alreadyLocalizedGlobal,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 4758 if (alreadyLocalizedGlobal) PetscFunctionReturn(0); 4759 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 4760 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 4761 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 4762 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 4763 ierr = PetscSectionSetChart(cSection, cStart, vEnd);CHKERRQ(ierr); 4764 for (v = vStart; v < vEnd; ++v) { 4765 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4766 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 4767 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 4768 } 4769 for (c = cStart; c < cEnd; ++c) { 4770 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, NULL);CHKERRQ(ierr); 4771 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 4772 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 4773 } 4774 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 4775 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 4776 ierr = VecCreate(PetscObjectComm((PetscObject) dm), &cVec);CHKERRQ(ierr); 4777 ierr = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 4778 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 4779 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 4780 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4781 ierr = VecSetType(cVec,VECSTANDARD);CHKERRQ(ierr); 4782 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4783 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 4784 for (v = vStart; v < vEnd; ++v) { 4785 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 4786 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4787 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 4788 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 4789 } 4790 ierr = DMGetWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 4791 for (c = cStart; c < cEnd; ++c) { 4792 PetscScalar *cellCoords = NULL; 4793 PetscInt b; 4794 4795 ierr = DMPlexVecGetClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4796 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 4797 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 4798 for (d = 0; d < dof/bs; ++d) {ierr = DMLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 4799 ierr = DMPlexVecRestoreClosure(cdm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 4800 } 4801 ierr = DMRestoreWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 4802 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4803 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 4804 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 4805 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 4806 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 4807 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 4808 PetscFunctionReturn(0); 4809 } 4810 4811 #undef __FUNCT__ 4812 #define __FUNCT__ "DMLocatePoints" 4813 /*@ 4814 DMLocatePoints - Locate the points in v in the mesh and return a PetscSF of the containing cells 4815 4816 Collective on Vec v (see explanation below) 4817 4818 Input Parameters: 4819 + dm - The DM 4820 . v - The Vec of points 4821 - cells - Points to either NULL, or a PetscSF with guesses for which cells contain each point. 4822 4823 Output Parameter: 4824 . cells - The PetscSF containing the ranks and local indices of the containing points. 4825 4826 4827 Level: developer 4828 4829 To do a search of the local cells of the mesh, v should have PETSC_COMM_SELF as its communicator. 4830 4831 To do a search of all the cells in the distributed mesh, v should have the same communicator as 4832 dm. 4833 4834 If *cellSF is NULL on input, a PetscSF will be created. 4835 4836 If *cellSF is not NULL on input, it should point to an existing PetscSF, whose graph will be used as initial 4837 guesses. 4838 4839 An array that maps each point to its containing cell can be obtained with 4840 4841 const PetscSFNode *cells; 4842 PetscInt nFound; 4843 const PetscSFNode *found; 4844 4845 PetscSFGetGraph(cells,NULL,&nFound,&found,&cells); 4846 4847 Where cells[i].rank is the rank of the cell containing point found[i] (or i if found == NULL), and cells[i].index is 4848 the index of the cell in its rank's local numbering. 4849 4850 .keywords: point location, mesh 4851 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4852 @*/ 4853 PetscErrorCode DMLocatePoints(DM dm, Vec v, PetscSF *cellSF) 4854 { 4855 PetscErrorCode ierr; 4856 4857 PetscFunctionBegin; 4858 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4859 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4860 PetscValidPointer(cellSF,3); 4861 if (*cellSF) { 4862 PetscMPIInt result; 4863 4864 PetscValidHeaderSpecific(cellSF,PETSCSF_CLASSID,3); 4865 ierr = MPI_Comm_compare(PetscObjectComm((PetscObject)v),PetscObjectComm((PetscObject)cellSF),&result);CHKERRQ(ierr); 4866 if (result != MPI_IDENT && result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"cellSF must have a communicator congruent to v's"); 4867 } 4868 else { 4869 ierr = PetscSFCreate(PetscObjectComm((PetscObject)v),cellSF);CHKERRQ(ierr); 4870 } 4871 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4872 if (dm->ops->locatepoints) { 4873 ierr = (*dm->ops->locatepoints)(dm,v,*cellSF);CHKERRQ(ierr); 4874 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4875 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4876 PetscFunctionReturn(0); 4877 } 4878 4879 #undef __FUNCT__ 4880 #define __FUNCT__ "DMGetOutputDM" 4881 /*@ 4882 DMGetOutputDM - Retrieve the DM associated with the layout for output 4883 4884 Input Parameter: 4885 . dm - The original DM 4886 4887 Output Parameter: 4888 . odm - The DM which provides the layout for output 4889 4890 Level: intermediate 4891 4892 .seealso: VecView(), DMGetDefaultGlobalSection() 4893 @*/ 4894 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4895 { 4896 PetscSection section; 4897 PetscBool hasConstraints; 4898 PetscErrorCode ierr; 4899 4900 PetscFunctionBegin; 4901 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4902 PetscValidPointer(odm,2); 4903 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4904 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4905 if (!hasConstraints) { 4906 *odm = dm; 4907 PetscFunctionReturn(0); 4908 } 4909 if (!dm->dmBC) { 4910 PetscDS ds; 4911 PetscSection newSection, gsection; 4912 PetscSF sf; 4913 4914 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4915 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 4916 ierr = DMSetDS(dm->dmBC, ds);CHKERRQ(ierr); 4917 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4918 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4919 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4920 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4921 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 4922 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4923 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4924 } 4925 *odm = dm->dmBC; 4926 PetscFunctionReturn(0); 4927 } 4928 4929 #undef __FUNCT__ 4930 #define __FUNCT__ "DMGetOutputSequenceNumber" 4931 /*@ 4932 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 4933 4934 Input Parameter: 4935 . dm - The original DM 4936 4937 Output Parameters: 4938 + num - The output sequence number 4939 - val - The output sequence value 4940 4941 Level: intermediate 4942 4943 Note: This is intended for output that should appear in sequence, for instance 4944 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4945 4946 .seealso: VecView() 4947 @*/ 4948 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 4949 { 4950 PetscFunctionBegin; 4951 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4952 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 4953 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 4954 PetscFunctionReturn(0); 4955 } 4956 4957 #undef __FUNCT__ 4958 #define __FUNCT__ "DMSetOutputSequenceNumber" 4959 /*@ 4960 DMSetOutputSequenceNumber - Set the sequence number/value for output 4961 4962 Input Parameters: 4963 + dm - The original DM 4964 . num - The output sequence number 4965 - val - The output sequence value 4966 4967 Level: intermediate 4968 4969 Note: This is intended for output that should appear in sequence, for instance 4970 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4971 4972 .seealso: VecView() 4973 @*/ 4974 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 4975 { 4976 PetscFunctionBegin; 4977 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4978 dm->outputSequenceNum = num; 4979 dm->outputSequenceVal = val; 4980 PetscFunctionReturn(0); 4981 } 4982 4983 #undef __FUNCT__ 4984 #define __FUNCT__ "DMOutputSequenceLoad" 4985 /*@C 4986 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 4987 4988 Input Parameters: 4989 + dm - The original DM 4990 . name - The sequence name 4991 - num - The output sequence number 4992 4993 Output Parameter: 4994 . val - The output sequence value 4995 4996 Level: intermediate 4997 4998 Note: This is intended for output that should appear in sequence, for instance 4999 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 5000 5001 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 5002 @*/ 5003 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 5004 { 5005 PetscBool ishdf5; 5006 PetscErrorCode ierr; 5007 5008 PetscFunctionBegin; 5009 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 5010 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 5011 PetscValidPointer(val,4); 5012 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 5013 if (ishdf5) { 5014 #if defined(PETSC_HAVE_HDF5) 5015 PetscScalar value; 5016 5017 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 5018 *val = PetscRealPart(value); 5019 #endif 5020 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 5021 PetscFunctionReturn(0); 5022 } 5023 5024 #undef __FUNCT__ 5025 #define __FUNCT__ "DMGetUseNatural" 5026 /*@ 5027 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 5028 5029 Not collective 5030 5031 Input Parameter: 5032 . dm - The DM 5033 5034 Output Parameter: 5035 . useNatural - The flag to build the mapping to a natural order during distribution 5036 5037 Level: beginner 5038 5039 .seealso: DMSetUseNatural(), DMCreate() 5040 @*/ 5041 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 5042 { 5043 PetscFunctionBegin; 5044 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5045 PetscValidPointer(useNatural, 2); 5046 *useNatural = dm->useNatural; 5047 PetscFunctionReturn(0); 5048 } 5049 5050 #undef __FUNCT__ 5051 #define __FUNCT__ "DMSetUseNatural" 5052 /*@ 5053 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 5054 5055 Collective on dm 5056 5057 Input Parameters: 5058 + dm - The DM 5059 - useNatural - The flag to build the mapping to a natural order during distribution 5060 5061 Level: beginner 5062 5063 .seealso: DMGetUseNatural(), DMCreate() 5064 @*/ 5065 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 5066 { 5067 PetscFunctionBegin; 5068 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5069 PetscValidLogicalCollectiveInt(dm, useNatural, 2); 5070 dm->useNatural = useNatural; 5071 PetscFunctionReturn(0); 5072 } 5073 5074 #undef __FUNCT__ 5075 #define __FUNCT__ 5076 5077 #undef __FUNCT__ 5078 #define __FUNCT__ "DMCreateLabel" 5079 /*@C 5080 DMCreateLabel - Create a label of the given name if it does not already exist 5081 5082 Not Collective 5083 5084 Input Parameters: 5085 + dm - The DM object 5086 - name - The label name 5087 5088 Level: intermediate 5089 5090 .keywords: mesh 5091 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5092 @*/ 5093 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 5094 { 5095 DMLabelLink next = dm->labels->next; 5096 PetscBool flg = PETSC_FALSE; 5097 PetscErrorCode ierr; 5098 5099 PetscFunctionBegin; 5100 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5101 PetscValidCharPointer(name, 2); 5102 while (next) { 5103 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5104 if (flg) break; 5105 next = next->next; 5106 } 5107 if (!flg) { 5108 DMLabelLink tmpLabel; 5109 5110 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5111 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 5112 tmpLabel->output = PETSC_TRUE; 5113 tmpLabel->next = dm->labels->next; 5114 dm->labels->next = tmpLabel; 5115 } 5116 PetscFunctionReturn(0); 5117 } 5118 5119 #undef __FUNCT__ 5120 #define __FUNCT__ "DMGetLabelValue" 5121 /*@C 5122 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 5123 5124 Not Collective 5125 5126 Input Parameters: 5127 + dm - The DM object 5128 . name - The label name 5129 - point - The mesh point 5130 5131 Output Parameter: 5132 . value - The label value for this point, or -1 if the point is not in the label 5133 5134 Level: beginner 5135 5136 .keywords: mesh 5137 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 5138 @*/ 5139 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 5140 { 5141 DMLabel label; 5142 PetscErrorCode ierr; 5143 5144 PetscFunctionBegin; 5145 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5146 PetscValidCharPointer(name, 2); 5147 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5148 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);CHKERRQ(ierr); 5149 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 5150 PetscFunctionReturn(0); 5151 } 5152 5153 #undef __FUNCT__ 5154 #define __FUNCT__ "DMSetLabelValue" 5155 /*@C 5156 DMSetLabelValue - Add a point to a Sieve Label with given value 5157 5158 Not Collective 5159 5160 Input Parameters: 5161 + dm - The DM object 5162 . name - The label name 5163 . point - The mesh point 5164 - value - The label value for this point 5165 5166 Output Parameter: 5167 5168 Level: beginner 5169 5170 .keywords: mesh 5171 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 5172 @*/ 5173 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5174 { 5175 DMLabel label; 5176 PetscErrorCode ierr; 5177 5178 PetscFunctionBegin; 5179 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5180 PetscValidCharPointer(name, 2); 5181 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5182 if (!label) { 5183 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 5184 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5185 } 5186 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 5187 PetscFunctionReturn(0); 5188 } 5189 5190 #undef __FUNCT__ 5191 #define __FUNCT__ "DMClearLabelValue" 5192 /*@C 5193 DMClearLabelValue - Remove a point from a Sieve Label with given value 5194 5195 Not Collective 5196 5197 Input Parameters: 5198 + dm - The DM object 5199 . name - The label name 5200 . point - The mesh point 5201 - value - The label value for this point 5202 5203 Output Parameter: 5204 5205 Level: beginner 5206 5207 .keywords: mesh 5208 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 5209 @*/ 5210 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 5211 { 5212 DMLabel label; 5213 PetscErrorCode ierr; 5214 5215 PetscFunctionBegin; 5216 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5217 PetscValidCharPointer(name, 2); 5218 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5219 if (!label) PetscFunctionReturn(0); 5220 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 5221 PetscFunctionReturn(0); 5222 } 5223 5224 #undef __FUNCT__ 5225 #define __FUNCT__ "DMGetLabelSize" 5226 /*@C 5227 DMGetLabelSize - Get the number of different integer ids in a Label 5228 5229 Not Collective 5230 5231 Input Parameters: 5232 + dm - The DM object 5233 - name - The label name 5234 5235 Output Parameter: 5236 . size - The number of different integer ids, or 0 if the label does not exist 5237 5238 Level: beginner 5239 5240 .keywords: mesh 5241 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 5242 @*/ 5243 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 5244 { 5245 DMLabel label; 5246 PetscErrorCode ierr; 5247 5248 PetscFunctionBegin; 5249 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5250 PetscValidCharPointer(name, 2); 5251 PetscValidPointer(size, 3); 5252 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5253 *size = 0; 5254 if (!label) PetscFunctionReturn(0); 5255 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 5256 PetscFunctionReturn(0); 5257 } 5258 5259 #undef __FUNCT__ 5260 #define __FUNCT__ "DMGetLabelIdIS" 5261 /*@C 5262 DMGetLabelIdIS - Get the integer ids in a label 5263 5264 Not Collective 5265 5266 Input Parameters: 5267 + mesh - The DM object 5268 - name - The label name 5269 5270 Output Parameter: 5271 . ids - The integer ids, or NULL if the label does not exist 5272 5273 Level: beginner 5274 5275 .keywords: mesh 5276 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 5277 @*/ 5278 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 5279 { 5280 DMLabel label; 5281 PetscErrorCode ierr; 5282 5283 PetscFunctionBegin; 5284 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5285 PetscValidCharPointer(name, 2); 5286 PetscValidPointer(ids, 3); 5287 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5288 *ids = NULL; 5289 if (!label) PetscFunctionReturn(0); 5290 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 5291 PetscFunctionReturn(0); 5292 } 5293 5294 #undef __FUNCT__ 5295 #define __FUNCT__ "DMGetStratumSize" 5296 /*@C 5297 DMGetStratumSize - Get the number of points in a label stratum 5298 5299 Not Collective 5300 5301 Input Parameters: 5302 + dm - The DM object 5303 . name - The label name 5304 - value - The stratum value 5305 5306 Output Parameter: 5307 . size - The stratum size 5308 5309 Level: beginner 5310 5311 .keywords: mesh 5312 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 5313 @*/ 5314 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 5315 { 5316 DMLabel label; 5317 PetscErrorCode ierr; 5318 5319 PetscFunctionBegin; 5320 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5321 PetscValidCharPointer(name, 2); 5322 PetscValidPointer(size, 4); 5323 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5324 *size = 0; 5325 if (!label) PetscFunctionReturn(0); 5326 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 5327 PetscFunctionReturn(0); 5328 } 5329 5330 #undef __FUNCT__ 5331 #define __FUNCT__ "DMGetStratumIS" 5332 /*@C 5333 DMGetStratumIS - Get the points in a label stratum 5334 5335 Not Collective 5336 5337 Input Parameters: 5338 + dm - The DM object 5339 . name - The label name 5340 - value - The stratum value 5341 5342 Output Parameter: 5343 . points - The stratum points, or NULL if the label does not exist or does not have that value 5344 5345 Level: beginner 5346 5347 .keywords: mesh 5348 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 5349 @*/ 5350 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 5351 { 5352 DMLabel label; 5353 PetscErrorCode ierr; 5354 5355 PetscFunctionBegin; 5356 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5357 PetscValidCharPointer(name, 2); 5358 PetscValidPointer(points, 4); 5359 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5360 *points = NULL; 5361 if (!label) PetscFunctionReturn(0); 5362 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 5363 PetscFunctionReturn(0); 5364 } 5365 5366 #undef __FUNCT__ 5367 #define __FUNCT__ "DMClearLabelStratum" 5368 /*@C 5369 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 5370 5371 Not Collective 5372 5373 Input Parameters: 5374 + dm - The DM object 5375 . name - The label name 5376 - value - The label value for this point 5377 5378 Output Parameter: 5379 5380 Level: beginner 5381 5382 .keywords: mesh 5383 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 5384 @*/ 5385 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 5386 { 5387 DMLabel label; 5388 PetscErrorCode ierr; 5389 5390 PetscFunctionBegin; 5391 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5392 PetscValidCharPointer(name, 2); 5393 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 5394 if (!label) PetscFunctionReturn(0); 5395 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 5396 PetscFunctionReturn(0); 5397 } 5398 5399 #undef __FUNCT__ 5400 #define __FUNCT__ "DMGetNumLabels" 5401 /*@ 5402 DMGetNumLabels - Return the number of labels defined by the mesh 5403 5404 Not Collective 5405 5406 Input Parameter: 5407 . dm - The DM object 5408 5409 Output Parameter: 5410 . numLabels - the number of Labels 5411 5412 Level: intermediate 5413 5414 .keywords: mesh 5415 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5416 @*/ 5417 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 5418 { 5419 DMLabelLink next = dm->labels->next; 5420 PetscInt n = 0; 5421 5422 PetscFunctionBegin; 5423 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5424 PetscValidPointer(numLabels, 2); 5425 while (next) {++n; next = next->next;} 5426 *numLabels = n; 5427 PetscFunctionReturn(0); 5428 } 5429 5430 #undef __FUNCT__ 5431 #define __FUNCT__ "DMGetLabelName" 5432 /*@C 5433 DMGetLabelName - Return the name of nth label 5434 5435 Not Collective 5436 5437 Input Parameters: 5438 + dm - The DM object 5439 - n - the label number 5440 5441 Output Parameter: 5442 . name - the label name 5443 5444 Level: intermediate 5445 5446 .keywords: mesh 5447 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5448 @*/ 5449 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 5450 { 5451 DMLabelLink next = dm->labels->next; 5452 PetscInt l = 0; 5453 5454 PetscFunctionBegin; 5455 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5456 PetscValidPointer(name, 3); 5457 while (next) { 5458 if (l == n) { 5459 *name = next->label->name; 5460 PetscFunctionReturn(0); 5461 } 5462 ++l; 5463 next = next->next; 5464 } 5465 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5466 } 5467 5468 #undef __FUNCT__ 5469 #define __FUNCT__ "DMHasLabel" 5470 /*@C 5471 DMHasLabel - Determine whether the mesh has a label of a given name 5472 5473 Not Collective 5474 5475 Input Parameters: 5476 + dm - The DM object 5477 - name - The label name 5478 5479 Output Parameter: 5480 . hasLabel - PETSC_TRUE if the label is present 5481 5482 Level: intermediate 5483 5484 .keywords: mesh 5485 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5486 @*/ 5487 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 5488 { 5489 DMLabelLink next = dm->labels->next; 5490 PetscErrorCode ierr; 5491 5492 PetscFunctionBegin; 5493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5494 PetscValidCharPointer(name, 2); 5495 PetscValidPointer(hasLabel, 3); 5496 *hasLabel = PETSC_FALSE; 5497 while (next) { 5498 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 5499 if (*hasLabel) break; 5500 next = next->next; 5501 } 5502 PetscFunctionReturn(0); 5503 } 5504 5505 #undef __FUNCT__ 5506 #define __FUNCT__ "DMGetLabel" 5507 /*@C 5508 DMGetLabel - Return the label of a given name, or NULL 5509 5510 Not Collective 5511 5512 Input Parameters: 5513 + dm - The DM object 5514 - name - The label name 5515 5516 Output Parameter: 5517 . label - The DMLabel, or NULL if the label is absent 5518 5519 Level: intermediate 5520 5521 .keywords: mesh 5522 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5523 @*/ 5524 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 5525 { 5526 DMLabelLink next = dm->labels->next; 5527 PetscBool hasLabel; 5528 PetscErrorCode ierr; 5529 5530 PetscFunctionBegin; 5531 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5532 PetscValidCharPointer(name, 2); 5533 PetscValidPointer(label, 3); 5534 *label = NULL; 5535 while (next) { 5536 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5537 if (hasLabel) { 5538 *label = next->label; 5539 break; 5540 } 5541 next = next->next; 5542 } 5543 PetscFunctionReturn(0); 5544 } 5545 5546 #undef __FUNCT__ 5547 #define __FUNCT__ "DMGetLabelByNum" 5548 /*@C 5549 DMGetLabelByNum - Return the nth label 5550 5551 Not Collective 5552 5553 Input Parameters: 5554 + dm - The DM object 5555 - n - the label number 5556 5557 Output Parameter: 5558 . label - the label 5559 5560 Level: intermediate 5561 5562 .keywords: mesh 5563 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5564 @*/ 5565 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5566 { 5567 DMLabelLink next = dm->labels->next; 5568 PetscInt l = 0; 5569 5570 PetscFunctionBegin; 5571 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5572 PetscValidPointer(label, 3); 5573 while (next) { 5574 if (l == n) { 5575 *label = next->label; 5576 PetscFunctionReturn(0); 5577 } 5578 ++l; 5579 next = next->next; 5580 } 5581 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5582 } 5583 5584 #undef __FUNCT__ 5585 #define __FUNCT__ "DMAddLabel" 5586 /*@C 5587 DMAddLabel - Add the label to this mesh 5588 5589 Not Collective 5590 5591 Input Parameters: 5592 + dm - The DM object 5593 - label - The DMLabel 5594 5595 Level: developer 5596 5597 .keywords: mesh 5598 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5599 @*/ 5600 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5601 { 5602 DMLabelLink tmpLabel; 5603 PetscBool hasLabel; 5604 PetscErrorCode ierr; 5605 5606 PetscFunctionBegin; 5607 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5608 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5609 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5610 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5611 tmpLabel->label = label; 5612 tmpLabel->output = PETSC_TRUE; 5613 tmpLabel->next = dm->labels->next; 5614 dm->labels->next = tmpLabel; 5615 PetscFunctionReturn(0); 5616 } 5617 5618 #undef __FUNCT__ 5619 #define __FUNCT__ "DMRemoveLabel" 5620 /*@C 5621 DMRemoveLabel - Remove the label from this mesh 5622 5623 Not Collective 5624 5625 Input Parameters: 5626 + dm - The DM object 5627 - name - The label name 5628 5629 Output Parameter: 5630 . label - The DMLabel, or NULL if the label is absent 5631 5632 Level: developer 5633 5634 .keywords: mesh 5635 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5636 @*/ 5637 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5638 { 5639 DMLabelLink next = dm->labels->next; 5640 DMLabelLink last = NULL; 5641 PetscBool hasLabel; 5642 PetscErrorCode ierr; 5643 5644 PetscFunctionBegin; 5645 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5646 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5647 *label = NULL; 5648 if (!hasLabel) PetscFunctionReturn(0); 5649 while (next) { 5650 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5651 if (hasLabel) { 5652 if (last) last->next = next->next; 5653 else dm->labels->next = next->next; 5654 next->next = NULL; 5655 *label = next->label; 5656 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5657 if (hasLabel) { 5658 dm->depthLabel = NULL; 5659 } 5660 ierr = PetscFree(next);CHKERRQ(ierr); 5661 break; 5662 } 5663 last = next; 5664 next = next->next; 5665 } 5666 PetscFunctionReturn(0); 5667 } 5668 5669 #undef __FUNCT__ 5670 #define __FUNCT__ "DMGetLabelOutput" 5671 /*@C 5672 DMGetLabelOutput - Get the output flag for a given label 5673 5674 Not Collective 5675 5676 Input Parameters: 5677 + dm - The DM object 5678 - name - The label name 5679 5680 Output Parameter: 5681 . output - The flag for output 5682 5683 Level: developer 5684 5685 .keywords: mesh 5686 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5687 @*/ 5688 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5689 { 5690 DMLabelLink next = dm->labels->next; 5691 PetscErrorCode ierr; 5692 5693 PetscFunctionBegin; 5694 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5695 PetscValidPointer(name, 2); 5696 PetscValidPointer(output, 3); 5697 while (next) { 5698 PetscBool flg; 5699 5700 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5701 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5702 next = next->next; 5703 } 5704 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5705 } 5706 5707 #undef __FUNCT__ 5708 #define __FUNCT__ "DMSetLabelOutput" 5709 /*@C 5710 DMSetLabelOutput - Set the output flag for a given label 5711 5712 Not Collective 5713 5714 Input Parameters: 5715 + dm - The DM object 5716 . name - The label name 5717 - output - The flag for output 5718 5719 Level: developer 5720 5721 .keywords: mesh 5722 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5723 @*/ 5724 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 5725 { 5726 DMLabelLink next = dm->labels->next; 5727 PetscErrorCode ierr; 5728 5729 PetscFunctionBegin; 5730 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5731 PetscValidPointer(name, 2); 5732 while (next) { 5733 PetscBool flg; 5734 5735 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5736 if (flg) {next->output = output; PetscFunctionReturn(0);} 5737 next = next->next; 5738 } 5739 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5740 } 5741 5742 5743 #undef __FUNCT__ 5744 #define __FUNCT__ "DMCopyLabels" 5745 /*@ 5746 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 5747 5748 Collective on DM 5749 5750 Input Parameter: 5751 . dmA - The DM object with initial labels 5752 5753 Output Parameter: 5754 . dmB - The DM object with copied labels 5755 5756 Level: intermediate 5757 5758 Note: This is typically used when interpolating or otherwise adding to a mesh 5759 5760 .keywords: mesh 5761 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 5762 @*/ 5763 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 5764 { 5765 PetscInt numLabels, l; 5766 PetscErrorCode ierr; 5767 5768 PetscFunctionBegin; 5769 if (dmA == dmB) PetscFunctionReturn(0); 5770 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 5771 for (l = 0; l < numLabels; ++l) { 5772 DMLabel label, labelNew; 5773 const char *name; 5774 PetscBool flg; 5775 5776 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 5777 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 5778 if (flg) continue; 5779 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 5780 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 5781 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 5782 } 5783 PetscFunctionReturn(0); 5784 } 5785 5786 #undef __FUNCT__ 5787 #define __FUNCT__ "DMGetCoarseDM" 5788 /*@ 5789 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5790 5791 Input Parameter: 5792 . dm - The DM object 5793 5794 Output Parameter: 5795 . cdm - The coarse DM 5796 5797 Level: intermediate 5798 5799 .seealso: DMSetCoarseDM() 5800 @*/ 5801 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 5802 { 5803 PetscFunctionBegin; 5804 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5805 PetscValidPointer(cdm, 2); 5806 *cdm = dm->coarseMesh; 5807 PetscFunctionReturn(0); 5808 } 5809 5810 #undef __FUNCT__ 5811 #define __FUNCT__ "DMSetCoarseDM" 5812 /*@ 5813 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5814 5815 Input Parameters: 5816 + dm - The DM object 5817 - cdm - The coarse DM 5818 5819 Level: intermediate 5820 5821 .seealso: DMGetCoarseDM() 5822 @*/ 5823 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 5824 { 5825 PetscErrorCode ierr; 5826 5827 PetscFunctionBegin; 5828 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5829 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5830 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5831 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 5832 dm->coarseMesh = cdm; 5833 PetscFunctionReturn(0); 5834 } 5835 5836 #undef __FUNCT__ 5837 #define __FUNCT__ "DMGetFineDM" 5838 /*@ 5839 DMGetFineDM - Get the fine mesh from which this was obtained by refinement 5840 5841 Input Parameter: 5842 . dm - The DM object 5843 5844 Output Parameter: 5845 . fdm - The fine DM 5846 5847 Level: intermediate 5848 5849 .seealso: DMSetFineDM() 5850 @*/ 5851 PetscErrorCode DMGetFineDM(DM dm, DM *fdm) 5852 { 5853 PetscFunctionBegin; 5854 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5855 PetscValidPointer(fdm, 2); 5856 *fdm = dm->fineMesh; 5857 PetscFunctionReturn(0); 5858 } 5859 5860 #undef __FUNCT__ 5861 #define __FUNCT__ "DMSetFineDM" 5862 /*@ 5863 DMSetFineDM - Set the fine mesh from which this was obtained by refinement 5864 5865 Input Parameters: 5866 + dm - The DM object 5867 - fdm - The fine DM 5868 5869 Level: intermediate 5870 5871 .seealso: DMGetFineDM() 5872 @*/ 5873 PetscErrorCode DMSetFineDM(DM dm, DM fdm) 5874 { 5875 PetscErrorCode ierr; 5876 5877 PetscFunctionBegin; 5878 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5879 if (fdm) PetscValidHeaderSpecific(fdm, DM_CLASSID, 2); 5880 ierr = PetscObjectReference((PetscObject)fdm);CHKERRQ(ierr); 5881 ierr = DMDestroy(&dm->fineMesh);CHKERRQ(ierr); 5882 dm->fineMesh = fdm; 5883 PetscFunctionReturn(0); 5884 } 5885 5886 /*=== DMBoundary code ===*/ 5887 5888 #undef __FUNCT__ 5889 #define __FUNCT__ "DMBoundaryDuplicate" 5890 PetscErrorCode DMBoundaryDuplicate(DMBoundaryLinkList bd, DMBoundaryLinkList *boundary) 5891 { 5892 DMBoundary b = bd->next, b2, bold = NULL; 5893 PetscErrorCode ierr; 5894 5895 PetscFunctionBegin; 5896 ierr = PetscNew(boundary);CHKERRQ(ierr); 5897 (*boundary)->refct = 1; 5898 (*boundary)->next = NULL; 5899 for (; b; b = b->next, bold = b2) { 5900 ierr = PetscNew(&b2);CHKERRQ(ierr); 5901 ierr = PetscStrallocpy(b->name, (char **) &b2->name);CHKERRQ(ierr); 5902 ierr = PetscStrallocpy(b->labelname, (char **) &b2->labelname);CHKERRQ(ierr); 5903 ierr = PetscMalloc1(b->numids, &b2->ids);CHKERRQ(ierr); 5904 ierr = PetscMemcpy(b2->ids, b->ids, b->numids*sizeof(PetscInt));CHKERRQ(ierr); 5905 ierr = PetscMalloc1(b->numcomps, &b2->comps);CHKERRQ(ierr); 5906 ierr = PetscMemcpy(b2->comps, b->comps, b->numcomps*sizeof(PetscInt));CHKERRQ(ierr); 5907 b2->label = NULL; 5908 b2->essential = b->essential; 5909 b2->field = b->field; 5910 b2->numcomps = b->numcomps; 5911 b2->func = b->func; 5912 b2->numids = b->numids; 5913 b2->ctx = b->ctx; 5914 b2->next = NULL; 5915 if (!(*boundary)->next) (*boundary)->next = b2; 5916 if (bold) bold->next = b2; 5917 } 5918 PetscFunctionReturn(0); 5919 } 5920 5921 #undef __FUNCT__ 5922 #define __FUNCT__ "DMBoundaryDestroy" 5923 PetscErrorCode DMBoundaryDestroy(DMBoundaryLinkList *boundary) 5924 { 5925 DMBoundary b, next; 5926 PetscErrorCode ierr; 5927 5928 PetscFunctionBegin; 5929 if (!boundary) PetscFunctionReturn(0); 5930 if (--((*boundary)->refct)) { 5931 *boundary = NULL; 5932 PetscFunctionReturn(0); 5933 } 5934 b = (*boundary)->next; 5935 for (; b; b = next) { 5936 next = b->next; 5937 ierr = PetscFree(b->comps);CHKERRQ(ierr); 5938 ierr = PetscFree(b->ids);CHKERRQ(ierr); 5939 ierr = PetscFree(b->name);CHKERRQ(ierr); 5940 ierr = PetscFree(b->labelname);CHKERRQ(ierr); 5941 ierr = PetscFree(b);CHKERRQ(ierr); 5942 } 5943 ierr = PetscFree(*boundary);CHKERRQ(ierr); 5944 PetscFunctionReturn(0); 5945 } 5946 5947 #undef __FUNCT__ 5948 #define __FUNCT__ "DMCopyBoundary" 5949 PetscErrorCode DMCopyBoundary(DM dm, DM dmNew) 5950 { 5951 DMBoundary b; 5952 PetscErrorCode ierr; 5953 5954 PetscFunctionBegin; 5955 ierr = DMBoundaryDestroy(&dmNew->boundary);CHKERRQ(ierr); 5956 ierr = DMBoundaryDuplicate(dm->boundary, &dmNew->boundary);CHKERRQ(ierr); 5957 for (b = dmNew->boundary->next; b; b = b->next) { 5958 if (b->labelname) { 5959 ierr = DMGetLabel(dmNew, b->labelname, &b->label);CHKERRQ(ierr); 5960 if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 5961 } 5962 } 5963 PetscFunctionReturn(0); 5964 } 5965 5966 #undef __FUNCT__ 5967 #define __FUNCT__ "DMAddBoundary" 5968 /*@C 5969 DMAddBoundary - Add a boundary condition to the model 5970 5971 Input Parameters: 5972 + dm - The mesh object 5973 . isEssential - Flag for an essential (Dirichlet) condition, as opposed to a natural (Neumann) condition 5974 . name - The BC name 5975 . labelname - The label defining constrained points 5976 . field - The field to constrain 5977 . numcomps - The number of constrained field components 5978 . comps - An array of constrained component numbers 5979 . bcFunc - A pointwise function giving boundary values 5980 . numids - The number of DMLabel ids for constrained points 5981 . ids - An array of ids for constrained points 5982 - ctx - An optional user context for bcFunc 5983 5984 Options Database Keys: 5985 + -bc_<boundary name> <num> - Overrides the boundary ids 5986 - -bc_<boundary name>_comp <num> - Overrides the boundary components 5987 5988 Level: developer 5989 5990 .seealso: DMGetBoundary() 5991 @*/ 5992 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) 5993 { 5994 DMBoundary b; 5995 PetscErrorCode ierr; 5996 5997 PetscFunctionBegin; 5998 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5999 ierr = PetscNew(&b);CHKERRQ(ierr); 6000 ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); 6001 ierr = PetscStrallocpy(labelname, (char **) &b->labelname);CHKERRQ(ierr); 6002 ierr = PetscMalloc1(numcomps, &b->comps);CHKERRQ(ierr); 6003 if (numcomps) {ierr = PetscMemcpy(b->comps, comps, numcomps*sizeof(PetscInt));CHKERRQ(ierr);} 6004 ierr = PetscMalloc1(numids, &b->ids);CHKERRQ(ierr); 6005 if (numids) {ierr = PetscMemcpy(b->ids, ids, numids*sizeof(PetscInt));CHKERRQ(ierr);} 6006 if (b->labelname) { 6007 ierr = DMGetLabel(dm, b->labelname, &b->label);CHKERRQ(ierr); 6008 if (!b->label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s does not exist in this DM", b->labelname); 6009 } 6010 b->essential = isEssential; 6011 b->field = field; 6012 b->numcomps = numcomps; 6013 b->func = bcFunc; 6014 b->numids = numids; 6015 b->ctx = ctx; 6016 b->next = dm->boundary->next; 6017 dm->boundary->next = b; 6018 PetscFunctionReturn(0); 6019 } 6020 6021 #undef __FUNCT__ 6022 #define __FUNCT__ "DMGetNumBoundary" 6023 /*@ 6024 DMGetNumBoundary - Get the number of registered BC 6025 6026 Input Parameters: 6027 . dm - The mesh object 6028 6029 Output Parameters: 6030 . numBd - The number of BC 6031 6032 Level: intermediate 6033 6034 .seealso: DMAddBoundary(), DMGetBoundary() 6035 @*/ 6036 PetscErrorCode DMGetNumBoundary(DM dm, PetscInt *numBd) 6037 { 6038 DMBoundary b = dm->boundary->next; 6039 6040 PetscFunctionBegin; 6041 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6042 PetscValidPointer(numBd, 2); 6043 *numBd = 0; 6044 while (b) {++(*numBd); b = b->next;} 6045 PetscFunctionReturn(0); 6046 } 6047 6048 #undef __FUNCT__ 6049 #define __FUNCT__ "DMGetBoundary" 6050 /*@C 6051 DMGetBoundary - Add a boundary condition to the model 6052 6053 Input Parameters: 6054 + dm - The mesh object 6055 - bd - The BC number 6056 6057 Output Parameters: 6058 + isEssential - Flag for an essential (Dirichlet) condition, as opposed to a natural (Neumann) condition 6059 . name - The BC name 6060 . labelname - The label defining constrained points 6061 . field - The field to constrain 6062 . numcomps - The number of constrained field components 6063 . comps - An array of constrained component numbers 6064 . bcFunc - A pointwise function giving boundary values 6065 . numids - The number of DMLabel ids for constrained points 6066 . ids - An array of ids for constrained points 6067 - ctx - An optional user context for bcFunc 6068 6069 Options Database Keys: 6070 + -bc_<boundary name> <num> - Overrides the boundary ids 6071 - -bc_<boundary name>_comp <num> - Overrides the boundary components 6072 6073 Level: developer 6074 6075 .seealso: DMAddBoundary() 6076 @*/ 6077 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) 6078 { 6079 DMBoundary b = dm->boundary->next; 6080 PetscInt n = 0; 6081 6082 PetscFunctionBegin; 6083 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6084 while (b) { 6085 if (n == bd) break; 6086 b = b->next; 6087 ++n; 6088 } 6089 if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n); 6090 if (isEssential) { 6091 PetscValidPointer(isEssential, 3); 6092 *isEssential = b->essential; 6093 } 6094 if (name) { 6095 PetscValidPointer(name, 4); 6096 *name = b->name; 6097 } 6098 if (labelname) { 6099 PetscValidPointer(labelname, 5); 6100 *labelname = b->labelname; 6101 } 6102 if (field) { 6103 PetscValidPointer(field, 6); 6104 *field = b->field; 6105 } 6106 if (numcomps) { 6107 PetscValidPointer(numcomps, 7); 6108 *numcomps = b->numcomps; 6109 } 6110 if (comps) { 6111 PetscValidPointer(comps, 8); 6112 *comps = b->comps; 6113 } 6114 if (func) { 6115 PetscValidPointer(func, 9); 6116 *func = b->func; 6117 } 6118 if (numids) { 6119 PetscValidPointer(numids, 10); 6120 *numids = b->numids; 6121 } 6122 if (ids) { 6123 PetscValidPointer(ids, 11); 6124 *ids = b->ids; 6125 } 6126 if (ctx) { 6127 PetscValidPointer(ctx, 12); 6128 *ctx = b->ctx; 6129 } 6130 PetscFunctionReturn(0); 6131 } 6132 6133 #undef __FUNCT__ 6134 #define __FUNCT__ "DMIsBoundaryPoint" 6135 PetscErrorCode DMIsBoundaryPoint(DM dm, PetscInt point, PetscBool *isBd) 6136 { 6137 DMBoundary b = dm->boundary->next; 6138 PetscErrorCode ierr; 6139 6140 PetscFunctionBegin; 6141 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6142 PetscValidPointer(isBd, 3); 6143 *isBd = PETSC_FALSE; 6144 while (b && !(*isBd)) { 6145 if (b->label) { 6146 PetscInt i; 6147 6148 for (i = 0; i < b->numids && !(*isBd); ++i) { 6149 ierr = DMLabelStratumHasPoint(b->label, b->ids[i], point, isBd);CHKERRQ(ierr); 6150 } 6151 } 6152 b = b->next; 6153 } 6154 PetscFunctionReturn(0); 6155 } 6156 6157 #undef __FUNCT__ 6158 #define __FUNCT__ "DMProjectFunction" 6159 /*@C 6160 DMProjectFunction - This projects the given function into the function space provided. 6161 6162 Input Parameters: 6163 + dm - The DM 6164 . time - The time 6165 . funcs - The coordinate functions to evaluate, one per field 6166 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 6167 - mode - The insertion mode for values 6168 6169 Output Parameter: 6170 . X - vector 6171 6172 Calling sequence of func: 6173 $ func(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar u[], void *ctx); 6174 6175 + dim - The spatial dimension 6176 . x - The coordinates 6177 . Nf - The number of fields 6178 . u - The output field values 6179 - ctx - optional user-defined function context 6180 6181 Level: developer 6182 6183 .seealso: DMComputeL2Diff() 6184 @*/ 6185 PetscErrorCode DMProjectFunction(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 6186 { 6187 Vec localX; 6188 PetscErrorCode ierr; 6189 6190 PetscFunctionBegin; 6191 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6192 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 6193 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6194 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 6195 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 6196 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 6197 PetscFunctionReturn(0); 6198 } 6199 6200 #undef __FUNCT__ 6201 #define __FUNCT__ "DMProjectFunctionLocal" 6202 PetscErrorCode DMProjectFunctionLocal(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 6203 { 6204 PetscErrorCode ierr; 6205 6206 PetscFunctionBegin; 6207 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6208 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6209 if (!dm->ops->projectfunctionlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLocal",((PetscObject)dm)->type_name); 6210 ierr = (dm->ops->projectfunctionlocal) (dm, time, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6211 PetscFunctionReturn(0); 6212 } 6213 6214 #undef __FUNCT__ 6215 #define __FUNCT__ "DMProjectFieldLocal" 6216 PetscErrorCode DMProjectFieldLocal(DM dm, Vec localU, 6217 void (**funcs)(PetscInt, PetscInt, PetscInt, 6218 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6219 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 6220 PetscReal, const PetscReal[], PetscScalar[]), 6221 InsertMode mode, Vec localX) 6222 { 6223 PetscErrorCode ierr; 6224 6225 PetscFunctionBegin; 6226 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6227 PetscValidHeaderSpecific(localU,VEC_CLASSID,2); 6228 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6229 if (!dm->ops->projectfieldlocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFieldLocal",((PetscObject)dm)->type_name); 6230 ierr = (dm->ops->projectfieldlocal) (dm, localU, funcs, mode, localX);CHKERRQ(ierr); 6231 PetscFunctionReturn(0); 6232 } 6233 6234 #undef __FUNCT__ 6235 #define __FUNCT__ "DMProjectFunctionLabelLocal" 6236 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) 6237 { 6238 PetscErrorCode ierr; 6239 6240 PetscFunctionBegin; 6241 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6242 PetscValidHeaderSpecific(localX,VEC_CLASSID,5); 6243 if (!dm->ops->projectfunctionlabellocal) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMProjectFunctionLabelLocal",((PetscObject)dm)->type_name); 6244 ierr = (dm->ops->projectfunctionlabellocal) (dm, time, label, numIds, ids, funcs, ctxs, mode, localX);CHKERRQ(ierr); 6245 PetscFunctionReturn(0); 6246 } 6247 6248 #undef __FUNCT__ 6249 #define __FUNCT__ "DMComputeL2Diff" 6250 /*@C 6251 DMComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 6252 6253 Input Parameters: 6254 + dm - The DM 6255 . time - The time 6256 . funcs - The functions to evaluate for each field component 6257 . ctxs - Optional array of contexts to pass to each function, or NULL. 6258 - X - The coefficient vector u_h 6259 6260 Output Parameter: 6261 . diff - The diff ||u - u_h||_2 6262 6263 Level: developer 6264 6265 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6266 @*/ 6267 PetscErrorCode DMComputeL2Diff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 6268 { 6269 PetscErrorCode ierr; 6270 6271 PetscFunctionBegin; 6272 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6273 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6274 if (!dm->ops->computel2diff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2Diff",((PetscObject)dm)->type_name); 6275 ierr = (dm->ops->computel2diff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6276 PetscFunctionReturn(0); 6277 } 6278 6279 #undef __FUNCT__ 6280 #define __FUNCT__ "DMComputeL2GradientDiff" 6281 /*@C 6282 DMComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 6283 6284 Input Parameters: 6285 + dm - The DM 6286 , time - The time 6287 . funcs - The gradient functions to evaluate for each field component 6288 . ctxs - Optional array of contexts to pass to each function, or NULL. 6289 . X - The coefficient vector u_h 6290 - n - The vector to project along 6291 6292 Output Parameter: 6293 . diff - The diff ||(grad u - grad u_h) . n||_2 6294 6295 Level: developer 6296 6297 .seealso: DMProjectFunction(), DMComputeL2Diff() 6298 @*/ 6299 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) 6300 { 6301 PetscErrorCode ierr; 6302 6303 PetscFunctionBegin; 6304 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6305 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6306 if (!dm->ops->computel2gradientdiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implement DMComputeL2GradientDiff",((PetscObject)dm)->type_name); 6307 ierr = (dm->ops->computel2gradientdiff)(dm,time,funcs,ctxs,X,n,diff);CHKERRQ(ierr); 6308 PetscFunctionReturn(0); 6309 } 6310 6311 #undef __FUNCT__ 6312 #define __FUNCT__ "DMComputeL2FieldDiff" 6313 /*@C 6314 DMComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 6315 6316 Input Parameters: 6317 + dm - The DM 6318 . time - The time 6319 . funcs - The functions to evaluate for each field component 6320 . ctxs - Optional array of contexts to pass to each function, or NULL. 6321 - X - The coefficient vector u_h 6322 6323 Output Parameter: 6324 . diff - The array of differences, ||u^f - u^f_h||_2 6325 6326 Level: developer 6327 6328 .seealso: DMProjectFunction(), DMComputeL2FieldDiff(), DMComputeL2GradientDiff() 6329 @*/ 6330 PetscErrorCode DMComputeL2FieldDiff(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 6331 { 6332 PetscErrorCode ierr; 6333 6334 PetscFunctionBegin; 6335 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 6336 PetscValidHeaderSpecific(X,VEC_CLASSID,5); 6337 if (!dm->ops->computel2fielddiff) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM type %s does not implemnt DMComputeL2FieldDiff",((PetscObject)dm)->type_name); 6338 ierr = (dm->ops->computel2fielddiff)(dm,time,funcs,ctxs,X,diff);CHKERRQ(ierr); 6339 PetscFunctionReturn(0); 6340 } 6341 6342