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