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