1 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/ 2 #include <petscsf.h> 3 #include <petscds.h> 4 5 PetscClassId DM_CLASSID; 6 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal, DM_LocalToLocal; 7 8 const char *const DMBoundaryTypes[] = {"NONE","GHOSTED","MIRROR","PERIODIC","TWIST","DM_BOUNDARY_",0}; 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "DMCreate" 12 /*@ 13 DMCreate - Creates an empty DM object. The type can then be set with DMSetType(). 14 15 If you never call DMSetType() it will generate an 16 error when you try to use the vector. 17 18 Collective on MPI_Comm 19 20 Input Parameter: 21 . comm - The communicator for the DM object 22 23 Output Parameter: 24 . dm - The DM object 25 26 Level: beginner 27 28 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE, DMPLEX, DMMOAB, DMNETWORK 29 @*/ 30 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm) 31 { 32 DM v; 33 PetscErrorCode ierr; 34 35 PetscFunctionBegin; 36 PetscValidPointer(dm,2); 37 *dm = NULL; 38 ierr = PetscSysInitializePackage();CHKERRQ(ierr); 39 ierr = VecInitializePackage();CHKERRQ(ierr); 40 ierr = MatInitializePackage();CHKERRQ(ierr); 41 ierr = DMInitializePackage();CHKERRQ(ierr); 42 43 ierr = PetscHeaderCreate(v, DM_CLASSID, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr); 44 45 v->ltogmap = NULL; 46 v->bs = 1; 47 v->coloringtype = IS_COLORING_GLOBAL; 48 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr); 49 ierr = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr); 50 v->defaultSection = NULL; 51 v->defaultGlobalSection = NULL; 52 v->defaultConstraintSection = NULL; 53 v->defaultConstraintMat = NULL; 54 v->L = NULL; 55 v->maxCell = NULL; 56 v->bdtype = NULL; 57 v->dimEmbed = PETSC_DEFAULT; 58 { 59 PetscInt i; 60 for (i = 0; i < 10; ++i) { 61 v->nullspaceConstructors[i] = NULL; 62 } 63 } 64 ierr = PetscDSCreate(comm, &v->prob);CHKERRQ(ierr); 65 v->dmBC = NULL; 66 v->outputSequenceNum = -1; 67 v->outputSequenceVal = 0.0; 68 ierr = DMSetVecType(v,VECSTANDARD);CHKERRQ(ierr); 69 ierr = DMSetMatType(v,MATAIJ);CHKERRQ(ierr); 70 *dm = v; 71 PetscFunctionReturn(0); 72 } 73 74 #undef __FUNCT__ 75 #define __FUNCT__ "DMClone" 76 /*@ 77 DMClone - Creates a DM object with the same topology as the original. 78 79 Collective on MPI_Comm 80 81 Input Parameter: 82 . dm - The original DM object 83 84 Output Parameter: 85 . newdm - The new DM object 86 87 Level: beginner 88 89 .keywords: DM, topology, create 90 @*/ 91 PetscErrorCode DMClone(DM dm, DM *newdm) 92 { 93 PetscSF sf; 94 Vec coords; 95 void *ctx; 96 PetscInt dim; 97 PetscErrorCode ierr; 98 99 PetscFunctionBegin; 100 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 101 PetscValidPointer(newdm,2); 102 ierr = DMCreate(PetscObjectComm((PetscObject)dm), newdm);CHKERRQ(ierr); 103 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 104 ierr = DMSetDimension(*newdm, dim);CHKERRQ(ierr); 105 if (dm->ops->clone) { 106 ierr = (*dm->ops->clone)(dm, newdm);CHKERRQ(ierr); 107 } 108 (*newdm)->setupcalled = PETSC_TRUE; 109 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 110 ierr = DMSetPointSF(*newdm, sf);CHKERRQ(ierr); 111 ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr); 112 ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr); 113 ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr); 114 if (coords) { 115 ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr); 116 } else { 117 ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); 118 if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);} 119 } 120 if (dm->maxCell) { 121 const PetscReal *maxCell, *L; 122 const DMBoundaryType *bd; 123 ierr = DMGetPeriodicity(dm, &maxCell, &L, &bd);CHKERRQ(ierr); 124 ierr = DMSetPeriodicity(*newdm, maxCell, L, bd);CHKERRQ(ierr); 125 } 126 PetscFunctionReturn(0); 127 } 128 129 #undef __FUNCT__ 130 #define __FUNCT__ "DMSetVecType" 131 /*@C 132 DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 133 134 Logically Collective on DM 135 136 Input Parameter: 137 + da - initial distributed array 138 . ctype - the vector type, currently either VECSTANDARD or VECCUSP 139 140 Options Database: 141 . -dm_vec_type ctype 142 143 Level: intermediate 144 145 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType, DMGetVecType() 146 @*/ 147 PetscErrorCode DMSetVecType(DM da,VecType ctype) 148 { 149 PetscErrorCode ierr; 150 151 PetscFunctionBegin; 152 PetscValidHeaderSpecific(da,DM_CLASSID,1); 153 ierr = PetscFree(da->vectype);CHKERRQ(ierr); 154 ierr = PetscStrallocpy(ctype,(char**)&da->vectype);CHKERRQ(ierr); 155 PetscFunctionReturn(0); 156 } 157 158 #undef __FUNCT__ 159 #define __FUNCT__ "DMGetVecType" 160 /*@C 161 DMGetVecType - Gets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 162 163 Logically Collective on DM 164 165 Input Parameter: 166 . da - initial distributed array 167 168 Output Parameter: 169 . ctype - the vector type 170 171 Level: intermediate 172 173 .seealso: DMCreate(), DMDestroy(), DM, DMDAInterpolationType, VecType 174 @*/ 175 PetscErrorCode DMGetVecType(DM da,VecType *ctype) 176 { 177 PetscFunctionBegin; 178 PetscValidHeaderSpecific(da,DM_CLASSID,1); 179 *ctype = da->vectype; 180 PetscFunctionReturn(0); 181 } 182 183 #undef __FUNCT__ 184 #define __FUNCT__ "VecGetDM" 185 /*@ 186 VecGetDM - Gets the DM defining the data layout of the vector 187 188 Not collective 189 190 Input Parameter: 191 . v - The Vec 192 193 Output Parameter: 194 . dm - The DM 195 196 Level: intermediate 197 198 .seealso: VecSetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 199 @*/ 200 PetscErrorCode VecGetDM(Vec v, DM *dm) 201 { 202 PetscErrorCode ierr; 203 204 PetscFunctionBegin; 205 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 206 PetscValidPointer(dm,2); 207 ierr = PetscObjectQuery((PetscObject) v, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 208 PetscFunctionReturn(0); 209 } 210 211 #undef __FUNCT__ 212 #define __FUNCT__ "VecSetDM" 213 /*@ 214 VecSetDM - Sets the DM defining the data layout of the vector. 215 216 Not collective 217 218 Input Parameters: 219 + v - The Vec 220 - dm - The DM 221 222 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. 223 224 Level: intermediate 225 226 .seealso: VecGetDM(), DMGetLocalVector(), DMGetGlobalVector(), DMSetVecType() 227 @*/ 228 PetscErrorCode VecSetDM(Vec v, DM dm) 229 { 230 PetscErrorCode ierr; 231 232 PetscFunctionBegin; 233 PetscValidHeaderSpecific(v,VEC_CLASSID,1); 234 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 235 ierr = PetscObjectCompose((PetscObject) v, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 236 PetscFunctionReturn(0); 237 } 238 239 #undef __FUNCT__ 240 #define __FUNCT__ "DMSetMatType" 241 /*@C 242 DMSetMatType - Sets the type of matrix created with DMCreateMatrix() 243 244 Logically Collective on DM 245 246 Input Parameter: 247 + dm - the DM context 248 . ctype - the matrix type 249 250 Options Database: 251 . -dm_mat_type ctype 252 253 Level: intermediate 254 255 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMGetMatType() 256 @*/ 257 PetscErrorCode DMSetMatType(DM dm,MatType ctype) 258 { 259 PetscErrorCode ierr; 260 261 PetscFunctionBegin; 262 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 263 ierr = PetscFree(dm->mattype);CHKERRQ(ierr); 264 ierr = PetscStrallocpy(ctype,(char**)&dm->mattype);CHKERRQ(ierr); 265 PetscFunctionReturn(0); 266 } 267 268 #undef __FUNCT__ 269 #define __FUNCT__ "DMGetMatType" 270 /*@C 271 DMGetMatType - Gets the type of matrix created with DMCreateMatrix() 272 273 Logically Collective on DM 274 275 Input Parameter: 276 . dm - the DM context 277 278 Output Parameter: 279 . ctype - the matrix type 280 281 Options Database: 282 . -dm_mat_type ctype 283 284 Level: intermediate 285 286 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType, DMSetMatType() 287 @*/ 288 PetscErrorCode DMGetMatType(DM dm,MatType *ctype) 289 { 290 PetscFunctionBegin; 291 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 292 *ctype = dm->mattype; 293 PetscFunctionReturn(0); 294 } 295 296 #undef __FUNCT__ 297 #define __FUNCT__ "MatGetDM" 298 /*@ 299 MatGetDM - Gets the DM defining the data layout of the matrix 300 301 Not collective 302 303 Input Parameter: 304 . A - The Mat 305 306 Output Parameter: 307 . dm - The DM 308 309 Level: intermediate 310 311 .seealso: MatSetDM(), DMCreateMatrix(), DMSetMatType() 312 @*/ 313 PetscErrorCode MatGetDM(Mat A, DM *dm) 314 { 315 PetscErrorCode ierr; 316 317 PetscFunctionBegin; 318 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 319 PetscValidPointer(dm,2); 320 ierr = PetscObjectQuery((PetscObject) A, "__PETSc_dm", (PetscObject*) dm);CHKERRQ(ierr); 321 PetscFunctionReturn(0); 322 } 323 324 #undef __FUNCT__ 325 #define __FUNCT__ "MatSetDM" 326 /*@ 327 MatSetDM - Sets the DM defining the data layout of the matrix 328 329 Not collective 330 331 Input Parameters: 332 + A - The Mat 333 - dm - The DM 334 335 Level: intermediate 336 337 .seealso: MatGetDM(), DMCreateMatrix(), DMSetMatType() 338 @*/ 339 PetscErrorCode MatSetDM(Mat A, DM dm) 340 { 341 PetscErrorCode ierr; 342 343 PetscFunctionBegin; 344 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 345 if (dm) PetscValidHeaderSpecific(dm,DM_CLASSID,2); 346 ierr = PetscObjectCompose((PetscObject) A, "__PETSc_dm", (PetscObject) dm);CHKERRQ(ierr); 347 PetscFunctionReturn(0); 348 } 349 350 #undef __FUNCT__ 351 #define __FUNCT__ "DMSetOptionsPrefix" 352 /*@C 353 DMSetOptionsPrefix - Sets the prefix used for searching for all 354 DM options in the database. 355 356 Logically Collective on DM 357 358 Input Parameter: 359 + da - the DM context 360 - prefix - the prefix to prepend to all option names 361 362 Notes: 363 A hyphen (-) must NOT be given at the beginning of the prefix name. 364 The first character of all runtime options is AUTOMATICALLY the hyphen. 365 366 Level: advanced 367 368 .keywords: DM, set, options, prefix, database 369 370 .seealso: DMSetFromOptions() 371 @*/ 372 PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[]) 373 { 374 PetscErrorCode ierr; 375 376 PetscFunctionBegin; 377 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 378 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 379 if (dm->sf) { 380 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->sf,prefix);CHKERRQ(ierr); 381 } 382 if (dm->defaultSF) { 383 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm->defaultSF,prefix);CHKERRQ(ierr); 384 } 385 PetscFunctionReturn(0); 386 } 387 388 #undef __FUNCT__ 389 #define __FUNCT__ "DMAppendOptionsPrefix" 390 /*@C 391 DMAppendOptionsPrefix - Appends to the prefix used for searching for all 392 DM options in the database. 393 394 Logically Collective on DM 395 396 Input Parameters: 397 + dm - the DM context 398 - prefix - the prefix string to prepend to all DM option requests 399 400 Notes: 401 A hyphen (-) must NOT be given at the beginning of the prefix name. 402 The first character of all runtime options is AUTOMATICALLY the hyphen. 403 404 Level: advanced 405 406 .keywords: DM, append, options, prefix, database 407 408 .seealso: DMSetOptionsPrefix(), DMGetOptionsPrefix() 409 @*/ 410 PetscErrorCode DMAppendOptionsPrefix(DM dm,const char prefix[]) 411 { 412 PetscErrorCode ierr; 413 414 PetscFunctionBegin; 415 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 416 ierr = PetscObjectAppendOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 417 PetscFunctionReturn(0); 418 } 419 420 #undef __FUNCT__ 421 #define __FUNCT__ "DMGetOptionsPrefix" 422 /*@C 423 DMGetOptionsPrefix - Gets the prefix used for searching for all 424 DM options in the database. 425 426 Not Collective 427 428 Input Parameters: 429 . dm - the DM context 430 431 Output Parameters: 432 . prefix - pointer to the prefix string used is returned 433 434 Notes: On the fortran side, the user should pass in a string 'prefix' of 435 sufficient length to hold the prefix. 436 437 Level: advanced 438 439 .keywords: DM, set, options, prefix, database 440 441 .seealso: DMSetOptionsPrefix(), DMAppendOptionsPrefix() 442 @*/ 443 PetscErrorCode DMGetOptionsPrefix(DM dm,const char *prefix[]) 444 { 445 PetscErrorCode ierr; 446 447 PetscFunctionBegin; 448 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 449 ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 450 PetscFunctionReturn(0); 451 } 452 453 #undef __FUNCT__ 454 #define __FUNCT__ "DMDestroy" 455 /*@ 456 DMDestroy - Destroys a vector packer or DM. 457 458 Collective on DM 459 460 Input Parameter: 461 . dm - the DM object to destroy 462 463 Level: developer 464 465 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 466 467 @*/ 468 PetscErrorCode DMDestroy(DM *dm) 469 { 470 PetscInt i, cnt = 0; 471 DMNamedVecLink nlink,nnext; 472 PetscErrorCode ierr; 473 474 PetscFunctionBegin; 475 if (!*dm) PetscFunctionReturn(0); 476 PetscValidHeaderSpecific((*dm),DM_CLASSID,1); 477 478 /* count all the circular references of DM and its contained Vecs */ 479 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 480 if ((*dm)->localin[i]) cnt++; 481 if ((*dm)->globalin[i]) cnt++; 482 } 483 for (nlink=(*dm)->namedglobal; nlink; nlink=nlink->next) cnt++; 484 for (nlink=(*dm)->namedlocal; nlink; nlink=nlink->next) cnt++; 485 if ((*dm)->x) { 486 DM obj; 487 ierr = VecGetDM((*dm)->x, &obj);CHKERRQ(ierr); 488 if (obj == *dm) cnt++; 489 } 490 491 if (--((PetscObject)(*dm))->refct - cnt > 0) {*dm = 0; PetscFunctionReturn(0);} 492 /* 493 Need this test because the dm references the vectors that 494 reference the dm, so destroying the dm calls destroy on the 495 vectors that cause another destroy on the dm 496 */ 497 if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0); 498 ((PetscObject) (*dm))->refct = 0; 499 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 500 if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()"); 501 ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr); 502 } 503 nnext=(*dm)->namedglobal; 504 (*dm)->namedglobal = NULL; 505 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named vectors */ 506 nnext = nlink->next; 507 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 508 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 509 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 510 ierr = PetscFree(nlink);CHKERRQ(ierr); 511 } 512 nnext=(*dm)->namedlocal; 513 (*dm)->namedlocal = NULL; 514 for (nlink=nnext; nlink; nlink=nnext) { /* Destroy the named local vectors */ 515 nnext = nlink->next; 516 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 517 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 518 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 519 ierr = PetscFree(nlink);CHKERRQ(ierr); 520 } 521 522 /* Destroy the list of hooks */ 523 { 524 DMCoarsenHookLink link,next; 525 for (link=(*dm)->coarsenhook; link; link=next) { 526 next = link->next; 527 ierr = PetscFree(link);CHKERRQ(ierr); 528 } 529 (*dm)->coarsenhook = NULL; 530 } 531 { 532 DMRefineHookLink link,next; 533 for (link=(*dm)->refinehook; link; link=next) { 534 next = link->next; 535 ierr = PetscFree(link);CHKERRQ(ierr); 536 } 537 (*dm)->refinehook = NULL; 538 } 539 { 540 DMSubDomainHookLink link,next; 541 for (link=(*dm)->subdomainhook; link; link=next) { 542 next = link->next; 543 ierr = PetscFree(link);CHKERRQ(ierr); 544 } 545 (*dm)->subdomainhook = NULL; 546 } 547 { 548 DMGlobalToLocalHookLink link,next; 549 for (link=(*dm)->gtolhook; link; link=next) { 550 next = link->next; 551 ierr = PetscFree(link);CHKERRQ(ierr); 552 } 553 (*dm)->gtolhook = NULL; 554 } 555 { 556 DMLocalToGlobalHookLink link,next; 557 for (link=(*dm)->ltoghook; link; link=next) { 558 next = link->next; 559 ierr = PetscFree(link);CHKERRQ(ierr); 560 } 561 (*dm)->ltoghook = NULL; 562 } 563 /* Destroy the work arrays */ 564 { 565 DMWorkLink link,next; 566 if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out"); 567 for (link=(*dm)->workin; link; link=next) { 568 next = link->next; 569 ierr = PetscFree(link->mem);CHKERRQ(ierr); 570 ierr = PetscFree(link);CHKERRQ(ierr); 571 } 572 (*dm)->workin = NULL; 573 } 574 575 ierr = PetscObjectDestroy(&(*dm)->dmksp);CHKERRQ(ierr); 576 ierr = PetscObjectDestroy(&(*dm)->dmsnes);CHKERRQ(ierr); 577 ierr = PetscObjectDestroy(&(*dm)->dmts);CHKERRQ(ierr); 578 579 if ((*dm)->ctx && (*dm)->ctxdestroy) { 580 ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr); 581 } 582 ierr = VecDestroy(&(*dm)->x);CHKERRQ(ierr); 583 ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr); 584 ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr); 585 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr); 586 ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr); 587 ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr); 588 589 ierr = PetscSectionDestroy(&(*dm)->defaultSection);CHKERRQ(ierr); 590 ierr = PetscSectionDestroy(&(*dm)->defaultGlobalSection);CHKERRQ(ierr); 591 ierr = PetscLayoutDestroy(&(*dm)->map);CHKERRQ(ierr); 592 ierr = PetscSectionDestroy(&(*dm)->defaultConstraintSection);CHKERRQ(ierr); 593 ierr = MatDestroy(&(*dm)->defaultConstraintMat);CHKERRQ(ierr); 594 ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr); 595 ierr = PetscSFDestroy(&(*dm)->defaultSF);CHKERRQ(ierr); 596 ierr = PetscSFDestroy(&(*dm)->sfNatural);CHKERRQ(ierr); 597 598 ierr = DMDestroy(&(*dm)->coordinateDM);CHKERRQ(ierr); 599 ierr = VecDestroy(&(*dm)->coordinates);CHKERRQ(ierr); 600 ierr = VecDestroy(&(*dm)->coordinatesLocal);CHKERRQ(ierr); 601 ierr = PetscFree3((*dm)->L,(*dm)->maxCell,(*dm)->bdtype);CHKERRQ(ierr); 602 603 ierr = PetscDSDestroy(&(*dm)->prob);CHKERRQ(ierr); 604 ierr = DMDestroy(&(*dm)->dmBC);CHKERRQ(ierr); 605 /* if memory was published with SAWs then destroy it */ 606 ierr = PetscObjectSAWsViewOff((PetscObject)*dm);CHKERRQ(ierr); 607 608 ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr); 609 /* We do not destroy (*dm)->data here so that we can reference count backend objects */ 610 ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr); 611 PetscFunctionReturn(0); 612 } 613 614 #undef __FUNCT__ 615 #define __FUNCT__ "DMSetUp" 616 /*@ 617 DMSetUp - sets up the data structures inside a DM object 618 619 Collective on DM 620 621 Input Parameter: 622 . dm - the DM object to setup 623 624 Level: developer 625 626 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 627 628 @*/ 629 PetscErrorCode DMSetUp(DM dm) 630 { 631 PetscErrorCode ierr; 632 633 PetscFunctionBegin; 634 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 635 if (dm->setupcalled) PetscFunctionReturn(0); 636 if (dm->ops->setup) { 637 ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr); 638 } 639 dm->setupcalled = PETSC_TRUE; 640 PetscFunctionReturn(0); 641 } 642 643 #undef __FUNCT__ 644 #define __FUNCT__ "DMSetFromOptions" 645 /*@ 646 DMSetFromOptions - sets parameters in a DM from the options database 647 648 Collective on DM 649 650 Input Parameter: 651 . dm - the DM object to set options for 652 653 Options Database: 654 + -dm_preallocate_only - Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 655 . -dm_vec_type <type> - type of vector to create inside DM 656 . -dm_mat_type <type> - type of matrix to create inside DM 657 - -dm_coloring_type - <global or ghosted> 658 659 Level: developer 660 661 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 662 663 @*/ 664 PetscErrorCode DMSetFromOptions(DM dm) 665 { 666 char typeName[256]; 667 PetscBool flg; 668 PetscErrorCode ierr; 669 670 PetscFunctionBegin; 671 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 672 if (dm->sf) { 673 ierr = PetscSFSetFromOptions(dm->sf);CHKERRQ(ierr); 674 } 675 if (dm->defaultSF) { 676 ierr = PetscSFSetFromOptions(dm->defaultSF);CHKERRQ(ierr); 677 } 678 ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr); 679 ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,NULL);CHKERRQ(ierr); 680 ierr = PetscOptionsFList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr); 681 if (flg) { 682 ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr); 683 } 684 ierr = PetscOptionsFList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype ? dm->mattype : typeName,typeName,sizeof(typeName),&flg);CHKERRQ(ierr); 685 if (flg) { 686 ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr); 687 } 688 ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","ISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,NULL);CHKERRQ(ierr); 689 if (dm->ops->setfromoptions) { 690 ierr = (*dm->ops->setfromoptions)(PetscOptionsObject,dm);CHKERRQ(ierr); 691 } 692 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 693 ierr = PetscObjectProcessOptionsHandlers((PetscObject) dm);CHKERRQ(ierr); 694 ierr = PetscOptionsEnd();CHKERRQ(ierr); 695 PetscFunctionReturn(0); 696 } 697 698 #undef __FUNCT__ 699 #define __FUNCT__ "DMView" 700 /*@C 701 DMView - Views a vector packer or DMDA. 702 703 Collective on DM 704 705 Input Parameter: 706 + dm - the DM object to view 707 - v - the viewer 708 709 Level: developer 710 711 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 712 713 @*/ 714 PetscErrorCode DMView(DM dm,PetscViewer v) 715 { 716 PetscErrorCode ierr; 717 PetscBool isbinary; 718 719 PetscFunctionBegin; 720 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 721 if (!v) { 722 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)dm),&v);CHKERRQ(ierr); 723 } 724 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)dm,v);CHKERRQ(ierr); 725 ierr = PetscObjectTypeCompare((PetscObject)v,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 726 if (isbinary) { 727 PetscInt classid = DM_FILE_CLASSID; 728 char type[256]; 729 730 ierr = PetscViewerBinaryWrite(v,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 731 ierr = PetscStrncpy(type,((PetscObject)dm)->type_name,256);CHKERRQ(ierr); 732 ierr = PetscViewerBinaryWrite(v,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 733 } 734 if (dm->ops->view) { 735 ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr); 736 } 737 PetscFunctionReturn(0); 738 } 739 740 #undef __FUNCT__ 741 #define __FUNCT__ "DMCreateGlobalVector" 742 /*@ 743 DMCreateGlobalVector - Creates a global vector from a DM object 744 745 Collective on DM 746 747 Input Parameter: 748 . dm - the DM object 749 750 Output Parameter: 751 . vec - the global vector 752 753 Level: beginner 754 755 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 756 757 @*/ 758 PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec) 759 { 760 PetscErrorCode ierr; 761 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 764 ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr); 765 PetscFunctionReturn(0); 766 } 767 768 #undef __FUNCT__ 769 #define __FUNCT__ "DMCreateLocalVector" 770 /*@ 771 DMCreateLocalVector - Creates a local vector from a DM object 772 773 Not Collective 774 775 Input Parameter: 776 . dm - the DM object 777 778 Output Parameter: 779 . vec - the local vector 780 781 Level: beginner 782 783 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 784 785 @*/ 786 PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec) 787 { 788 PetscErrorCode ierr; 789 790 PetscFunctionBegin; 791 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 792 ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr); 793 PetscFunctionReturn(0); 794 } 795 796 #undef __FUNCT__ 797 #define __FUNCT__ "DMGetLocalToGlobalMapping" 798 /*@ 799 DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM. 800 801 Collective on DM 802 803 Input Parameter: 804 . dm - the DM that provides the mapping 805 806 Output Parameter: 807 . ltog - the mapping 808 809 Level: intermediate 810 811 Notes: 812 This mapping can then be used by VecSetLocalToGlobalMapping() or 813 MatSetLocalToGlobalMapping(). 814 815 .seealso: DMCreateLocalVector() 816 @*/ 817 PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog) 818 { 819 PetscErrorCode ierr; 820 821 PetscFunctionBegin; 822 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 823 PetscValidPointer(ltog,2); 824 if (!dm->ltogmap) { 825 PetscSection section, sectionGlobal; 826 827 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 828 if (section) { 829 PetscInt *ltog; 830 PetscInt pStart, pEnd, size, p, l; 831 832 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 833 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 834 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 835 ierr = PetscMalloc1(size, <og);CHKERRQ(ierr); /* We want the local+overlap size */ 836 for (p = pStart, l = 0; p < pEnd; ++p) { 837 PetscInt dof, off, c; 838 839 /* Should probably use constrained dofs */ 840 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 841 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 842 for (c = 0; c < dof; ++c, ++l) { 843 ltog[l] = off+c; 844 } 845 } 846 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, 1,size, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr); 847 ierr = PetscLogObjectParent((PetscObject)dm, (PetscObject)dm->ltogmap);CHKERRQ(ierr); 848 } else { 849 if (!dm->ops->getlocaltoglobalmapping) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping"); 850 ierr = (*dm->ops->getlocaltoglobalmapping)(dm);CHKERRQ(ierr); 851 } 852 } 853 *ltog = dm->ltogmap; 854 PetscFunctionReturn(0); 855 } 856 857 #undef __FUNCT__ 858 #define __FUNCT__ "DMGetBlockSize" 859 /*@ 860 DMGetBlockSize - Gets the inherent block size associated with a DM 861 862 Not Collective 863 864 Input Parameter: 865 . dm - the DM with block structure 866 867 Output Parameter: 868 . bs - the block size, 1 implies no exploitable block structure 869 870 Level: intermediate 871 872 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMapping() 873 @*/ 874 PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs) 875 { 876 PetscFunctionBegin; 877 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 878 PetscValidPointer(bs,2); 879 if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet"); 880 *bs = dm->bs; 881 PetscFunctionReturn(0); 882 } 883 884 #undef __FUNCT__ 885 #define __FUNCT__ "DMCreateInterpolation" 886 /*@ 887 DMCreateInterpolation - Gets interpolation matrix between two DM objects 888 889 Collective on DM 890 891 Input Parameter: 892 + dm1 - the DM object 893 - dm2 - the second, finer DM object 894 895 Output Parameter: 896 + mat - the interpolation 897 - vec - the scaling (optional) 898 899 Level: developer 900 901 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 902 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 903 904 For DMDA objects you can use this interpolation (more precisely the interpolation from the DMGetCoordinateDM()) to interpolate the mesh coordinate vectors 905 EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic. 906 907 908 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen() 909 910 @*/ 911 PetscErrorCode DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec) 912 { 913 PetscErrorCode ierr; 914 915 PetscFunctionBegin; 916 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 917 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 918 ierr = (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr); 919 PetscFunctionReturn(0); 920 } 921 922 #undef __FUNCT__ 923 #define __FUNCT__ "DMCreateInjection" 924 /*@ 925 DMCreateInjection - Gets injection matrix between two DM objects 926 927 Collective on DM 928 929 Input Parameter: 930 + dm1 - the DM object 931 - dm2 - the second, finer DM object 932 933 Output Parameter: 934 . mat - the injection 935 936 Level: developer 937 938 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 939 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection. 940 941 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation() 942 943 @*/ 944 PetscErrorCode DMCreateInjection(DM dm1,DM dm2,Mat *mat) 945 { 946 PetscErrorCode ierr; 947 948 PetscFunctionBegin; 949 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 950 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 951 ierr = (*dm1->ops->getinjection)(dm1,dm2,mat);CHKERRQ(ierr); 952 PetscFunctionReturn(0); 953 } 954 955 #undef __FUNCT__ 956 #define __FUNCT__ "DMCreateColoring" 957 /*@ 958 DMCreateColoring - Gets coloring for a DM 959 960 Collective on DM 961 962 Input Parameter: 963 + dm - the DM object 964 - ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL 965 966 Output Parameter: 967 . coloring - the coloring 968 969 Level: developer 970 971 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix(), DMSetMatType() 972 973 @*/ 974 PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,ISColoring *coloring) 975 { 976 PetscErrorCode ierr; 977 978 PetscFunctionBegin; 979 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 980 if (!dm->ops->getcoloring) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No coloring for this type of DM yet"); 981 ierr = (*dm->ops->getcoloring)(dm,ctype,coloring);CHKERRQ(ierr); 982 PetscFunctionReturn(0); 983 } 984 985 #undef __FUNCT__ 986 #define __FUNCT__ "DMCreateMatrix" 987 /*@ 988 DMCreateMatrix - Gets empty Jacobian for a DM 989 990 Collective on DM 991 992 Input Parameter: 993 . dm - the DM object 994 995 Output Parameter: 996 . mat - the empty Jacobian 997 998 Level: beginner 999 1000 Notes: This properly preallocates the number of nonzeros in the sparse matrix so you 1001 do not need to do it yourself. 1002 1003 By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 1004 the nonzero pattern call DMDASetMatPreallocateOnly() 1005 1006 For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used 1007 internally by PETSc. 1008 1009 For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 1010 the indices for the global numbering for DMDAs which is complicated. 1011 1012 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMSetMatType() 1013 1014 @*/ 1015 PetscErrorCode DMCreateMatrix(DM dm,Mat *mat) 1016 { 1017 PetscErrorCode ierr; 1018 1019 PetscFunctionBegin; 1020 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1021 ierr = MatInitializePackage();CHKERRQ(ierr); 1022 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1023 PetscValidPointer(mat,3); 1024 ierr = (*dm->ops->creatematrix)(dm,mat);CHKERRQ(ierr); 1025 PetscFunctionReturn(0); 1026 } 1027 1028 #undef __FUNCT__ 1029 #define __FUNCT__ "DMSetMatrixPreallocateOnly" 1030 /*@ 1031 DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly 1032 preallocated but the nonzero structure and zero values will not be set. 1033 1034 Logically Collective on DM 1035 1036 Input Parameter: 1037 + dm - the DM 1038 - only - PETSC_TRUE if only want preallocation 1039 1040 Level: developer 1041 .seealso DMCreateMatrix() 1042 @*/ 1043 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only) 1044 { 1045 PetscFunctionBegin; 1046 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1047 dm->prealloc_only = only; 1048 PetscFunctionReturn(0); 1049 } 1050 1051 #undef __FUNCT__ 1052 #define __FUNCT__ "DMGetWorkArray" 1053 /*@C 1054 DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1055 1056 Not Collective 1057 1058 Input Parameters: 1059 + dm - the DM object 1060 . count - The minium size 1061 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 1062 1063 Output Parameter: 1064 . array - the work array 1065 1066 Level: developer 1067 1068 .seealso DMDestroy(), DMCreate() 1069 @*/ 1070 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 1071 { 1072 PetscErrorCode ierr; 1073 DMWorkLink link; 1074 size_t dsize; 1075 1076 PetscFunctionBegin; 1077 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1078 PetscValidPointer(mem,4); 1079 if (dm->workin) { 1080 link = dm->workin; 1081 dm->workin = dm->workin->next; 1082 } else { 1083 ierr = PetscNewLog(dm,&link);CHKERRQ(ierr); 1084 } 1085 ierr = PetscDataTypeGetSize(dtype,&dsize);CHKERRQ(ierr); 1086 if (dsize*count > link->bytes) { 1087 ierr = PetscFree(link->mem);CHKERRQ(ierr); 1088 ierr = PetscMalloc(dsize*count,&link->mem);CHKERRQ(ierr); 1089 link->bytes = dsize*count; 1090 } 1091 link->next = dm->workout; 1092 dm->workout = link; 1093 *(void**)mem = link->mem; 1094 PetscFunctionReturn(0); 1095 } 1096 1097 #undef __FUNCT__ 1098 #define __FUNCT__ "DMRestoreWorkArray" 1099 /*@C 1100 DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 1101 1102 Not Collective 1103 1104 Input Parameters: 1105 + dm - the DM object 1106 . count - The minium size 1107 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 1108 1109 Output Parameter: 1110 . array - the work array 1111 1112 Level: developer 1113 1114 .seealso DMDestroy(), DMCreate() 1115 @*/ 1116 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 1117 { 1118 DMWorkLink *p,link; 1119 1120 PetscFunctionBegin; 1121 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1122 PetscValidPointer(mem,4); 1123 for (p=&dm->workout; (link=*p); p=&link->next) { 1124 if (link->mem == *(void**)mem) { 1125 *p = link->next; 1126 link->next = dm->workin; 1127 dm->workin = link; 1128 *(void**)mem = NULL; 1129 PetscFunctionReturn(0); 1130 } 1131 } 1132 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out"); 1133 } 1134 1135 #undef __FUNCT__ 1136 #define __FUNCT__ "DMSetNullSpaceConstructor" 1137 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace)) 1138 { 1139 PetscFunctionBegin; 1140 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1141 if (field >= 10) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 1142 dm->nullspaceConstructors[field] = nullsp; 1143 PetscFunctionReturn(0); 1144 } 1145 1146 #undef __FUNCT__ 1147 #define __FUNCT__ "DMCreateFieldIS" 1148 /*@C 1149 DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field 1150 1151 Not collective 1152 1153 Input Parameter: 1154 . dm - the DM object 1155 1156 Output Parameters: 1157 + numFields - The number of fields (or NULL if not requested) 1158 . fieldNames - The name for each field (or NULL if not requested) 1159 - fields - The global indices for each field (or NULL if not requested) 1160 1161 Level: intermediate 1162 1163 Notes: 1164 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1165 PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with 1166 PetscFree(). 1167 1168 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 1169 @*/ 1170 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields) 1171 { 1172 PetscSection section, sectionGlobal; 1173 PetscErrorCode ierr; 1174 1175 PetscFunctionBegin; 1176 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1177 if (numFields) { 1178 PetscValidPointer(numFields,2); 1179 *numFields = 0; 1180 } 1181 if (fieldNames) { 1182 PetscValidPointer(fieldNames,3); 1183 *fieldNames = NULL; 1184 } 1185 if (fields) { 1186 PetscValidPointer(fields,4); 1187 *fields = NULL; 1188 } 1189 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1190 if (section) { 1191 PetscInt *fieldSizes, **fieldIndices; 1192 PetscInt nF, f, pStart, pEnd, p; 1193 1194 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1195 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1196 ierr = PetscMalloc2(nF,&fieldSizes,nF,&fieldIndices);CHKERRQ(ierr); 1197 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1198 for (f = 0; f < nF; ++f) { 1199 fieldSizes[f] = 0; 1200 } 1201 for (p = pStart; p < pEnd; ++p) { 1202 PetscInt gdof; 1203 1204 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1205 if (gdof > 0) { 1206 for (f = 0; f < nF; ++f) { 1207 PetscInt fdof, fcdof; 1208 1209 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1210 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1211 fieldSizes[f] += fdof-fcdof; 1212 } 1213 } 1214 } 1215 for (f = 0; f < nF; ++f) { 1216 ierr = PetscMalloc1(fieldSizes[f], &fieldIndices[f]);CHKERRQ(ierr); 1217 fieldSizes[f] = 0; 1218 } 1219 for (p = pStart; p < pEnd; ++p) { 1220 PetscInt gdof, goff; 1221 1222 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1223 if (gdof > 0) { 1224 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1225 for (f = 0; f < nF; ++f) { 1226 PetscInt fdof, fcdof, fc; 1227 1228 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 1229 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 1230 for (fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) { 1231 fieldIndices[f][fieldSizes[f]] = goff++; 1232 } 1233 } 1234 } 1235 } 1236 if (numFields) *numFields = nF; 1237 if (fieldNames) { 1238 ierr = PetscMalloc1(nF, fieldNames);CHKERRQ(ierr); 1239 for (f = 0; f < nF; ++f) { 1240 const char *fieldName; 1241 1242 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1243 ierr = PetscStrallocpy(fieldName, (char**) &(*fieldNames)[f]);CHKERRQ(ierr); 1244 } 1245 } 1246 if (fields) { 1247 ierr = PetscMalloc1(nF, fields);CHKERRQ(ierr); 1248 for (f = 0; f < nF; ++f) { 1249 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr); 1250 } 1251 } 1252 ierr = PetscFree2(fieldSizes,fieldIndices);CHKERRQ(ierr); 1253 } else if (dm->ops->createfieldis) { 1254 ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr); 1255 } 1256 PetscFunctionReturn(0); 1257 } 1258 1259 1260 #undef __FUNCT__ 1261 #define __FUNCT__ "DMCreateFieldDecomposition" 1262 /*@C 1263 DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems 1264 corresponding to different fields: each IS contains the global indices of the dofs of the 1265 corresponding field. The optional list of DMs define the DM for each subproblem. 1266 Generalizes DMCreateFieldIS(). 1267 1268 Not collective 1269 1270 Input Parameter: 1271 . dm - the DM object 1272 1273 Output Parameters: 1274 + len - The number of subproblems in the field decomposition (or NULL if not requested) 1275 . namelist - The name for each field (or NULL if not requested) 1276 . islist - The global indices for each field (or NULL if not requested) 1277 - dmlist - The DMs for each field subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1278 1279 Level: intermediate 1280 1281 Notes: 1282 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1283 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1284 and all of the arrays should be freed with PetscFree(). 1285 1286 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1287 @*/ 1288 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 1289 { 1290 PetscErrorCode ierr; 1291 1292 PetscFunctionBegin; 1293 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1294 if (len) { 1295 PetscValidPointer(len,2); 1296 *len = 0; 1297 } 1298 if (namelist) { 1299 PetscValidPointer(namelist,3); 1300 *namelist = 0; 1301 } 1302 if (islist) { 1303 PetscValidPointer(islist,4); 1304 *islist = 0; 1305 } 1306 if (dmlist) { 1307 PetscValidPointer(dmlist,5); 1308 *dmlist = 0; 1309 } 1310 /* 1311 Is it a good idea to apply the following check across all impls? 1312 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1313 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1314 */ 1315 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1316 if (!dm->ops->createfielddecomposition) { 1317 PetscSection section; 1318 PetscInt numFields, f; 1319 1320 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1321 if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);} 1322 if (section && numFields && dm->ops->createsubdm) { 1323 *len = numFields; 1324 if (namelist) {ierr = PetscMalloc1(numFields,namelist);CHKERRQ(ierr);} 1325 if (islist) {ierr = PetscMalloc1(numFields,islist);CHKERRQ(ierr);} 1326 if (dmlist) {ierr = PetscMalloc1(numFields,dmlist);CHKERRQ(ierr);} 1327 for (f = 0; f < numFields; ++f) { 1328 const char *fieldName; 1329 1330 ierr = DMCreateSubDM(dm, 1, &f, islist ? &(*islist)[f] : NULL, dmlist ? &(*dmlist)[f] : NULL);CHKERRQ(ierr); 1331 if (namelist) { 1332 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1333 ierr = PetscStrallocpy(fieldName, (char**) &(*namelist)[f]);CHKERRQ(ierr); 1334 } 1335 } 1336 } else { 1337 ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr); 1338 /* By default there are no DMs associated with subproblems. */ 1339 if (dmlist) *dmlist = NULL; 1340 } 1341 } else { 1342 ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist);CHKERRQ(ierr); 1343 } 1344 PetscFunctionReturn(0); 1345 } 1346 1347 #undef __FUNCT__ 1348 #define __FUNCT__ "DMCreateSubDM" 1349 /*@ 1350 DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in. 1351 The fields are defined by DMCreateFieldIS(). 1352 1353 Not collective 1354 1355 Input Parameters: 1356 + dm - the DM object 1357 . numFields - number of fields in this subproblem 1358 - len - The number of subproblems in the decomposition (or NULL if not requested) 1359 1360 Output Parameters: 1361 . is - The global indices for the subproblem 1362 - dm - The DM for the subproblem 1363 1364 Level: intermediate 1365 1366 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1367 @*/ 1368 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1369 { 1370 PetscErrorCode ierr; 1371 1372 PetscFunctionBegin; 1373 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1374 PetscValidPointer(fields,3); 1375 if (is) PetscValidPointer(is,4); 1376 if (subdm) PetscValidPointer(subdm,5); 1377 if (dm->ops->createsubdm) { 1378 ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1379 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined"); 1380 PetscFunctionReturn(0); 1381 } 1382 1383 1384 #undef __FUNCT__ 1385 #define __FUNCT__ "DMCreateDomainDecomposition" 1386 /*@C 1387 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems 1388 corresponding to restrictions to pairs nested subdomains: each IS contains the global 1389 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually 1390 define a nonoverlapping covering, while outer subdomains can overlap. 1391 The optional list of DMs define the DM for each subproblem. 1392 1393 Not collective 1394 1395 Input Parameter: 1396 . dm - the DM object 1397 1398 Output Parameters: 1399 + len - The number of subproblems in the domain decomposition (or NULL if not requested) 1400 . namelist - The name for each subdomain (or NULL if not requested) 1401 . innerislist - The global indices for each inner subdomain (or NULL, if not requested) 1402 . outerislist - The global indices for each outer subdomain (or NULL, if not requested) 1403 - dmlist - The DMs for each subdomain subproblem (or NULL, if not requested; if NULL is returned, no DMs are defined) 1404 1405 Level: intermediate 1406 1407 Notes: 1408 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1409 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1410 and all of the arrays should be freed with PetscFree(). 1411 1412 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition() 1413 @*/ 1414 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 1415 { 1416 PetscErrorCode ierr; 1417 DMSubDomainHookLink link; 1418 PetscInt i,l; 1419 1420 PetscFunctionBegin; 1421 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1422 if (len) {PetscValidPointer(len,2); *len = 0;} 1423 if (namelist) {PetscValidPointer(namelist,3); *namelist = NULL;} 1424 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = NULL;} 1425 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = NULL;} 1426 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = NULL;} 1427 /* 1428 Is it a good idea to apply the following check across all impls? 1429 Perhaps some impls can have a well-defined decomposition before DMSetUp? 1430 This, however, follows the general principle that accessors are not well-behaved until the object is set up. 1431 */ 1432 if (!dm->setupcalled) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE, "Decomposition defined only after DMSetUp"); 1433 if (dm->ops->createdomaindecomposition) { 1434 ierr = (*dm->ops->createdomaindecomposition)(dm,&l,namelist,innerislist,outerislist,dmlist);CHKERRQ(ierr); 1435 /* copy subdomain hooks and context over to the subdomain DMs */ 1436 if (dmlist) { 1437 for (i = 0; i < l; i++) { 1438 for (link=dm->subdomainhook; link; link=link->next) { 1439 if (link->ddhook) {ierr = (*link->ddhook)(dm,(*dmlist)[i],link->ctx);CHKERRQ(ierr);} 1440 } 1441 (*dmlist)[i]->ctx = dm->ctx; 1442 } 1443 } 1444 if (len) *len = l; 1445 } 1446 PetscFunctionReturn(0); 1447 } 1448 1449 1450 #undef __FUNCT__ 1451 #define __FUNCT__ "DMCreateDomainDecompositionScatters" 1452 /*@C 1453 DMCreateDomainDecompositionScatters - Returns scatters to the subdomain vectors from the global vector 1454 1455 Not collective 1456 1457 Input Parameters: 1458 + dm - the DM object 1459 . n - the number of subdomain scatters 1460 - subdms - the local subdomains 1461 1462 Output Parameters: 1463 + n - the number of scatters returned 1464 . iscat - scatter from global vector to nonoverlapping global vector entries on subdomain 1465 . oscat - scatter from global vector to overlapping global vector entries on subdomain 1466 - gscat - scatter from global vector to local vector on subdomain (fills in ghosts) 1467 1468 Notes: This is an alternative to the iis and ois arguments in DMCreateDomainDecomposition that allow for the solution 1469 of general nonlinear problems with overlapping subdomain methods. While merely having index sets that enable subsets 1470 of the residual equations to be created is fine for linear problems, nonlinear problems require local assembly of 1471 solution and residual data. 1472 1473 Level: developer 1474 1475 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1476 @*/ 1477 PetscErrorCode DMCreateDomainDecompositionScatters(DM dm,PetscInt n,DM *subdms,VecScatter **iscat,VecScatter **oscat,VecScatter **gscat) 1478 { 1479 PetscErrorCode ierr; 1480 1481 PetscFunctionBegin; 1482 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1483 PetscValidPointer(subdms,3); 1484 if (dm->ops->createddscatters) { 1485 ierr = (*dm->ops->createddscatters)(dm,n,subdms,iscat,oscat,gscat);CHKERRQ(ierr); 1486 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "This type has no DMCreateDomainDecompositionLocalScatter implementation defined"); 1487 PetscFunctionReturn(0); 1488 } 1489 1490 #undef __FUNCT__ 1491 #define __FUNCT__ "DMRefine" 1492 /*@ 1493 DMRefine - Refines a DM object 1494 1495 Collective on DM 1496 1497 Input Parameter: 1498 + dm - the DM object 1499 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1500 1501 Output Parameter: 1502 . dmf - the refined DM, or NULL 1503 1504 Note: If no refinement was done, the return value is NULL 1505 1506 Level: developer 1507 1508 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1509 @*/ 1510 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 1511 { 1512 PetscErrorCode ierr; 1513 DMRefineHookLink link; 1514 1515 PetscFunctionBegin; 1516 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1517 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr); 1518 if (*dmf) { 1519 (*dmf)->ops->creatematrix = dm->ops->creatematrix; 1520 1521 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr); 1522 1523 (*dmf)->ctx = dm->ctx; 1524 (*dmf)->leveldown = dm->leveldown; 1525 (*dmf)->levelup = dm->levelup + 1; 1526 1527 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr); 1528 for (link=dm->refinehook; link; link=link->next) { 1529 if (link->refinehook) { 1530 ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr); 1531 } 1532 } 1533 } 1534 PetscFunctionReturn(0); 1535 } 1536 1537 #undef __FUNCT__ 1538 #define __FUNCT__ "DMRefineHookAdd" 1539 /*@C 1540 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 1541 1542 Logically Collective 1543 1544 Input Arguments: 1545 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1546 . refinehook - function to run when setting up a coarser level 1547 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1548 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1549 1550 Calling sequence of refinehook: 1551 $ refinehook(DM coarse,DM fine,void *ctx); 1552 1553 + coarse - coarse level DM 1554 . fine - fine level DM to interpolate problem to 1555 - ctx - optional user-defined function context 1556 1557 Calling sequence for interphook: 1558 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 1559 1560 + coarse - coarse level DM 1561 . interp - matrix interpolating a coarse-level solution to the finer grid 1562 . fine - fine level DM to update 1563 - ctx - optional user-defined function context 1564 1565 Level: advanced 1566 1567 Notes: 1568 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 1569 1570 If this function is called multiple times, the hooks will be run in the order they are added. 1571 1572 This function is currently not available from Fortran. 1573 1574 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1575 @*/ 1576 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1577 { 1578 PetscErrorCode ierr; 1579 DMRefineHookLink link,*p; 1580 1581 PetscFunctionBegin; 1582 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1583 for (p=&coarse->refinehook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1584 ierr = PetscMalloc(sizeof(struct _DMRefineHookLink),&link);CHKERRQ(ierr); 1585 link->refinehook = refinehook; 1586 link->interphook = interphook; 1587 link->ctx = ctx; 1588 link->next = NULL; 1589 *p = link; 1590 PetscFunctionReturn(0); 1591 } 1592 1593 #undef __FUNCT__ 1594 #define __FUNCT__ "DMInterpolate" 1595 /*@ 1596 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 1597 1598 Collective if any hooks are 1599 1600 Input Arguments: 1601 + coarse - coarser DM to use as a base 1602 . restrct - interpolation matrix, apply using MatInterpolate() 1603 - fine - finer DM to update 1604 1605 Level: developer 1606 1607 .seealso: DMRefineHookAdd(), MatInterpolate() 1608 @*/ 1609 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 1610 { 1611 PetscErrorCode ierr; 1612 DMRefineHookLink link; 1613 1614 PetscFunctionBegin; 1615 for (link=fine->refinehook; link; link=link->next) { 1616 if (link->interphook) { 1617 ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr); 1618 } 1619 } 1620 PetscFunctionReturn(0); 1621 } 1622 1623 #undef __FUNCT__ 1624 #define __FUNCT__ "DMGetRefineLevel" 1625 /*@ 1626 DMGetRefineLevel - Get's the number of refinements that have generated this DM. 1627 1628 Not Collective 1629 1630 Input Parameter: 1631 . dm - the DM object 1632 1633 Output Parameter: 1634 . level - number of refinements 1635 1636 Level: developer 1637 1638 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1639 1640 @*/ 1641 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 1642 { 1643 PetscFunctionBegin; 1644 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1645 *level = dm->levelup; 1646 PetscFunctionReturn(0); 1647 } 1648 1649 #undef __FUNCT__ 1650 #define __FUNCT__ "DMGlobalToLocalHookAdd" 1651 /*@C 1652 DMGlobalToLocalHookAdd - adds a callback to be run when global to local is called 1653 1654 Logically Collective 1655 1656 Input Arguments: 1657 + dm - the DM 1658 . beginhook - function to run at the beginning of DMGlobalToLocalBegin() 1659 . endhook - function to run after DMGlobalToLocalEnd() has completed 1660 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1661 1662 Calling sequence for beginhook: 1663 $ beginhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1664 1665 + dm - global DM 1666 . g - global vector 1667 . mode - mode 1668 . l - local vector 1669 - ctx - optional user-defined function context 1670 1671 1672 Calling sequence for endhook: 1673 $ endhook(DM fine,VecScatter out,VecScatter in,DM coarse,void *ctx) 1674 1675 + global - global DM 1676 - ctx - optional user-defined function context 1677 1678 Level: advanced 1679 1680 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1681 @*/ 1682 PetscErrorCode DMGlobalToLocalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 1683 { 1684 PetscErrorCode ierr; 1685 DMGlobalToLocalHookLink link,*p; 1686 1687 PetscFunctionBegin; 1688 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1689 for (p=&dm->gtolhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1690 ierr = PetscMalloc(sizeof(struct _DMGlobalToLocalHookLink),&link);CHKERRQ(ierr); 1691 link->beginhook = beginhook; 1692 link->endhook = endhook; 1693 link->ctx = ctx; 1694 link->next = NULL; 1695 *p = link; 1696 PetscFunctionReturn(0); 1697 } 1698 1699 #undef __FUNCT__ 1700 #define __FUNCT__ "DMGlobalToLocalHook_Constraints" 1701 static PetscErrorCode DMGlobalToLocalHook_Constraints(DM dm, Vec g, InsertMode mode, Vec l, void *ctx) 1702 { 1703 Mat cMat; 1704 Vec cVec; 1705 PetscSection section, cSec; 1706 PetscInt pStart, pEnd, p, dof; 1707 PetscErrorCode ierr; 1708 1709 PetscFunctionBegin; 1710 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1711 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 1712 if (cMat && (mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES)) { 1713 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 1714 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 1715 ierr = MatMult(cMat,l,cVec);CHKERRQ(ierr); 1716 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 1717 for (p = pStart; p < pEnd; p++) { 1718 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 1719 if (dof) { 1720 PetscScalar *vals; 1721 ierr = VecGetValuesSection(cVec,cSec,p,&vals);CHKERRQ(ierr); 1722 ierr = VecSetValuesSection(l,section,p,vals,INSERT_ALL_VALUES);CHKERRQ(ierr); 1723 } 1724 } 1725 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 1726 } 1727 PetscFunctionReturn(0); 1728 } 1729 1730 #undef __FUNCT__ 1731 #define __FUNCT__ "DMGlobalToLocalBegin" 1732 /*@ 1733 DMGlobalToLocalBegin - Begins updating local vectors from global vector 1734 1735 Neighbor-wise Collective on DM 1736 1737 Input Parameters: 1738 + dm - the DM object 1739 . g - the global vector 1740 . mode - INSERT_VALUES or ADD_VALUES 1741 - l - the local vector 1742 1743 1744 Level: beginner 1745 1746 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1747 1748 @*/ 1749 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 1750 { 1751 PetscSF sf; 1752 PetscErrorCode ierr; 1753 DMGlobalToLocalHookLink link; 1754 1755 PetscFunctionBegin; 1756 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1757 for (link=dm->gtolhook; link; link=link->next) { 1758 if (link->beginhook) { 1759 ierr = (*link->beginhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr); 1760 } 1761 } 1762 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1763 if (sf) { 1764 const PetscScalar *gArray; 1765 PetscScalar *lArray; 1766 1767 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1768 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1769 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 1770 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1771 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1772 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 1773 } else { 1774 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1775 } 1776 PetscFunctionReturn(0); 1777 } 1778 1779 #undef __FUNCT__ 1780 #define __FUNCT__ "DMGlobalToLocalEnd" 1781 /*@ 1782 DMGlobalToLocalEnd - Ends updating local vectors from global vector 1783 1784 Neighbor-wise Collective on DM 1785 1786 Input Parameters: 1787 + dm - the DM object 1788 . g - the global vector 1789 . mode - INSERT_VALUES or ADD_VALUES 1790 - l - the local vector 1791 1792 1793 Level: beginner 1794 1795 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1796 1797 @*/ 1798 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 1799 { 1800 PetscSF sf; 1801 PetscErrorCode ierr; 1802 const PetscScalar *gArray; 1803 PetscScalar *lArray; 1804 DMGlobalToLocalHookLink link; 1805 1806 PetscFunctionBegin; 1807 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1808 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1809 if (sf) { 1810 if (mode == ADD_VALUES) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1811 1812 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1813 ierr = VecGetArrayRead(g, &gArray);CHKERRQ(ierr); 1814 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1815 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1816 ierr = VecRestoreArrayRead(g, &gArray);CHKERRQ(ierr); 1817 } else { 1818 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1819 } 1820 ierr = DMGlobalToLocalHook_Constraints(dm,g,mode,l,NULL);CHKERRQ(ierr); 1821 for (link=dm->gtolhook; link; link=link->next) { 1822 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 1823 } 1824 PetscFunctionReturn(0); 1825 } 1826 1827 #undef __FUNCT__ 1828 #define __FUNCT__ "DMLocalToGlobalHookAdd" 1829 /*@C 1830 DMLocalToGlobalHookAdd - adds a callback to be run when a local to global is called 1831 1832 Logically Collective 1833 1834 Input Arguments: 1835 + dm - the DM 1836 . beginhook - function to run at the beginning of DMLocalToGlobalBegin() 1837 . endhook - function to run after DMLocalToGlobalEnd() has completed 1838 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 1839 1840 Calling sequence for beginhook: 1841 $ beginhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 1842 1843 + dm - global DM 1844 . l - local vector 1845 . mode - mode 1846 . g - global vector 1847 - ctx - optional user-defined function context 1848 1849 1850 Calling sequence for endhook: 1851 $ endhook(DM fine,Vec l,InsertMode mode,Vec g,void *ctx) 1852 1853 + global - global DM 1854 . l - local vector 1855 . mode - mode 1856 . g - global vector 1857 - ctx - optional user-defined function context 1858 1859 Level: advanced 1860 1861 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1862 @*/ 1863 PetscErrorCode DMLocalToGlobalHookAdd(DM dm,PetscErrorCode (*beginhook)(DM,Vec,InsertMode,Vec,void*),PetscErrorCode (*endhook)(DM,Vec,InsertMode,Vec,void*),void *ctx) 1864 { 1865 PetscErrorCode ierr; 1866 DMLocalToGlobalHookLink link,*p; 1867 1868 PetscFunctionBegin; 1869 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1870 for (p=&dm->ltoghook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1871 ierr = PetscMalloc(sizeof(struct _DMLocalToGlobalHookLink),&link);CHKERRQ(ierr); 1872 link->beginhook = beginhook; 1873 link->endhook = endhook; 1874 link->ctx = ctx; 1875 link->next = NULL; 1876 *p = link; 1877 PetscFunctionReturn(0); 1878 } 1879 1880 #undef __FUNCT__ 1881 #define __FUNCT__ "DMLocalToGlobalHook_Constraints" 1882 static PetscErrorCode DMLocalToGlobalHook_Constraints(DM dm, Vec l, InsertMode mode, Vec g, void *ctx) 1883 { 1884 Mat cMat; 1885 Vec cVec; 1886 PetscSection section, cSec; 1887 PetscInt pStart, pEnd, p, dof; 1888 PetscErrorCode ierr; 1889 1890 PetscFunctionBegin; 1891 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1892 ierr = DMGetDefaultConstraints(dm,&cSec,&cMat);CHKERRQ(ierr); 1893 if (cMat && (mode == ADD_VALUES || mode == ADD_ALL_VALUES || mode == ADD_BC_VALUES)) { 1894 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 1895 ierr = MatCreateVecs(cMat,NULL,&cVec);CHKERRQ(ierr); 1896 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 1897 for (p = pStart; p < pEnd; p++) { 1898 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 1899 if (dof) { 1900 PetscInt d; 1901 PetscScalar *vals; 1902 ierr = VecGetValuesSection(l,section,p,&vals);CHKERRQ(ierr); 1903 ierr = VecSetValuesSection(cVec,cSec,p,vals,mode);CHKERRQ(ierr); 1904 /* for this to be the true transpose, we have to zero the values that 1905 * we just extracted */ 1906 for (d = 0; d < dof; d++) { 1907 vals[d] = 0.; 1908 } 1909 } 1910 } 1911 ierr = MatMultTransposeAdd(cMat,cVec,l,l);CHKERRQ(ierr); 1912 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 1913 } 1914 PetscFunctionReturn(0); 1915 } 1916 1917 #undef __FUNCT__ 1918 #define __FUNCT__ "DMLocalToGlobalBegin" 1919 /*@ 1920 DMLocalToGlobalBegin - updates global vectors from local vectors 1921 1922 Neighbor-wise Collective on DM 1923 1924 Input Parameters: 1925 + dm - the DM object 1926 . l - the local vector 1927 . 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. 1928 - g - the global vector 1929 1930 Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. 1931 INSERT_VALUES is not supported for DMDA, in that case simply compute the values directly into a global vector instead of a local one. 1932 1933 Level: beginner 1934 1935 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 1936 1937 @*/ 1938 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 1939 { 1940 PetscSF sf; 1941 PetscSection s, gs; 1942 DMLocalToGlobalHookLink link; 1943 const PetscScalar *lArray; 1944 PetscScalar *gArray; 1945 PetscBool isInsert; 1946 PetscErrorCode ierr; 1947 1948 PetscFunctionBegin; 1949 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1950 for (link=dm->ltoghook; link; link=link->next) { 1951 if (link->beginhook) { 1952 ierr = (*link->beginhook)(dm,l,mode,g,link->ctx);CHKERRQ(ierr); 1953 } 1954 } 1955 ierr = DMLocalToGlobalHook_Constraints(dm,l,mode,g,NULL);CHKERRQ(ierr); 1956 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1957 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 1958 switch (mode) { 1959 case INSERT_VALUES: 1960 case INSERT_ALL_VALUES: 1961 isInsert = PETSC_TRUE; break; 1962 case ADD_VALUES: 1963 case ADD_ALL_VALUES: 1964 isInsert = PETSC_FALSE; break; 1965 default: 1966 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1967 } 1968 if (sf && !isInsert) { 1969 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 1970 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1971 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 1972 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 1973 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1974 } else if (s && isInsert) { 1975 PetscInt gStart, pStart, pEnd, p; 1976 1977 ierr = DMGetDefaultGlobalSection(dm, &gs);CHKERRQ(ierr); 1978 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 1979 ierr = VecGetOwnershipRange(g, &gStart, NULL);CHKERRQ(ierr); 1980 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 1981 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1982 for (p = pStart; p < pEnd; ++p) { 1983 PetscInt dof, gdof, cdof, gcdof, off, goff, d, e; 1984 1985 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 1986 ierr = PetscSectionGetDof(gs, p, &gdof);CHKERRQ(ierr); 1987 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 1988 ierr = PetscSectionGetConstraintDof(gs, p, &gcdof);CHKERRQ(ierr); 1989 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 1990 ierr = PetscSectionGetOffset(gs, p, &goff);CHKERRQ(ierr); 1991 /* Ignore off-process data and points with no global data */ 1992 if (!gdof || goff < 0) continue; 1993 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); 1994 /* If no constraints are enforced in the global vector */ 1995 if (!gcdof) { 1996 for (d = 0; d < dof; ++d) gArray[goff-gStart+d] = lArray[off+d]; 1997 /* If constraints are enforced in the global vector */ 1998 } else if (cdof == gcdof) { 1999 const PetscInt *cdofs; 2000 PetscInt cind = 0; 2001 2002 ierr = PetscSectionGetConstraintIndices(s, p, &cdofs);CHKERRQ(ierr); 2003 for (d = 0, e = 0; d < dof; ++d) { 2004 if ((cind < cdof) && (d == cdofs[cind])) {++cind; continue;} 2005 gArray[goff-gStart+e++] = lArray[off+d]; 2006 } 2007 } 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); 2008 } 2009 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2010 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2011 } else { 2012 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2013 } 2014 PetscFunctionReturn(0); 2015 } 2016 2017 #undef __FUNCT__ 2018 #define __FUNCT__ "DMLocalToGlobalEnd" 2019 /*@ 2020 DMLocalToGlobalEnd - updates global vectors from local vectors 2021 2022 Neighbor-wise Collective on DM 2023 2024 Input Parameters: 2025 + dm - the DM object 2026 . l - the local vector 2027 . mode - INSERT_VALUES or ADD_VALUES 2028 - g - the global vector 2029 2030 2031 Level: beginner 2032 2033 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 2034 2035 @*/ 2036 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 2037 { 2038 PetscSF sf; 2039 PetscSection s; 2040 DMLocalToGlobalHookLink link; 2041 PetscBool isInsert; 2042 PetscErrorCode ierr; 2043 2044 PetscFunctionBegin; 2045 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2046 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 2047 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 2048 switch (mode) { 2049 case INSERT_VALUES: 2050 case INSERT_ALL_VALUES: 2051 isInsert = PETSC_TRUE; break; 2052 case ADD_VALUES: 2053 case ADD_ALL_VALUES: 2054 isInsert = PETSC_FALSE; break; 2055 default: 2056 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 2057 } 2058 if (sf && !isInsert) { 2059 const PetscScalar *lArray; 2060 PetscScalar *gArray; 2061 2062 ierr = VecGetArrayRead(l, &lArray);CHKERRQ(ierr); 2063 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 2064 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_SUM);CHKERRQ(ierr); 2065 ierr = VecRestoreArrayRead(l, &lArray);CHKERRQ(ierr); 2066 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 2067 } else if (s && isInsert) { 2068 } else { 2069 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 2070 } 2071 for (link=dm->ltoghook; link; link=link->next) { 2072 if (link->endhook) {ierr = (*link->endhook)(dm,g,mode,l,link->ctx);CHKERRQ(ierr);} 2073 } 2074 PetscFunctionReturn(0); 2075 } 2076 2077 #undef __FUNCT__ 2078 #define __FUNCT__ "DMLocalToLocalBegin" 2079 /*@ 2080 DMLocalToLocalBegin - Maps from a local vector (including ghost points 2081 that contain irrelevant values) to another local vector where the ghost 2082 points in the second are set correctly. Must be followed by DMLocalToLocalEnd(). 2083 2084 Neighbor-wise Collective on DM and Vec 2085 2086 Input Parameters: 2087 + dm - the DM object 2088 . g - the original local vector 2089 - mode - one of INSERT_VALUES or ADD_VALUES 2090 2091 Output Parameter: 2092 . l - the local vector with correct ghost values 2093 2094 Level: intermediate 2095 2096 Notes: 2097 The local vectors used here need not be the same as those 2098 obtained from DMCreateLocalVector(), BUT they 2099 must have the same parallel data layout; they could, for example, be 2100 obtained with VecDuplicate() from the DM originating vectors. 2101 2102 .keywords: DM, local-to-local, begin 2103 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalEnd(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2104 2105 @*/ 2106 PetscErrorCode DMLocalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 2107 { 2108 PetscErrorCode ierr; 2109 2110 PetscFunctionBegin; 2111 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2112 ierr = (*dm->ops->localtolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2113 PetscFunctionReturn(0); 2114 } 2115 2116 #undef __FUNCT__ 2117 #define __FUNCT__ "DMLocalToLocalEnd" 2118 /*@ 2119 DMLocalToLocalEnd - Maps from a local vector (including ghost points 2120 that contain irrelevant values) to another local vector where the ghost 2121 points in the second are set correctly. Must be preceded by DMLocalToLocalBegin(). 2122 2123 Neighbor-wise Collective on DM and Vec 2124 2125 Input Parameters: 2126 + da - the DM object 2127 . g - the original local vector 2128 - mode - one of INSERT_VALUES or ADD_VALUES 2129 2130 Output Parameter: 2131 . l - the local vector with correct ghost values 2132 2133 Level: intermediate 2134 2135 Notes: 2136 The local vectors used here need not be the same as those 2137 obtained from DMCreateLocalVector(), BUT they 2138 must have the same parallel data layout; they could, for example, be 2139 obtained with VecDuplicate() from the DM originating vectors. 2140 2141 .keywords: DM, local-to-local, end 2142 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateLocalVector(), DMCreateGlobalVector(), DMCreateInterpolation(), DMLocalToLocalBegin(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 2143 2144 @*/ 2145 PetscErrorCode DMLocalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 2146 { 2147 PetscErrorCode ierr; 2148 2149 PetscFunctionBegin; 2150 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2151 ierr = (*dm->ops->localtolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 2152 PetscFunctionReturn(0); 2153 } 2154 2155 2156 #undef __FUNCT__ 2157 #define __FUNCT__ "DMCoarsen" 2158 /*@ 2159 DMCoarsen - Coarsens a DM object 2160 2161 Collective on DM 2162 2163 Input Parameter: 2164 + dm - the DM object 2165 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 2166 2167 Output Parameter: 2168 . dmc - the coarsened DM 2169 2170 Level: developer 2171 2172 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2173 2174 @*/ 2175 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 2176 { 2177 PetscErrorCode ierr; 2178 DMCoarsenHookLink link; 2179 2180 PetscFunctionBegin; 2181 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2182 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 2183 if (!(*dmc)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "NULL coarse mesh produced"); 2184 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2185 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2186 (*dmc)->ctx = dm->ctx; 2187 (*dmc)->levelup = dm->levelup; 2188 (*dmc)->leveldown = dm->leveldown + 1; 2189 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2190 for (link=dm->coarsenhook; link; link=link->next) { 2191 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2192 } 2193 PetscFunctionReturn(0); 2194 } 2195 2196 #undef __FUNCT__ 2197 #define __FUNCT__ "DMCoarsenHookAdd" 2198 /*@C 2199 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2200 2201 Logically Collective 2202 2203 Input Arguments: 2204 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2205 . coarsenhook - function to run when setting up a coarser level 2206 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2207 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2208 2209 Calling sequence of coarsenhook: 2210 $ coarsenhook(DM fine,DM coarse,void *ctx); 2211 2212 + fine - fine level DM 2213 . coarse - coarse level DM to restrict problem to 2214 - ctx - optional user-defined function context 2215 2216 Calling sequence for restricthook: 2217 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2218 2219 + fine - fine level DM 2220 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2221 . rscale - scaling vector for restriction 2222 . inject - matrix restricting by injection 2223 . coarse - coarse level DM to update 2224 - ctx - optional user-defined function context 2225 2226 Level: advanced 2227 2228 Notes: 2229 This function is only needed if auxiliary data needs to be set up on coarse grids. 2230 2231 If this function is called multiple times, the hooks will be run in the order they are added. 2232 2233 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2234 extract the finest level information from its context (instead of from the SNES). 2235 2236 This function is currently not available from Fortran. 2237 2238 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2239 @*/ 2240 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2241 { 2242 PetscErrorCode ierr; 2243 DMCoarsenHookLink link,*p; 2244 2245 PetscFunctionBegin; 2246 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2247 for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2248 ierr = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr); 2249 link->coarsenhook = coarsenhook; 2250 link->restricthook = restricthook; 2251 link->ctx = ctx; 2252 link->next = NULL; 2253 *p = link; 2254 PetscFunctionReturn(0); 2255 } 2256 2257 #undef __FUNCT__ 2258 #define __FUNCT__ "DMRestrict" 2259 /*@ 2260 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 2261 2262 Collective if any hooks are 2263 2264 Input Arguments: 2265 + fine - finer DM to use as a base 2266 . restrct - restriction matrix, apply using MatRestrict() 2267 . inject - injection matrix, also use MatRestrict() 2268 - coarse - coarer DM to update 2269 2270 Level: developer 2271 2272 .seealso: DMCoarsenHookAdd(), MatRestrict() 2273 @*/ 2274 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 2275 { 2276 PetscErrorCode ierr; 2277 DMCoarsenHookLink link; 2278 2279 PetscFunctionBegin; 2280 for (link=fine->coarsenhook; link; link=link->next) { 2281 if (link->restricthook) { 2282 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 2283 } 2284 } 2285 PetscFunctionReturn(0); 2286 } 2287 2288 #undef __FUNCT__ 2289 #define __FUNCT__ "DMSubDomainHookAdd" 2290 /*@C 2291 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 2292 2293 Logically Collective 2294 2295 Input Arguments: 2296 + global - global DM 2297 . ddhook - function to run to pass data to the decomposition DM upon its creation 2298 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2299 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2300 2301 2302 Calling sequence for ddhook: 2303 $ ddhook(DM global,DM block,void *ctx) 2304 2305 + global - global DM 2306 . block - block DM 2307 - ctx - optional user-defined function context 2308 2309 Calling sequence for restricthook: 2310 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 2311 2312 + global - global DM 2313 . out - scatter to the outer (with ghost and overlap points) block vector 2314 . in - scatter to block vector values only owned locally 2315 . block - block DM 2316 - ctx - optional user-defined function context 2317 2318 Level: advanced 2319 2320 Notes: 2321 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 2322 2323 If this function is called multiple times, the hooks will be run in the order they are added. 2324 2325 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2326 extract the global information from its context (instead of from the SNES). 2327 2328 This function is currently not available from Fortran. 2329 2330 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2331 @*/ 2332 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2333 { 2334 PetscErrorCode ierr; 2335 DMSubDomainHookLink link,*p; 2336 2337 PetscFunctionBegin; 2338 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2339 for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2340 ierr = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr); 2341 link->restricthook = restricthook; 2342 link->ddhook = ddhook; 2343 link->ctx = ctx; 2344 link->next = NULL; 2345 *p = link; 2346 PetscFunctionReturn(0); 2347 } 2348 2349 #undef __FUNCT__ 2350 #define __FUNCT__ "DMSubDomainRestrict" 2351 /*@ 2352 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 2353 2354 Collective if any hooks are 2355 2356 Input Arguments: 2357 + fine - finer DM to use as a base 2358 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 2359 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 2360 - coarse - coarer DM to update 2361 2362 Level: developer 2363 2364 .seealso: DMCoarsenHookAdd(), MatRestrict() 2365 @*/ 2366 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 2367 { 2368 PetscErrorCode ierr; 2369 DMSubDomainHookLink link; 2370 2371 PetscFunctionBegin; 2372 for (link=global->subdomainhook; link; link=link->next) { 2373 if (link->restricthook) { 2374 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2375 } 2376 } 2377 PetscFunctionReturn(0); 2378 } 2379 2380 #undef __FUNCT__ 2381 #define __FUNCT__ "DMGetCoarsenLevel" 2382 /*@ 2383 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2384 2385 Not Collective 2386 2387 Input Parameter: 2388 . dm - the DM object 2389 2390 Output Parameter: 2391 . level - number of coarsenings 2392 2393 Level: developer 2394 2395 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2396 2397 @*/ 2398 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2399 { 2400 PetscFunctionBegin; 2401 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2402 *level = dm->leveldown; 2403 PetscFunctionReturn(0); 2404 } 2405 2406 2407 2408 #undef __FUNCT__ 2409 #define __FUNCT__ "DMRefineHierarchy" 2410 /*@C 2411 DMRefineHierarchy - Refines a DM object, all levels at once 2412 2413 Collective on DM 2414 2415 Input Parameter: 2416 + dm - the DM object 2417 - nlevels - the number of levels of refinement 2418 2419 Output Parameter: 2420 . dmf - the refined DM hierarchy 2421 2422 Level: developer 2423 2424 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2425 2426 @*/ 2427 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 2428 { 2429 PetscErrorCode ierr; 2430 2431 PetscFunctionBegin; 2432 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2433 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2434 if (nlevels == 0) PetscFunctionReturn(0); 2435 if (dm->ops->refinehierarchy) { 2436 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2437 } else if (dm->ops->refine) { 2438 PetscInt i; 2439 2440 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2441 for (i=1; i<nlevels; i++) { 2442 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2443 } 2444 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2445 PetscFunctionReturn(0); 2446 } 2447 2448 #undef __FUNCT__ 2449 #define __FUNCT__ "DMCoarsenHierarchy" 2450 /*@C 2451 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2452 2453 Collective on DM 2454 2455 Input Parameter: 2456 + dm - the DM object 2457 - nlevels - the number of levels of coarsening 2458 2459 Output Parameter: 2460 . dmc - the coarsened DM hierarchy 2461 2462 Level: developer 2463 2464 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2465 2466 @*/ 2467 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 2468 { 2469 PetscErrorCode ierr; 2470 2471 PetscFunctionBegin; 2472 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2473 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2474 if (nlevels == 0) PetscFunctionReturn(0); 2475 PetscValidPointer(dmc,3); 2476 if (dm->ops->coarsenhierarchy) { 2477 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 2478 } else if (dm->ops->coarsen) { 2479 PetscInt i; 2480 2481 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 2482 for (i=1; i<nlevels; i++) { 2483 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 2484 } 2485 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 2486 PetscFunctionReturn(0); 2487 } 2488 2489 #undef __FUNCT__ 2490 #define __FUNCT__ "DMCreateAggregates" 2491 /*@ 2492 DMCreateAggregates - Gets the aggregates that map between 2493 grids associated with two DMs. 2494 2495 Collective on DM 2496 2497 Input Parameters: 2498 + dmc - the coarse grid DM 2499 - dmf - the fine grid DM 2500 2501 Output Parameters: 2502 . rest - the restriction matrix (transpose of the projection matrix) 2503 2504 Level: intermediate 2505 2506 .keywords: interpolation, restriction, multigrid 2507 2508 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 2509 @*/ 2510 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 2511 { 2512 PetscErrorCode ierr; 2513 2514 PetscFunctionBegin; 2515 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 2516 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 2517 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 2518 PetscFunctionReturn(0); 2519 } 2520 2521 #undef __FUNCT__ 2522 #define __FUNCT__ "DMSetApplicationContextDestroy" 2523 /*@C 2524 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 2525 2526 Not Collective 2527 2528 Input Parameters: 2529 + dm - the DM object 2530 - destroy - the destroy function 2531 2532 Level: intermediate 2533 2534 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2535 2536 @*/ 2537 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 2538 { 2539 PetscFunctionBegin; 2540 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2541 dm->ctxdestroy = destroy; 2542 PetscFunctionReturn(0); 2543 } 2544 2545 #undef __FUNCT__ 2546 #define __FUNCT__ "DMSetApplicationContext" 2547 /*@ 2548 DMSetApplicationContext - Set a user context into a DM object 2549 2550 Not Collective 2551 2552 Input Parameters: 2553 + dm - the DM object 2554 - ctx - the user context 2555 2556 Level: intermediate 2557 2558 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2559 2560 @*/ 2561 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 2562 { 2563 PetscFunctionBegin; 2564 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2565 dm->ctx = ctx; 2566 PetscFunctionReturn(0); 2567 } 2568 2569 #undef __FUNCT__ 2570 #define __FUNCT__ "DMGetApplicationContext" 2571 /*@ 2572 DMGetApplicationContext - Gets a user context from a DM object 2573 2574 Not Collective 2575 2576 Input Parameter: 2577 . dm - the DM object 2578 2579 Output Parameter: 2580 . ctx - the user context 2581 2582 Level: intermediate 2583 2584 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2585 2586 @*/ 2587 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 2588 { 2589 PetscFunctionBegin; 2590 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2591 *(void**)ctx = dm->ctx; 2592 PetscFunctionReturn(0); 2593 } 2594 2595 #undef __FUNCT__ 2596 #define __FUNCT__ "DMSetVariableBounds" 2597 /*@C 2598 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 2599 2600 Logically Collective on DM 2601 2602 Input Parameter: 2603 + dm - the DM object 2604 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 2605 2606 Level: intermediate 2607 2608 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 2609 DMSetJacobian() 2610 2611 @*/ 2612 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 2613 { 2614 PetscFunctionBegin; 2615 dm->ops->computevariablebounds = f; 2616 PetscFunctionReturn(0); 2617 } 2618 2619 #undef __FUNCT__ 2620 #define __FUNCT__ "DMHasVariableBounds" 2621 /*@ 2622 DMHasVariableBounds - does the DM object have a variable bounds function? 2623 2624 Not Collective 2625 2626 Input Parameter: 2627 . dm - the DM object to destroy 2628 2629 Output Parameter: 2630 . flg - PETSC_TRUE if the variable bounds function exists 2631 2632 Level: developer 2633 2634 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2635 2636 @*/ 2637 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 2638 { 2639 PetscFunctionBegin; 2640 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 2641 PetscFunctionReturn(0); 2642 } 2643 2644 #undef __FUNCT__ 2645 #define __FUNCT__ "DMComputeVariableBounds" 2646 /*@C 2647 DMComputeVariableBounds - compute variable bounds used by SNESVI. 2648 2649 Logically Collective on DM 2650 2651 Input Parameters: 2652 . dm - the DM object 2653 2654 Output parameters: 2655 + xl - lower bound 2656 - xu - upper bound 2657 2658 Level: advanced 2659 2660 Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 2661 2662 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2663 2664 @*/ 2665 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 2666 { 2667 PetscErrorCode ierr; 2668 2669 PetscFunctionBegin; 2670 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 2671 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 2672 if (dm->ops->computevariablebounds) { 2673 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 2674 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 2675 PetscFunctionReturn(0); 2676 } 2677 2678 #undef __FUNCT__ 2679 #define __FUNCT__ "DMHasColoring" 2680 /*@ 2681 DMHasColoring - does the DM object have a method of providing a coloring? 2682 2683 Not Collective 2684 2685 Input Parameter: 2686 . dm - the DM object 2687 2688 Output Parameter: 2689 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 2690 2691 Level: developer 2692 2693 .seealso DMHasFunction(), DMCreateColoring() 2694 2695 @*/ 2696 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 2697 { 2698 PetscFunctionBegin; 2699 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 2700 PetscFunctionReturn(0); 2701 } 2702 2703 #undef __FUNCT__ 2704 #define __FUNCT__ "DMSetVec" 2705 /*@C 2706 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 2707 2708 Collective on DM 2709 2710 Input Parameter: 2711 + dm - the DM object 2712 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 2713 2714 Level: developer 2715 2716 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2717 2718 @*/ 2719 PetscErrorCode DMSetVec(DM dm,Vec x) 2720 { 2721 PetscErrorCode ierr; 2722 2723 PetscFunctionBegin; 2724 if (x) { 2725 if (!dm->x) { 2726 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 2727 } 2728 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 2729 } else if (dm->x) { 2730 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 2731 } 2732 PetscFunctionReturn(0); 2733 } 2734 2735 PetscFunctionList DMList = NULL; 2736 PetscBool DMRegisterAllCalled = PETSC_FALSE; 2737 2738 #undef __FUNCT__ 2739 #define __FUNCT__ "DMSetType" 2740 /*@C 2741 DMSetType - Builds a DM, for a particular DM implementation. 2742 2743 Collective on DM 2744 2745 Input Parameters: 2746 + dm - The DM object 2747 - method - The name of the DM type 2748 2749 Options Database Key: 2750 . -dm_type <type> - Sets the DM type; use -help for a list of available types 2751 2752 Notes: 2753 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 2754 2755 Level: intermediate 2756 2757 .keywords: DM, set, type 2758 .seealso: DMGetType(), DMCreate() 2759 @*/ 2760 PetscErrorCode DMSetType(DM dm, DMType method) 2761 { 2762 PetscErrorCode (*r)(DM); 2763 PetscBool match; 2764 PetscErrorCode ierr; 2765 2766 PetscFunctionBegin; 2767 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2768 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 2769 if (match) PetscFunctionReturn(0); 2770 2771 ierr = DMRegisterAll();CHKERRQ(ierr); 2772 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 2773 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 2774 2775 if (dm->ops->destroy) { 2776 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 2777 dm->ops->destroy = NULL; 2778 } 2779 ierr = (*r)(dm);CHKERRQ(ierr); 2780 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 2781 PetscFunctionReturn(0); 2782 } 2783 2784 #undef __FUNCT__ 2785 #define __FUNCT__ "DMGetType" 2786 /*@C 2787 DMGetType - Gets the DM type name (as a string) from the DM. 2788 2789 Not Collective 2790 2791 Input Parameter: 2792 . dm - The DM 2793 2794 Output Parameter: 2795 . type - The DM type name 2796 2797 Level: intermediate 2798 2799 .keywords: DM, get, type, name 2800 .seealso: DMSetType(), DMCreate() 2801 @*/ 2802 PetscErrorCode DMGetType(DM dm, DMType *type) 2803 { 2804 PetscErrorCode ierr; 2805 2806 PetscFunctionBegin; 2807 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2808 PetscValidPointer(type,2); 2809 ierr = DMRegisterAll();CHKERRQ(ierr); 2810 *type = ((PetscObject)dm)->type_name; 2811 PetscFunctionReturn(0); 2812 } 2813 2814 #undef __FUNCT__ 2815 #define __FUNCT__ "DMConvert" 2816 /*@C 2817 DMConvert - Converts a DM to another DM, either of the same or different type. 2818 2819 Collective on DM 2820 2821 Input Parameters: 2822 + dm - the DM 2823 - newtype - new DM type (use "same" for the same type) 2824 2825 Output Parameter: 2826 . M - pointer to new DM 2827 2828 Notes: 2829 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 2830 the MPI communicator of the generated DM is always the same as the communicator 2831 of the input DM. 2832 2833 Level: intermediate 2834 2835 .seealso: DMCreate() 2836 @*/ 2837 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 2838 { 2839 DM B; 2840 char convname[256]; 2841 PetscBool sametype, issame; 2842 PetscErrorCode ierr; 2843 2844 PetscFunctionBegin; 2845 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2846 PetscValidType(dm,1); 2847 PetscValidPointer(M,3); 2848 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 2849 ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); 2850 { 2851 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 2852 2853 /* 2854 Order of precedence: 2855 1) See if a specialized converter is known to the current DM. 2856 2) See if a specialized converter is known to the desired DM class. 2857 3) See if a good general converter is registered for the desired class 2858 4) See if a good general converter is known for the current matrix. 2859 5) Use a really basic converter. 2860 */ 2861 2862 /* 1) See if a specialized converter is known to the current DM and the desired class */ 2863 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2864 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2865 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2866 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2867 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2868 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 2869 if (conv) goto foundconv; 2870 2871 /* 2) See if a specialized converter is known to the desired DM class. */ 2872 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 2873 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 2874 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2875 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2876 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2877 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2878 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2879 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 2880 if (conv) { 2881 ierr = DMDestroy(&B);CHKERRQ(ierr); 2882 goto foundconv; 2883 } 2884 2885 #if 0 2886 /* 3) See if a good general converter is registered for the desired class */ 2887 conv = B->ops->convertfrom; 2888 ierr = DMDestroy(&B);CHKERRQ(ierr); 2889 if (conv) goto foundconv; 2890 2891 /* 4) See if a good general converter is known for the current matrix */ 2892 if (dm->ops->convert) { 2893 conv = dm->ops->convert; 2894 } 2895 if (conv) goto foundconv; 2896 #endif 2897 2898 /* 5) Use a really basic converter. */ 2899 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 2900 2901 foundconv: 2902 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2903 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 2904 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2905 } 2906 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 2907 PetscFunctionReturn(0); 2908 } 2909 2910 /*--------------------------------------------------------------------------------------------------------------------*/ 2911 2912 #undef __FUNCT__ 2913 #define __FUNCT__ "DMRegister" 2914 /*@C 2915 DMRegister - Adds a new DM component implementation 2916 2917 Not Collective 2918 2919 Input Parameters: 2920 + name - The name of a new user-defined creation routine 2921 - create_func - The creation routine itself 2922 2923 Notes: 2924 DMRegister() may be called multiple times to add several user-defined DMs 2925 2926 2927 Sample usage: 2928 .vb 2929 DMRegister("my_da", MyDMCreate); 2930 .ve 2931 2932 Then, your DM type can be chosen with the procedural interface via 2933 .vb 2934 DMCreate(MPI_Comm, DM *); 2935 DMSetType(DM,"my_da"); 2936 .ve 2937 or at runtime via the option 2938 .vb 2939 -da_type my_da 2940 .ve 2941 2942 Level: advanced 2943 2944 .keywords: DM, register 2945 .seealso: DMRegisterAll(), DMRegisterDestroy() 2946 2947 @*/ 2948 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 2949 { 2950 PetscErrorCode ierr; 2951 2952 PetscFunctionBegin; 2953 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 2954 PetscFunctionReturn(0); 2955 } 2956 2957 #undef __FUNCT__ 2958 #define __FUNCT__ "DMLoad" 2959 /*@C 2960 DMLoad - Loads a DM that has been stored in binary with DMView(). 2961 2962 Collective on PetscViewer 2963 2964 Input Parameters: 2965 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 2966 some related function before a call to DMLoad(). 2967 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 2968 HDF5 file viewer, obtained from PetscViewerHDF5Open() 2969 2970 Level: intermediate 2971 2972 Notes: 2973 The type is determined by the data in the file, any type set into the DM before this call is ignored. 2974 2975 Notes for advanced users: 2976 Most users should not need to know the details of the binary storage 2977 format, since DMLoad() and DMView() completely hide these details. 2978 But for anyone who's interested, the standard binary matrix storage 2979 format is 2980 .vb 2981 has not yet been determined 2982 .ve 2983 2984 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 2985 @*/ 2986 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 2987 { 2988 PetscBool isbinary, ishdf5; 2989 PetscErrorCode ierr; 2990 2991 PetscFunctionBegin; 2992 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 2993 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 2994 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 2995 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 2996 if (isbinary) { 2997 PetscInt classid; 2998 char type[256]; 2999 3000 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3001 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3002 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3003 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3004 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3005 } else if (ishdf5) { 3006 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3007 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3008 PetscFunctionReturn(0); 3009 } 3010 3011 /******************************** FEM Support **********************************/ 3012 3013 #undef __FUNCT__ 3014 #define __FUNCT__ "DMPrintCellVector" 3015 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3016 { 3017 PetscInt f; 3018 PetscErrorCode ierr; 3019 3020 PetscFunctionBegin; 3021 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3022 for (f = 0; f < len; ++f) { 3023 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3024 } 3025 PetscFunctionReturn(0); 3026 } 3027 3028 #undef __FUNCT__ 3029 #define __FUNCT__ "DMPrintCellMatrix" 3030 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3031 { 3032 PetscInt f, g; 3033 PetscErrorCode ierr; 3034 3035 PetscFunctionBegin; 3036 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3037 for (f = 0; f < rows; ++f) { 3038 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3039 for (g = 0; g < cols; ++g) { 3040 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3041 } 3042 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3043 } 3044 PetscFunctionReturn(0); 3045 } 3046 3047 #undef __FUNCT__ 3048 #define __FUNCT__ "DMPrintLocalVec" 3049 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3050 { 3051 PetscMPIInt rank, numProcs; 3052 PetscInt p; 3053 PetscErrorCode ierr; 3054 3055 PetscFunctionBegin; 3056 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 3057 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 3058 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr); 3059 for (p = 0; p < numProcs; ++p) { 3060 if (p == rank) { 3061 Vec x; 3062 3063 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3064 ierr = VecCopy(X, x);CHKERRQ(ierr); 3065 ierr = VecChop(x, tol);CHKERRQ(ierr); 3066 ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3067 ierr = VecDestroy(&x);CHKERRQ(ierr); 3068 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3069 } 3070 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 3071 } 3072 PetscFunctionReturn(0); 3073 } 3074 3075 #undef __FUNCT__ 3076 #define __FUNCT__ "DMGetDefaultSection" 3077 /*@ 3078 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 3079 3080 Input Parameter: 3081 . dm - The DM 3082 3083 Output Parameter: 3084 . section - The PetscSection 3085 3086 Level: intermediate 3087 3088 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3089 3090 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3091 @*/ 3092 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 3093 { 3094 PetscErrorCode ierr; 3095 3096 PetscFunctionBegin; 3097 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3098 PetscValidPointer(section, 2); 3099 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3100 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3101 ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr); 3102 } 3103 *section = dm->defaultSection; 3104 PetscFunctionReturn(0); 3105 } 3106 3107 #undef __FUNCT__ 3108 #define __FUNCT__ "DMSetDefaultSection" 3109 /*@ 3110 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3111 3112 Input Parameters: 3113 + dm - The DM 3114 - section - The PetscSection 3115 3116 Level: intermediate 3117 3118 Note: Any existing Section will be destroyed 3119 3120 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3121 @*/ 3122 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 3123 { 3124 PetscInt numFields = 0; 3125 PetscInt f; 3126 PetscErrorCode ierr; 3127 3128 PetscFunctionBegin; 3129 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3130 if (section) { 3131 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3132 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3133 } 3134 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3135 dm->defaultSection = section; 3136 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3137 if (numFields) { 3138 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3139 for (f = 0; f < numFields; ++f) { 3140 PetscObject disc; 3141 const char *name; 3142 3143 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3144 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3145 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3146 } 3147 } 3148 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3149 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3150 PetscFunctionReturn(0); 3151 } 3152 3153 #undef __FUNCT__ 3154 #define __FUNCT__ "DMGetDefaultConstraints" 3155 /*@ 3156 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3157 3158 not collective 3159 3160 Input Parameter: 3161 . dm - The DM 3162 3163 Output Parameter: 3164 + 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. 3165 - 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. 3166 3167 Level: advanced 3168 3169 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3170 3171 .seealso: DMSetDefaultConstraints() 3172 @*/ 3173 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3174 { 3175 PetscErrorCode ierr; 3176 3177 PetscFunctionBegin; 3178 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3179 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3180 if (section) {*section = dm->defaultConstraintSection;} 3181 if (mat) {*mat = dm->defaultConstraintMat;} 3182 PetscFunctionReturn(0); 3183 } 3184 3185 #undef __FUNCT__ 3186 #define __FUNCT__ "DMSetDefaultConstraints" 3187 /*@ 3188 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3189 3190 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(). 3191 3192 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. 3193 3194 collective on dm 3195 3196 Input Parameters: 3197 + dm - The DM 3198 + 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). 3199 - 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). 3200 3201 Level: advanced 3202 3203 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3204 3205 .seealso: DMGetDefaultConstraints() 3206 @*/ 3207 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3208 { 3209 PetscMPIInt result; 3210 PetscErrorCode ierr; 3211 3212 PetscFunctionBegin; 3213 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3214 if (section) { 3215 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3216 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3217 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3218 } 3219 if (mat) { 3220 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3221 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3222 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3223 } 3224 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3225 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3226 dm->defaultConstraintSection = section; 3227 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3228 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3229 dm->defaultConstraintMat = mat; 3230 PetscFunctionReturn(0); 3231 } 3232 3233 #ifdef PETSC_USE_DEBUG 3234 #undef __FUNCT__ 3235 #define __FUNCT__ "DMDefaultSectionCheckConsistency_Internal" 3236 /* 3237 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3238 3239 Input Parameters: 3240 + dm - The DM 3241 . localSection - PetscSection describing the local data layout 3242 - globalSection - PetscSection describing the global data layout 3243 3244 Level: intermediate 3245 3246 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3247 */ 3248 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3249 { 3250 MPI_Comm comm; 3251 PetscLayout layout; 3252 const PetscInt *ranges; 3253 PetscInt pStart, pEnd, p, nroots; 3254 PetscMPIInt size, rank; 3255 PetscBool valid = PETSC_TRUE, gvalid; 3256 PetscErrorCode ierr; 3257 3258 PetscFunctionBegin; 3259 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3260 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3261 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3262 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3263 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3264 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3265 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3266 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3267 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3268 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3269 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3270 for (p = pStart; p < pEnd; ++p) { 3271 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3272 3273 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3274 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3275 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3276 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3277 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3278 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3279 if (!gdof) continue; /* Censored point */ 3280 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;} 3281 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;} 3282 if (gdof < 0) { 3283 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3284 for (d = 0; d < gsize; ++d) { 3285 PetscInt offset = -(goff+1) + d, r; 3286 3287 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3288 if (r < 0) r = -(r+2); 3289 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;} 3290 } 3291 } 3292 } 3293 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3294 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3295 ierr = MPI_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3296 if (!gvalid) { 3297 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3298 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3299 } 3300 PetscFunctionReturn(0); 3301 } 3302 #endif 3303 3304 #undef __FUNCT__ 3305 #define __FUNCT__ "DMGetDefaultGlobalSection" 3306 /*@ 3307 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3308 3309 Collective on DM 3310 3311 Input Parameter: 3312 . dm - The DM 3313 3314 Output Parameter: 3315 . section - The PetscSection 3316 3317 Level: intermediate 3318 3319 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3320 3321 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3322 @*/ 3323 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3324 { 3325 PetscErrorCode ierr; 3326 3327 PetscFunctionBegin; 3328 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3329 PetscValidPointer(section, 2); 3330 if (!dm->defaultGlobalSection) { 3331 PetscSection s; 3332 3333 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3334 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3335 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3336 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3337 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3338 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3339 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 3340 } 3341 *section = dm->defaultGlobalSection; 3342 PetscFunctionReturn(0); 3343 } 3344 3345 #undef __FUNCT__ 3346 #define __FUNCT__ "DMSetDefaultGlobalSection" 3347 /*@ 3348 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3349 3350 Input Parameters: 3351 + dm - The DM 3352 - section - The PetscSection, or NULL 3353 3354 Level: intermediate 3355 3356 Note: Any existing Section will be destroyed 3357 3358 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3359 @*/ 3360 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3361 { 3362 PetscErrorCode ierr; 3363 3364 PetscFunctionBegin; 3365 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3366 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3367 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3368 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3369 dm->defaultGlobalSection = section; 3370 #ifdef PETSC_USE_DEBUG 3371 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3372 #endif 3373 PetscFunctionReturn(0); 3374 } 3375 3376 #undef __FUNCT__ 3377 #define __FUNCT__ "DMGetDefaultSF" 3378 /*@ 3379 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3380 it is created from the default PetscSection layouts in the DM. 3381 3382 Input Parameter: 3383 . dm - The DM 3384 3385 Output Parameter: 3386 . sf - The PetscSF 3387 3388 Level: intermediate 3389 3390 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3391 3392 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3393 @*/ 3394 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3395 { 3396 PetscInt nroots; 3397 PetscErrorCode ierr; 3398 3399 PetscFunctionBegin; 3400 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3401 PetscValidPointer(sf, 2); 3402 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3403 if (nroots < 0) { 3404 PetscSection section, gSection; 3405 3406 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3407 if (section) { 3408 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3409 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3410 } else { 3411 *sf = NULL; 3412 PetscFunctionReturn(0); 3413 } 3414 } 3415 *sf = dm->defaultSF; 3416 PetscFunctionReturn(0); 3417 } 3418 3419 #undef __FUNCT__ 3420 #define __FUNCT__ "DMSetDefaultSF" 3421 /*@ 3422 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3423 3424 Input Parameters: 3425 + dm - The DM 3426 - sf - The PetscSF 3427 3428 Level: intermediate 3429 3430 Note: Any previous SF is destroyed 3431 3432 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3433 @*/ 3434 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3435 { 3436 PetscErrorCode ierr; 3437 3438 PetscFunctionBegin; 3439 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3440 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3441 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3442 dm->defaultSF = sf; 3443 PetscFunctionReturn(0); 3444 } 3445 3446 #undef __FUNCT__ 3447 #define __FUNCT__ "DMCreateDefaultSF" 3448 /*@C 3449 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3450 describing the data layout. 3451 3452 Input Parameters: 3453 + dm - The DM 3454 . localSection - PetscSection describing the local data layout 3455 - globalSection - PetscSection describing the global data layout 3456 3457 Level: intermediate 3458 3459 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3460 @*/ 3461 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3462 { 3463 MPI_Comm comm; 3464 PetscLayout layout; 3465 const PetscInt *ranges; 3466 PetscInt *local; 3467 PetscSFNode *remote; 3468 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3469 PetscMPIInt size, rank; 3470 PetscErrorCode ierr; 3471 3472 PetscFunctionBegin; 3473 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3474 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3475 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3476 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3477 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3478 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3479 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3480 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3481 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3482 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3483 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3484 for (p = pStart; p < pEnd; ++p) { 3485 PetscInt gdof, gcdof; 3486 3487 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3488 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3489 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)); 3490 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3491 } 3492 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3493 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3494 for (p = pStart, l = 0; p < pEnd; ++p) { 3495 const PetscInt *cind; 3496 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3497 3498 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3499 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3500 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3501 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3502 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3503 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3504 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3505 if (!gdof) continue; /* Censored point */ 3506 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3507 if (gsize != dof-cdof) { 3508 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); 3509 cdof = 0; /* Ignore constraints */ 3510 } 3511 for (d = 0, c = 0; d < dof; ++d) { 3512 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3513 local[l+d-c] = off+d; 3514 } 3515 if (gdof < 0) { 3516 for (d = 0; d < gsize; ++d, ++l) { 3517 PetscInt offset = -(goff+1) + d, r; 3518 3519 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3520 if (r < 0) r = -(r+2); 3521 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); 3522 remote[l].rank = r; 3523 remote[l].index = offset - ranges[r]; 3524 } 3525 } else { 3526 for (d = 0; d < gsize; ++d, ++l) { 3527 remote[l].rank = rank; 3528 remote[l].index = goff+d - ranges[rank]; 3529 } 3530 } 3531 } 3532 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3533 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3534 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3535 PetscFunctionReturn(0); 3536 } 3537 3538 #undef __FUNCT__ 3539 #define __FUNCT__ "DMGetPointSF" 3540 /*@ 3541 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3542 3543 Input Parameter: 3544 . dm - The DM 3545 3546 Output Parameter: 3547 . sf - The PetscSF 3548 3549 Level: intermediate 3550 3551 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3552 3553 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3554 @*/ 3555 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3556 { 3557 PetscFunctionBegin; 3558 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3559 PetscValidPointer(sf, 2); 3560 *sf = dm->sf; 3561 PetscFunctionReturn(0); 3562 } 3563 3564 #undef __FUNCT__ 3565 #define __FUNCT__ "DMSetPointSF" 3566 /*@ 3567 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3568 3569 Input Parameters: 3570 + dm - The DM 3571 - sf - The PetscSF 3572 3573 Level: intermediate 3574 3575 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3576 @*/ 3577 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3578 { 3579 PetscErrorCode ierr; 3580 3581 PetscFunctionBegin; 3582 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3583 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3584 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3585 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3586 dm->sf = sf; 3587 PetscFunctionReturn(0); 3588 } 3589 3590 #undef __FUNCT__ 3591 #define __FUNCT__ "DMGetDS" 3592 /*@ 3593 DMGetDS - Get the PetscDS 3594 3595 Input Parameter: 3596 . dm - The DM 3597 3598 Output Parameter: 3599 . prob - The PetscDS 3600 3601 Level: developer 3602 3603 .seealso: DMSetDS() 3604 @*/ 3605 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3606 { 3607 PetscFunctionBegin; 3608 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3609 PetscValidPointer(prob, 2); 3610 *prob = dm->prob; 3611 PetscFunctionReturn(0); 3612 } 3613 3614 #undef __FUNCT__ 3615 #define __FUNCT__ "DMSetDS" 3616 /*@ 3617 DMSetDS - Set the PetscDS 3618 3619 Input Parameters: 3620 + dm - The DM 3621 - prob - The PetscDS 3622 3623 Level: developer 3624 3625 .seealso: DMGetDS() 3626 @*/ 3627 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3628 { 3629 PetscErrorCode ierr; 3630 3631 PetscFunctionBegin; 3632 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3633 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3634 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3635 dm->prob = prob; 3636 ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr); 3637 PetscFunctionReturn(0); 3638 } 3639 3640 #undef __FUNCT__ 3641 #define __FUNCT__ "DMGetNumFields" 3642 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3643 { 3644 PetscErrorCode ierr; 3645 3646 PetscFunctionBegin; 3647 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3648 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3649 PetscFunctionReturn(0); 3650 } 3651 3652 #undef __FUNCT__ 3653 #define __FUNCT__ "DMSetNumFields" 3654 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3655 { 3656 PetscInt Nf, f; 3657 PetscErrorCode ierr; 3658 3659 PetscFunctionBegin; 3660 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3661 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3662 for (f = Nf; f < numFields; ++f) { 3663 PetscContainer obj; 3664 3665 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3666 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3667 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3668 } 3669 PetscFunctionReturn(0); 3670 } 3671 3672 #undef __FUNCT__ 3673 #define __FUNCT__ "DMGetField" 3674 /*@ 3675 DMGetField - Return the discretization object for a given DM field 3676 3677 Not collective 3678 3679 Input Parameters: 3680 + dm - The DM 3681 - f - The field number 3682 3683 Output Parameter: 3684 . field - The discretization object 3685 3686 Level: developer 3687 3688 .seealso: DMSetField() 3689 @*/ 3690 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3691 { 3692 PetscErrorCode ierr; 3693 3694 PetscFunctionBegin; 3695 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3696 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3697 PetscFunctionReturn(0); 3698 } 3699 3700 #undef __FUNCT__ 3701 #define __FUNCT__ "DMSetField" 3702 /*@ 3703 DMSetField - Set the discretization object for a given DM field 3704 3705 Logically collective on DM 3706 3707 Input Parameters: 3708 + dm - The DM 3709 . f - The field number 3710 - field - The discretization object 3711 3712 Level: developer 3713 3714 .seealso: DMGetField() 3715 @*/ 3716 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3717 { 3718 PetscErrorCode ierr; 3719 3720 PetscFunctionBegin; 3721 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3722 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3723 PetscFunctionReturn(0); 3724 } 3725 3726 #undef __FUNCT__ 3727 #define __FUNCT__ "DMRestrictHook_Coordinates" 3728 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3729 { 3730 DM dm_coord,dmc_coord; 3731 PetscErrorCode ierr; 3732 Vec coords,ccoords; 3733 Mat inject; 3734 PetscFunctionBegin; 3735 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3736 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3737 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3738 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3739 if (coords && !ccoords) { 3740 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3741 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 3742 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 3743 ierr = MatDestroy(&inject);CHKERRQ(ierr); 3744 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3745 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3746 } 3747 PetscFunctionReturn(0); 3748 } 3749 3750 #undef __FUNCT__ 3751 #define __FUNCT__ "DMSubDomainHook_Coordinates" 3752 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 3753 { 3754 DM dm_coord,subdm_coord; 3755 PetscErrorCode ierr; 3756 Vec coords,ccoords,clcoords; 3757 VecScatter *scat_i,*scat_g; 3758 PetscFunctionBegin; 3759 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3760 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 3761 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3762 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 3763 if (coords && !ccoords) { 3764 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 3765 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 3766 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 3767 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3768 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3769 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3770 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3771 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 3772 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 3773 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 3774 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 3775 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3776 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 3777 ierr = PetscFree(scat_i);CHKERRQ(ierr); 3778 ierr = PetscFree(scat_g);CHKERRQ(ierr); 3779 } 3780 PetscFunctionReturn(0); 3781 } 3782 3783 #undef __FUNCT__ 3784 #define __FUNCT__ "DMGetDimension" 3785 /*@ 3786 DMGetDimension - Return the topological dimension of the DM 3787 3788 Not collective 3789 3790 Input Parameter: 3791 . dm - The DM 3792 3793 Output Parameter: 3794 . dim - The topological dimension 3795 3796 Level: beginner 3797 3798 .seealso: DMSetDimension(), DMCreate() 3799 @*/ 3800 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 3801 { 3802 PetscFunctionBegin; 3803 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3804 PetscValidPointer(dim, 2); 3805 *dim = dm->dim; 3806 PetscFunctionReturn(0); 3807 } 3808 3809 #undef __FUNCT__ 3810 #define __FUNCT__ "DMSetDimension" 3811 /*@ 3812 DMSetDimension - Set the topological dimension of the DM 3813 3814 Collective on dm 3815 3816 Input Parameters: 3817 + dm - The DM 3818 - dim - The topological dimension 3819 3820 Level: beginner 3821 3822 .seealso: DMGetDimension(), DMCreate() 3823 @*/ 3824 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 3825 { 3826 PetscFunctionBegin; 3827 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3828 PetscValidLogicalCollectiveInt(dm, dim, 2); 3829 dm->dim = dim; 3830 PetscFunctionReturn(0); 3831 } 3832 3833 #undef __FUNCT__ 3834 #define __FUNCT__ "DMGetDimPoints" 3835 /*@ 3836 DMGetDimPoints - Get the half-open interval for all points of a given dimension 3837 3838 Collective on DM 3839 3840 Input Parameters: 3841 + dm - the DM 3842 - dim - the dimension 3843 3844 Output Parameters: 3845 + pStart - The first point of the given dimension 3846 . pEnd - The first point following points of the given dimension 3847 3848 Note: 3849 The points are vertices in the Hasse diagram encoding the topology. This is explained in 3850 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 3851 then the interval is empty. 3852 3853 Level: intermediate 3854 3855 .keywords: point, Hasse Diagram, dimension 3856 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 3857 @*/ 3858 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 3859 { 3860 PetscInt d; 3861 PetscErrorCode ierr; 3862 3863 PetscFunctionBegin; 3864 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3865 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 3866 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 3867 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 3868 PetscFunctionReturn(0); 3869 } 3870 3871 #undef __FUNCT__ 3872 #define __FUNCT__ "DMSetCoordinates" 3873 /*@ 3874 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 3875 3876 Collective on DM 3877 3878 Input Parameters: 3879 + dm - the DM 3880 - c - coordinate vector 3881 3882 Note: 3883 The coordinates do include those for ghost points, which are in the local vector 3884 3885 Level: intermediate 3886 3887 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3888 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 3889 @*/ 3890 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 3891 { 3892 PetscErrorCode ierr; 3893 3894 PetscFunctionBegin; 3895 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3896 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3897 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3898 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3899 dm->coordinates = c; 3900 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3901 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3902 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3903 PetscFunctionReturn(0); 3904 } 3905 3906 #undef __FUNCT__ 3907 #define __FUNCT__ "DMSetCoordinatesLocal" 3908 /*@ 3909 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 3910 3911 Collective on DM 3912 3913 Input Parameters: 3914 + dm - the DM 3915 - c - coordinate vector 3916 3917 Note: 3918 The coordinates of ghost points can be set using DMSetCoordinates() 3919 followed by DMGetCoordinatesLocal(). This is intended to enable the 3920 setting of ghost coordinates outside of the domain. 3921 3922 Level: intermediate 3923 3924 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3925 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 3926 @*/ 3927 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 3928 { 3929 PetscErrorCode ierr; 3930 3931 PetscFunctionBegin; 3932 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3933 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3934 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3935 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3936 3937 dm->coordinatesLocal = c; 3938 3939 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3940 PetscFunctionReturn(0); 3941 } 3942 3943 #undef __FUNCT__ 3944 #define __FUNCT__ "DMGetCoordinates" 3945 /*@ 3946 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 3947 3948 Not Collective 3949 3950 Input Parameter: 3951 . dm - the DM 3952 3953 Output Parameter: 3954 . c - global coordinate vector 3955 3956 Note: 3957 This is a borrowed reference, so the user should NOT destroy this vector 3958 3959 Each process has only the local coordinates (does NOT have the ghost coordinates). 3960 3961 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3962 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3963 3964 Level: intermediate 3965 3966 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3967 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 3968 @*/ 3969 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 3970 { 3971 PetscErrorCode ierr; 3972 3973 PetscFunctionBegin; 3974 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3975 PetscValidPointer(c,2); 3976 if (!dm->coordinates && dm->coordinatesLocal) { 3977 DM cdm = NULL; 3978 3979 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3980 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 3981 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 3982 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3983 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3984 } 3985 *c = dm->coordinates; 3986 PetscFunctionReturn(0); 3987 } 3988 3989 #undef __FUNCT__ 3990 #define __FUNCT__ "DMGetCoordinatesLocal" 3991 /*@ 3992 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 3993 3994 Collective on DM 3995 3996 Input Parameter: 3997 . dm - the DM 3998 3999 Output Parameter: 4000 . c - coordinate vector 4001 4002 Note: 4003 This is a borrowed reference, so the user should NOT destroy this vector 4004 4005 Each process has the local and ghost coordinates 4006 4007 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4008 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4009 4010 Level: intermediate 4011 4012 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4013 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4014 @*/ 4015 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4016 { 4017 PetscErrorCode ierr; 4018 4019 PetscFunctionBegin; 4020 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4021 PetscValidPointer(c,2); 4022 if (!dm->coordinatesLocal && dm->coordinates) { 4023 DM cdm = NULL; 4024 4025 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4026 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4027 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4028 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4029 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4030 } 4031 *c = dm->coordinatesLocal; 4032 PetscFunctionReturn(0); 4033 } 4034 4035 #undef __FUNCT__ 4036 #define __FUNCT__ "DMGetCoordinateDM" 4037 /*@ 4038 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4039 4040 Collective on DM 4041 4042 Input Parameter: 4043 . dm - the DM 4044 4045 Output Parameter: 4046 . cdm - coordinate DM 4047 4048 Level: intermediate 4049 4050 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4051 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4052 @*/ 4053 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4054 { 4055 PetscErrorCode ierr; 4056 4057 PetscFunctionBegin; 4058 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4059 PetscValidPointer(cdm,2); 4060 if (!dm->coordinateDM) { 4061 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4062 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 4063 } 4064 *cdm = dm->coordinateDM; 4065 PetscFunctionReturn(0); 4066 } 4067 4068 #undef __FUNCT__ 4069 #define __FUNCT__ "DMSetCoordinateDM" 4070 /*@ 4071 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4072 4073 Logically Collective on DM 4074 4075 Input Parameters: 4076 + dm - the DM 4077 - cdm - coordinate DM 4078 4079 Level: intermediate 4080 4081 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4082 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4083 @*/ 4084 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4085 { 4086 PetscErrorCode ierr; 4087 4088 PetscFunctionBegin; 4089 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4090 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4091 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4092 dm->coordinateDM = cdm; 4093 ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr); 4094 PetscFunctionReturn(0); 4095 } 4096 4097 #undef __FUNCT__ 4098 #define __FUNCT__ "DMGetCoordinateDim" 4099 /*@ 4100 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4101 4102 Not Collective 4103 4104 Input Parameter: 4105 . dm - The DM object 4106 4107 Output Parameter: 4108 . dim - The embedding dimension 4109 4110 Level: intermediate 4111 4112 .keywords: mesh, coordinates 4113 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4114 @*/ 4115 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4116 { 4117 PetscFunctionBegin; 4118 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4119 PetscValidPointer(dim, 2); 4120 if (dm->dimEmbed == PETSC_DEFAULT) { 4121 dm->dimEmbed = dm->dim; 4122 } 4123 *dim = dm->dimEmbed; 4124 PetscFunctionReturn(0); 4125 } 4126 4127 #undef __FUNCT__ 4128 #define __FUNCT__ "DMSetCoordinateDim" 4129 /*@ 4130 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4131 4132 Not Collective 4133 4134 Input Parameters: 4135 + dm - The DM object 4136 - dim - The embedding dimension 4137 4138 Level: intermediate 4139 4140 .keywords: mesh, coordinates 4141 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4142 @*/ 4143 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4144 { 4145 PetscFunctionBegin; 4146 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4147 dm->dimEmbed = dim; 4148 PetscFunctionReturn(0); 4149 } 4150 4151 #undef __FUNCT__ 4152 #define __FUNCT__ "DMGetCoordinateSection" 4153 /*@ 4154 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4155 4156 Not Collective 4157 4158 Input Parameter: 4159 . dm - The DM object 4160 4161 Output Parameter: 4162 . section - The PetscSection object 4163 4164 Level: intermediate 4165 4166 .keywords: mesh, coordinates 4167 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4168 @*/ 4169 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4170 { 4171 DM cdm; 4172 PetscErrorCode ierr; 4173 4174 PetscFunctionBegin; 4175 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4176 PetscValidPointer(section, 2); 4177 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4178 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4179 PetscFunctionReturn(0); 4180 } 4181 4182 #undef __FUNCT__ 4183 #define __FUNCT__ "DMSetCoordinateSection" 4184 /*@ 4185 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4186 4187 Not Collective 4188 4189 Input Parameters: 4190 + dm - The DM object 4191 . dim - The embedding dimension, or PETSC_DETERMINE 4192 - section - The PetscSection object 4193 4194 Level: intermediate 4195 4196 .keywords: mesh, coordinates 4197 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4198 @*/ 4199 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4200 { 4201 DM cdm; 4202 PetscErrorCode ierr; 4203 4204 PetscFunctionBegin; 4205 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4206 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4207 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4208 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4209 if (dim == PETSC_DETERMINE) { 4210 PetscInt d = dim; 4211 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4212 4213 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4214 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4215 pStart = PetscMax(vStart, pStart); 4216 pEnd = PetscMin(vEnd, pEnd); 4217 for (v = pStart; v < pEnd; ++v) { 4218 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4219 if (dd) {d = dd; break;} 4220 } 4221 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4222 } 4223 PetscFunctionReturn(0); 4224 } 4225 4226 #undef __FUNCT__ 4227 #define __FUNCT__ "DMGetPeriodicity" 4228 /*@C 4229 DMSetPeriodicity - Set the description of mesh periodicity 4230 4231 Input Parameters: 4232 + dm - The DM object 4233 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4234 . L - If we assume the mesh is a torus, this is the length of each coordinate 4235 - bd - This describes the type of periodicity in each topological dimension 4236 4237 Level: developer 4238 4239 .seealso: DMGetPeriodicity() 4240 @*/ 4241 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4242 { 4243 PetscFunctionBegin; 4244 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4245 if (L) *L = dm->L; 4246 if (maxCell) *maxCell = dm->maxCell; 4247 if (bd) *bd = dm->bdtype; 4248 PetscFunctionReturn(0); 4249 } 4250 4251 #undef __FUNCT__ 4252 #define __FUNCT__ "DMSetPeriodicity" 4253 /*@C 4254 DMSetPeriodicity - Set the description of mesh periodicity 4255 4256 Input Parameters: 4257 + dm - The DM object 4258 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4259 . L - If we assume the mesh is a torus, this is the length of each coordinate 4260 - bd - This describes the type of periodicity in each topological dimension 4261 4262 Level: developer 4263 4264 .seealso: DMGetPeriodicity() 4265 @*/ 4266 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4267 { 4268 PetscInt dim, d; 4269 PetscErrorCode ierr; 4270 4271 PetscFunctionBegin; 4272 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4273 PetscValidPointer(L,3);PetscValidPointer(maxCell,2);PetscValidPointer(bd,4); 4274 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4275 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4276 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4277 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4278 PetscFunctionReturn(0); 4279 } 4280 4281 #undef __FUNCT__ 4282 #define __FUNCT__ "DMLocatePoints" 4283 /*@ 4284 DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells 4285 4286 Not collective 4287 4288 Input Parameters: 4289 + dm - The DM 4290 - v - The Vec of points 4291 4292 Output Parameter: 4293 . cells - The local cell numbers for cells which contain the points 4294 4295 Level: developer 4296 4297 .keywords: point location, mesh 4298 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4299 @*/ 4300 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells) 4301 { 4302 PetscErrorCode ierr; 4303 4304 PetscFunctionBegin; 4305 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4306 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4307 PetscValidPointer(cells,3); 4308 if (dm->ops->locatepoints) { 4309 ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr); 4310 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4311 PetscFunctionReturn(0); 4312 } 4313 4314 #undef __FUNCT__ 4315 #define __FUNCT__ "DMGetOutputDM" 4316 /*@ 4317 DMGetOutputDM - Retrieve the DM associated with the layout for output 4318 4319 Input Parameter: 4320 . dm - The original DM 4321 4322 Output Parameter: 4323 . odm - The DM which provides the layout for output 4324 4325 Level: intermediate 4326 4327 .seealso: VecView(), DMGetDefaultGlobalSection() 4328 @*/ 4329 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4330 { 4331 PetscSection section; 4332 PetscBool hasConstraints; 4333 PetscErrorCode ierr; 4334 4335 PetscFunctionBegin; 4336 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4337 PetscValidPointer(odm,2); 4338 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4339 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4340 if (!hasConstraints) { 4341 *odm = dm; 4342 PetscFunctionReturn(0); 4343 } 4344 if (!dm->dmBC) { 4345 PetscSection newSection, gsection; 4346 PetscSF sf; 4347 4348 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4349 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4350 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4351 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4352 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4353 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 4354 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4355 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4356 } 4357 *odm = dm->dmBC; 4358 PetscFunctionReturn(0); 4359 } 4360 4361 #undef __FUNCT__ 4362 #define __FUNCT__ "DMGetOutputSequenceNumber" 4363 /*@ 4364 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 4365 4366 Input Parameter: 4367 . dm - The original DM 4368 4369 Output Parameters: 4370 + num - The output sequence number 4371 - val - The output sequence value 4372 4373 Level: intermediate 4374 4375 Note: This is intended for output that should appear in sequence, for instance 4376 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4377 4378 .seealso: VecView() 4379 @*/ 4380 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 4381 { 4382 PetscFunctionBegin; 4383 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4384 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 4385 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 4386 PetscFunctionReturn(0); 4387 } 4388 4389 #undef __FUNCT__ 4390 #define __FUNCT__ "DMSetOutputSequenceNumber" 4391 /*@ 4392 DMSetOutputSequenceNumber - Set the sequence number/value for output 4393 4394 Input Parameters: 4395 + dm - The original DM 4396 . num - The output sequence number 4397 - val - The output sequence value 4398 4399 Level: intermediate 4400 4401 Note: This is intended for output that should appear in sequence, for instance 4402 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4403 4404 .seealso: VecView() 4405 @*/ 4406 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 4407 { 4408 PetscFunctionBegin; 4409 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4410 dm->outputSequenceNum = num; 4411 dm->outputSequenceVal = val; 4412 PetscFunctionReturn(0); 4413 } 4414 4415 #undef __FUNCT__ 4416 #define __FUNCT__ "DMOutputSequenceLoad" 4417 /*@C 4418 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 4419 4420 Input Parameters: 4421 + dm - The original DM 4422 . name - The sequence name 4423 - num - The output sequence number 4424 4425 Output Parameter: 4426 . val - The output sequence value 4427 4428 Level: intermediate 4429 4430 Note: This is intended for output that should appear in sequence, for instance 4431 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4432 4433 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 4434 @*/ 4435 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 4436 { 4437 PetscBool ishdf5; 4438 PetscErrorCode ierr; 4439 4440 PetscFunctionBegin; 4441 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4442 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4443 PetscValidPointer(val,4); 4444 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4445 if (ishdf5) { 4446 #if defined(PETSC_HAVE_HDF5) 4447 PetscScalar value; 4448 4449 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 4450 *val = PetscRealPart(value); 4451 #endif 4452 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 4453 PetscFunctionReturn(0); 4454 } 4455 4456 #undef __FUNCT__ 4457 #define __FUNCT__ "DMGetUseNatural" 4458 /*@ 4459 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 4460 4461 Not collective 4462 4463 Input Parameter: 4464 . dm - The DM 4465 4466 Output Parameter: 4467 . useNatural - The flag to build the mapping to a natural order during distribution 4468 4469 Level: beginner 4470 4471 .seealso: DMSetUseNatural(), DMCreate() 4472 @*/ 4473 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 4474 { 4475 PetscFunctionBegin; 4476 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4477 PetscValidPointer(useNatural, 2); 4478 *useNatural = dm->useNatural; 4479 PetscFunctionReturn(0); 4480 } 4481 4482 #undef __FUNCT__ 4483 #define __FUNCT__ "DMSetUseNatural" 4484 /*@ 4485 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 4486 4487 Collective on dm 4488 4489 Input Parameters: 4490 + dm - The DM 4491 - useNatural - The flag to build the mapping to a natural order during distribution 4492 4493 Level: beginner 4494 4495 .seealso: DMGetUseNatural(), DMCreate() 4496 @*/ 4497 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 4498 { 4499 PetscFunctionBegin; 4500 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4501 PetscValidLogicalCollectiveInt(dm, useNatural, 2); 4502 dm->useNatural = useNatural; 4503 PetscFunctionReturn(0); 4504 } 4505