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