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