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