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 vector packer or DMDA. 634 635 Collective on DM 636 637 Input Parameter: 638 + dm - the DM object to view 639 - v - the viewer 640 641 Level: developer 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, "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; 3057 PetscInt f; 3058 PetscErrorCode ierr; 3059 3060 PetscFunctionBegin; 3061 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3062 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3063 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3064 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3065 dm->defaultSection = section; 3066 ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr); 3067 if (numFields) { 3068 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3069 for (f = 0; f < numFields; ++f) { 3070 PetscObject disc; 3071 const char *name; 3072 3073 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3074 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3075 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3076 } 3077 } 3078 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3079 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3080 PetscFunctionReturn(0); 3081 } 3082 3083 #undef __FUNCT__ 3084 #define __FUNCT__ "DMGetDefaultConstraints" 3085 /*@ 3086 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3087 3088 not collective 3089 3090 Input Parameter: 3091 . dm - The DM 3092 3093 Output Parameter: 3094 + 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. 3095 - 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. 3096 3097 Level: advanced 3098 3099 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3100 3101 .seealso: DMSetDefaultConstraints() 3102 @*/ 3103 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3104 { 3105 PetscErrorCode ierr; 3106 3107 PetscFunctionBegin; 3108 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3109 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3110 if (section) {*section = dm->defaultConstraintSection;} 3111 if (mat) {*mat = dm->defaultConstraintMat;} 3112 PetscFunctionReturn(0); 3113 } 3114 3115 #undef __FUNCT__ 3116 #define __FUNCT__ "DMSetDefaultConstraints" 3117 /*@ 3118 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3119 3120 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(). 3121 3122 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. 3123 3124 collective on dm 3125 3126 Input Parameters: 3127 + dm - The DM 3128 + 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). 3129 - 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). 3130 3131 Level: advanced 3132 3133 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3134 3135 .seealso: DMGetDefaultConstraints() 3136 @*/ 3137 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3138 { 3139 PetscMPIInt result; 3140 PetscErrorCode ierr; 3141 3142 PetscFunctionBegin; 3143 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3144 if (section) { 3145 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3146 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3147 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3148 } 3149 if (mat) { 3150 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3151 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3152 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3153 } 3154 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3155 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3156 dm->defaultConstraintSection = section; 3157 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3158 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3159 dm->defaultConstraintMat = mat; 3160 PetscFunctionReturn(0); 3161 } 3162 3163 #ifdef PETSC_USE_DEBUG 3164 #undef __FUNCT__ 3165 #define __FUNCT__ "DMDefaultSectionCheckConsistency_Internal" 3166 /* 3167 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3168 3169 Input Parameters: 3170 + dm - The DM 3171 . localSection - PetscSection describing the local data layout 3172 - globalSection - PetscSection describing the global data layout 3173 3174 Level: intermediate 3175 3176 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3177 */ 3178 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3179 { 3180 MPI_Comm comm; 3181 PetscLayout layout; 3182 const PetscInt *ranges; 3183 PetscInt pStart, pEnd, p, nroots; 3184 PetscMPIInt size, rank; 3185 PetscBool valid = PETSC_TRUE, gvalid; 3186 PetscErrorCode ierr; 3187 3188 PetscFunctionBegin; 3189 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3190 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3191 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3192 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3193 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3194 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3195 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3196 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3197 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3198 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3199 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3200 for (p = pStart; p < pEnd; ++p) { 3201 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3202 3203 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3204 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3205 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3206 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3207 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3208 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3209 if (!gdof) continue; /* Censored point */ 3210 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;} 3211 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;} 3212 if (gdof < 0) { 3213 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3214 for (d = 0; d < gsize; ++d) { 3215 PetscInt offset = -(goff+1) + d, r; 3216 3217 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3218 if (r < 0) r = -(r+2); 3219 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;} 3220 } 3221 } 3222 } 3223 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3224 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3225 ierr = MPI_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3226 if (!gvalid) { 3227 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3228 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3229 } 3230 PetscFunctionReturn(0); 3231 } 3232 #endif 3233 3234 #undef __FUNCT__ 3235 #define __FUNCT__ "DMGetDefaultGlobalSection" 3236 /*@ 3237 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3238 3239 Collective on DM 3240 3241 Input Parameter: 3242 . dm - The DM 3243 3244 Output Parameter: 3245 . section - The PetscSection 3246 3247 Level: intermediate 3248 3249 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3250 3251 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3252 @*/ 3253 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3254 { 3255 PetscErrorCode ierr; 3256 3257 PetscFunctionBegin; 3258 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3259 PetscValidPointer(section, 2); 3260 if (!dm->defaultGlobalSection) { 3261 PetscSection s; 3262 3263 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3264 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3265 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3266 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3267 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3268 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3269 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, "global_", "-section_view");CHKERRQ(ierr); 3270 } 3271 *section = dm->defaultGlobalSection; 3272 PetscFunctionReturn(0); 3273 } 3274 3275 #undef __FUNCT__ 3276 #define __FUNCT__ "DMSetDefaultGlobalSection" 3277 /*@ 3278 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3279 3280 Input Parameters: 3281 + dm - The DM 3282 - section - The PetscSection, or NULL 3283 3284 Level: intermediate 3285 3286 Note: Any existing Section will be destroyed 3287 3288 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3289 @*/ 3290 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3291 { 3292 PetscErrorCode ierr; 3293 3294 PetscFunctionBegin; 3295 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3296 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3297 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3298 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3299 dm->defaultGlobalSection = section; 3300 #ifdef PETSC_USE_DEBUG 3301 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3302 #endif 3303 PetscFunctionReturn(0); 3304 } 3305 3306 #undef __FUNCT__ 3307 #define __FUNCT__ "DMGetDefaultSF" 3308 /*@ 3309 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3310 it is created from the default PetscSection layouts in the DM. 3311 3312 Input Parameter: 3313 . dm - The DM 3314 3315 Output Parameter: 3316 . sf - The PetscSF 3317 3318 Level: intermediate 3319 3320 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3321 3322 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3323 @*/ 3324 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3325 { 3326 PetscInt nroots; 3327 PetscErrorCode ierr; 3328 3329 PetscFunctionBegin; 3330 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3331 PetscValidPointer(sf, 2); 3332 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3333 if (nroots < 0) { 3334 PetscSection section, gSection; 3335 3336 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3337 if (section) { 3338 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3339 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3340 } else { 3341 *sf = NULL; 3342 PetscFunctionReturn(0); 3343 } 3344 } 3345 *sf = dm->defaultSF; 3346 PetscFunctionReturn(0); 3347 } 3348 3349 #undef __FUNCT__ 3350 #define __FUNCT__ "DMSetDefaultSF" 3351 /*@ 3352 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3353 3354 Input Parameters: 3355 + dm - The DM 3356 - sf - The PetscSF 3357 3358 Level: intermediate 3359 3360 Note: Any previous SF is destroyed 3361 3362 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3363 @*/ 3364 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3365 { 3366 PetscErrorCode ierr; 3367 3368 PetscFunctionBegin; 3369 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3370 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3371 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3372 dm->defaultSF = sf; 3373 PetscFunctionReturn(0); 3374 } 3375 3376 #undef __FUNCT__ 3377 #define __FUNCT__ "DMCreateDefaultSF" 3378 /*@C 3379 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3380 describing the data layout. 3381 3382 Input Parameters: 3383 + dm - The DM 3384 . localSection - PetscSection describing the local data layout 3385 - globalSection - PetscSection describing the global data layout 3386 3387 Level: intermediate 3388 3389 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3390 @*/ 3391 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3392 { 3393 MPI_Comm comm; 3394 PetscLayout layout; 3395 const PetscInt *ranges; 3396 PetscInt *local; 3397 PetscSFNode *remote; 3398 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3399 PetscMPIInt size, rank; 3400 PetscErrorCode ierr; 3401 3402 PetscFunctionBegin; 3403 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3404 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3405 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3406 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3407 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3408 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3409 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3410 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3411 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3412 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3413 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3414 for (p = pStart; p < pEnd; ++p) { 3415 PetscInt gdof, gcdof; 3416 3417 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3418 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3419 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)); 3420 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3421 } 3422 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3423 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3424 for (p = pStart, l = 0; p < pEnd; ++p) { 3425 const PetscInt *cind; 3426 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3427 3428 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3429 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3430 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3431 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3432 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3433 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3434 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3435 if (!gdof) continue; /* Censored point */ 3436 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3437 if (gsize != dof-cdof) { 3438 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); 3439 cdof = 0; /* Ignore constraints */ 3440 } 3441 for (d = 0, c = 0; d < dof; ++d) { 3442 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3443 local[l+d-c] = off+d; 3444 } 3445 if (gdof < 0) { 3446 for (d = 0; d < gsize; ++d, ++l) { 3447 PetscInt offset = -(goff+1) + d, r; 3448 3449 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3450 if (r < 0) r = -(r+2); 3451 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); 3452 remote[l].rank = r; 3453 remote[l].index = offset - ranges[r]; 3454 } 3455 } else { 3456 for (d = 0; d < gsize; ++d, ++l) { 3457 remote[l].rank = rank; 3458 remote[l].index = goff+d - ranges[rank]; 3459 } 3460 } 3461 } 3462 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3463 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3464 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3465 PetscFunctionReturn(0); 3466 } 3467 3468 #undef __FUNCT__ 3469 #define __FUNCT__ "DMGetPointSF" 3470 /*@ 3471 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3472 3473 Input Parameter: 3474 . dm - The DM 3475 3476 Output Parameter: 3477 . sf - The PetscSF 3478 3479 Level: intermediate 3480 3481 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3482 3483 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3484 @*/ 3485 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3486 { 3487 PetscFunctionBegin; 3488 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3489 PetscValidPointer(sf, 2); 3490 *sf = dm->sf; 3491 PetscFunctionReturn(0); 3492 } 3493 3494 #undef __FUNCT__ 3495 #define __FUNCT__ "DMSetPointSF" 3496 /*@ 3497 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3498 3499 Input Parameters: 3500 + dm - The DM 3501 - sf - The PetscSF 3502 3503 Level: intermediate 3504 3505 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3506 @*/ 3507 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3508 { 3509 PetscErrorCode ierr; 3510 3511 PetscFunctionBegin; 3512 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3513 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3514 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3515 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3516 dm->sf = sf; 3517 PetscFunctionReturn(0); 3518 } 3519 3520 #undef __FUNCT__ 3521 #define __FUNCT__ "DMGetDS" 3522 /*@ 3523 DMGetDS - Get the PetscDS 3524 3525 Input Parameter: 3526 . dm - The DM 3527 3528 Output Parameter: 3529 . prob - The PetscDS 3530 3531 Level: developer 3532 3533 .seealso: DMSetDS() 3534 @*/ 3535 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3536 { 3537 PetscFunctionBegin; 3538 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3539 PetscValidPointer(prob, 2); 3540 *prob = dm->prob; 3541 PetscFunctionReturn(0); 3542 } 3543 3544 #undef __FUNCT__ 3545 #define __FUNCT__ "DMSetDS" 3546 /*@ 3547 DMSetDS - Set the PetscDS 3548 3549 Input Parameters: 3550 + dm - The DM 3551 - prob - The PetscDS 3552 3553 Level: developer 3554 3555 .seealso: DMGetDS() 3556 @*/ 3557 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3558 { 3559 PetscErrorCode ierr; 3560 3561 PetscFunctionBegin; 3562 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3563 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3564 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3565 dm->prob = prob; 3566 ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr); 3567 PetscFunctionReturn(0); 3568 } 3569 3570 #undef __FUNCT__ 3571 #define __FUNCT__ "DMGetNumFields" 3572 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3573 { 3574 PetscErrorCode ierr; 3575 3576 PetscFunctionBegin; 3577 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3578 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3579 PetscFunctionReturn(0); 3580 } 3581 3582 #undef __FUNCT__ 3583 #define __FUNCT__ "DMSetNumFields" 3584 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3585 { 3586 PetscInt Nf, f; 3587 PetscErrorCode ierr; 3588 3589 PetscFunctionBegin; 3590 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3591 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3592 for (f = Nf; f < numFields; ++f) { 3593 PetscContainer obj; 3594 3595 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3596 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3597 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3598 } 3599 PetscFunctionReturn(0); 3600 } 3601 3602 #undef __FUNCT__ 3603 #define __FUNCT__ "DMGetField" 3604 /*@ 3605 DMGetField - Return the discretization object for a given DM field 3606 3607 Not collective 3608 3609 Input Parameters: 3610 + dm - The DM 3611 - f - The field number 3612 3613 Output Parameter: 3614 . field - The discretization object 3615 3616 Level: developer 3617 3618 .seealso: DMSetField() 3619 @*/ 3620 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3621 { 3622 PetscErrorCode ierr; 3623 3624 PetscFunctionBegin; 3625 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3626 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3627 PetscFunctionReturn(0); 3628 } 3629 3630 #undef __FUNCT__ 3631 #define __FUNCT__ "DMSetField" 3632 /*@ 3633 DMSetField - Set the discretization object for a given DM field 3634 3635 Logically collective on DM 3636 3637 Input Parameters: 3638 + dm - The DM 3639 . f - The field number 3640 - field - The discretization object 3641 3642 Level: developer 3643 3644 .seealso: DMGetField() 3645 @*/ 3646 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3647 { 3648 PetscErrorCode ierr; 3649 3650 PetscFunctionBegin; 3651 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3652 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3653 PetscFunctionReturn(0); 3654 } 3655 3656 #undef __FUNCT__ 3657 #define __FUNCT__ "DMRestrictHook_Coordinates" 3658 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3659 { 3660 DM dm_coord,dmc_coord; 3661 PetscErrorCode ierr; 3662 Vec coords,ccoords; 3663 Mat inject; 3664 PetscFunctionBegin; 3665 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3666 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3667 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3668 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3669 if (coords && !ccoords) { 3670 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3671 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 3672 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 3673 ierr = MatDestroy(&inject);CHKERRQ(ierr); 3674 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3675 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3676 } 3677 PetscFunctionReturn(0); 3678 } 3679 3680 #undef __FUNCT__ 3681 #define __FUNCT__ "DMSubDomainHook_Coordinates" 3682 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 3683 { 3684 DM dm_coord,subdm_coord; 3685 PetscErrorCode ierr; 3686 Vec coords,ccoords,clcoords; 3687 VecScatter *scat_i,*scat_g; 3688 PetscFunctionBegin; 3689 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3690 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 3691 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3692 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 3693 if (coords && !ccoords) { 3694 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 3695 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 3696 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 3697 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3698 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3699 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3700 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3701 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 3702 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 3703 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 3704 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 3705 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3706 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 3707 ierr = PetscFree(scat_i);CHKERRQ(ierr); 3708 ierr = PetscFree(scat_g);CHKERRQ(ierr); 3709 } 3710 PetscFunctionReturn(0); 3711 } 3712 3713 #undef __FUNCT__ 3714 #define __FUNCT__ "DMGetDimension" 3715 /*@ 3716 DMGetDimension - Return the topological dimension of the DM 3717 3718 Not collective 3719 3720 Input Parameter: 3721 . dm - The DM 3722 3723 Output Parameter: 3724 . dim - The topological dimension 3725 3726 Level: beginner 3727 3728 .seealso: DMSetDimension(), DMCreate() 3729 @*/ 3730 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 3731 { 3732 PetscFunctionBegin; 3733 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3734 PetscValidPointer(dim, 2); 3735 *dim = dm->dim; 3736 PetscFunctionReturn(0); 3737 } 3738 3739 #undef __FUNCT__ 3740 #define __FUNCT__ "DMSetDimension" 3741 /*@ 3742 DMSetDimension - Set the topological dimension of the DM 3743 3744 Collective on dm 3745 3746 Input Parameters: 3747 + dm - The DM 3748 - dim - The topological dimension 3749 3750 Level: beginner 3751 3752 .seealso: DMGetDimension(), DMCreate() 3753 @*/ 3754 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 3755 { 3756 PetscFunctionBegin; 3757 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3758 PetscValidLogicalCollectiveInt(dm, dim, 2); 3759 dm->dim = dim; 3760 PetscFunctionReturn(0); 3761 } 3762 3763 #undef __FUNCT__ 3764 #define __FUNCT__ "DMGetDimPoints" 3765 /*@ 3766 DMGetDimPoints - Get the half-open interval for all points of a given dimension 3767 3768 Collective on DM 3769 3770 Input Parameters: 3771 + dm - the DM 3772 - dim - the dimension 3773 3774 Output Parameters: 3775 + pStart - The first point of the given dimension 3776 . pEnd - The first point following points of the given dimension 3777 3778 Note: 3779 The points are vertices in the Hasse diagram encoding the topology. This is explained in 3780 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 3781 then the interval is empty. 3782 3783 Level: intermediate 3784 3785 .keywords: point, Hasse Diagram, dimension 3786 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 3787 @*/ 3788 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 3789 { 3790 PetscInt d; 3791 PetscErrorCode ierr; 3792 3793 PetscFunctionBegin; 3794 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3795 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 3796 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 3797 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 3798 PetscFunctionReturn(0); 3799 } 3800 3801 #undef __FUNCT__ 3802 #define __FUNCT__ "DMSetCoordinates" 3803 /*@ 3804 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 3805 3806 Collective on DM 3807 3808 Input Parameters: 3809 + dm - the DM 3810 - c - coordinate vector 3811 3812 Note: 3813 The coordinates do include those for ghost points, which are in the local vector 3814 3815 Level: intermediate 3816 3817 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3818 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 3819 @*/ 3820 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 3821 { 3822 PetscErrorCode ierr; 3823 3824 PetscFunctionBegin; 3825 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3826 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3827 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3828 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3829 dm->coordinates = c; 3830 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3831 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3832 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3833 PetscFunctionReturn(0); 3834 } 3835 3836 #undef __FUNCT__ 3837 #define __FUNCT__ "DMSetCoordinatesLocal" 3838 /*@ 3839 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 3840 3841 Collective on DM 3842 3843 Input Parameters: 3844 + dm - the DM 3845 - c - coordinate vector 3846 3847 Note: 3848 The coordinates of ghost points can be set using DMSetCoordinates() 3849 followed by DMGetCoordinatesLocal(). This is intended to enable the 3850 setting of ghost coordinates outside of the domain. 3851 3852 Level: intermediate 3853 3854 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3855 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 3856 @*/ 3857 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 3858 { 3859 PetscErrorCode ierr; 3860 3861 PetscFunctionBegin; 3862 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3863 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3864 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3865 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3866 3867 dm->coordinatesLocal = c; 3868 3869 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3870 PetscFunctionReturn(0); 3871 } 3872 3873 #undef __FUNCT__ 3874 #define __FUNCT__ "DMGetCoordinates" 3875 /*@ 3876 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 3877 3878 Not Collective 3879 3880 Input Parameter: 3881 . dm - the DM 3882 3883 Output Parameter: 3884 . c - global coordinate vector 3885 3886 Note: 3887 This is a borrowed reference, so the user should NOT destroy this vector 3888 3889 Each process has only the local coordinates (does NOT have the ghost coordinates). 3890 3891 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3892 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3893 3894 Level: intermediate 3895 3896 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3897 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 3898 @*/ 3899 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 3900 { 3901 PetscErrorCode ierr; 3902 3903 PetscFunctionBegin; 3904 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3905 PetscValidPointer(c,2); 3906 if (!dm->coordinates && dm->coordinatesLocal) { 3907 DM cdm = NULL; 3908 3909 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3910 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 3911 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 3912 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3913 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3914 } 3915 *c = dm->coordinates; 3916 PetscFunctionReturn(0); 3917 } 3918 3919 #undef __FUNCT__ 3920 #define __FUNCT__ "DMGetCoordinatesLocal" 3921 /*@ 3922 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 3923 3924 Collective on DM 3925 3926 Input Parameter: 3927 . dm - the DM 3928 3929 Output Parameter: 3930 . c - coordinate vector 3931 3932 Note: 3933 This is a borrowed reference, so the user should NOT destroy this vector 3934 3935 Each process has the local and ghost coordinates 3936 3937 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3938 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3939 3940 Level: intermediate 3941 3942 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3943 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 3944 @*/ 3945 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 3946 { 3947 PetscErrorCode ierr; 3948 3949 PetscFunctionBegin; 3950 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3951 PetscValidPointer(c,2); 3952 if (!dm->coordinatesLocal && dm->coordinates) { 3953 DM cdm = NULL; 3954 3955 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3956 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 3957 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 3958 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3959 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3960 } 3961 *c = dm->coordinatesLocal; 3962 PetscFunctionReturn(0); 3963 } 3964 3965 #undef __FUNCT__ 3966 #define __FUNCT__ "DMGetCoordinateDM" 3967 /*@ 3968 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 3969 3970 Collective on DM 3971 3972 Input Parameter: 3973 . dm - the DM 3974 3975 Output Parameter: 3976 . cdm - coordinate DM 3977 3978 Level: intermediate 3979 3980 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3981 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3982 @*/ 3983 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 3984 { 3985 PetscErrorCode ierr; 3986 3987 PetscFunctionBegin; 3988 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3989 PetscValidPointer(cdm,2); 3990 if (!dm->coordinateDM) { 3991 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 3992 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 3993 } 3994 *cdm = dm->coordinateDM; 3995 PetscFunctionReturn(0); 3996 } 3997 3998 #undef __FUNCT__ 3999 #define __FUNCT__ "DMSetCoordinateDM" 4000 /*@ 4001 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4002 4003 Logically Collective on DM 4004 4005 Input Parameters: 4006 + dm - the DM 4007 - cdm - coordinate DM 4008 4009 Level: intermediate 4010 4011 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4012 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4013 @*/ 4014 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4015 { 4016 PetscErrorCode ierr; 4017 4018 PetscFunctionBegin; 4019 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4020 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4021 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4022 dm->coordinateDM = cdm; 4023 ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr); 4024 PetscFunctionReturn(0); 4025 } 4026 4027 #undef __FUNCT__ 4028 #define __FUNCT__ "DMGetCoordinateDim" 4029 /*@ 4030 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4031 4032 Not Collective 4033 4034 Input Parameter: 4035 . dm - The DM object 4036 4037 Output Parameter: 4038 . dim - The embedding dimension 4039 4040 Level: intermediate 4041 4042 .keywords: mesh, coordinates 4043 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4044 @*/ 4045 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4046 { 4047 PetscFunctionBegin; 4048 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4049 PetscValidPointer(dim, 2); 4050 if (dm->dimEmbed == PETSC_DEFAULT) { 4051 dm->dimEmbed = dm->dim; 4052 } 4053 *dim = dm->dimEmbed; 4054 PetscFunctionReturn(0); 4055 } 4056 4057 #undef __FUNCT__ 4058 #define __FUNCT__ "DMSetCoordinateDim" 4059 /*@ 4060 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4061 4062 Not Collective 4063 4064 Input Parameters: 4065 + dm - The DM object 4066 - dim - The embedding dimension 4067 4068 Level: intermediate 4069 4070 .keywords: mesh, coordinates 4071 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4072 @*/ 4073 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4074 { 4075 PetscFunctionBegin; 4076 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4077 dm->dimEmbed = dim; 4078 PetscFunctionReturn(0); 4079 } 4080 4081 #undef __FUNCT__ 4082 #define __FUNCT__ "DMGetCoordinateSection" 4083 /*@ 4084 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4085 4086 Not Collective 4087 4088 Input Parameter: 4089 . dm - The DM object 4090 4091 Output Parameter: 4092 . section - The PetscSection object 4093 4094 Level: intermediate 4095 4096 .keywords: mesh, coordinates 4097 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4098 @*/ 4099 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4100 { 4101 DM cdm; 4102 PetscErrorCode ierr; 4103 4104 PetscFunctionBegin; 4105 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4106 PetscValidPointer(section, 2); 4107 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4108 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4109 PetscFunctionReturn(0); 4110 } 4111 4112 #undef __FUNCT__ 4113 #define __FUNCT__ "DMSetCoordinateSection" 4114 /*@ 4115 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4116 4117 Not Collective 4118 4119 Input Parameters: 4120 + dm - The DM object 4121 . dim - The embedding dimension, or PETSC_DETERMINE 4122 - section - The PetscSection object 4123 4124 Level: intermediate 4125 4126 .keywords: mesh, coordinates 4127 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4128 @*/ 4129 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4130 { 4131 DM cdm; 4132 PetscErrorCode ierr; 4133 4134 PetscFunctionBegin; 4135 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4136 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4137 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4138 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4139 if (dim == PETSC_DETERMINE) { 4140 PetscInt d = dim; 4141 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4142 4143 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4144 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4145 pStart = PetscMax(vStart, pStart); 4146 pEnd = PetscMin(vEnd, pEnd); 4147 for (v = pStart; v < pEnd; ++v) { 4148 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4149 if (dd) {d = dd; break;} 4150 } 4151 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4152 } 4153 PetscFunctionReturn(0); 4154 } 4155 4156 #undef __FUNCT__ 4157 #define __FUNCT__ "DMGetPeriodicity" 4158 /*@C 4159 DMSetPeriodicity - Set the description of mesh periodicity 4160 4161 Input Parameters: 4162 + dm - The DM object 4163 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4164 . L - If we assume the mesh is a torus, this is the length of each coordinate 4165 - bd - This describes the type of periodicity in each topological dimension 4166 4167 Level: developer 4168 4169 .seealso: DMGetPeriodicity() 4170 @*/ 4171 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4172 { 4173 PetscFunctionBegin; 4174 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4175 if (L) *L = dm->L; 4176 if (maxCell) *maxCell = dm->maxCell; 4177 if (bd) *bd = dm->bdtype; 4178 PetscFunctionReturn(0); 4179 } 4180 4181 #undef __FUNCT__ 4182 #define __FUNCT__ "DMSetPeriodicity" 4183 /*@C 4184 DMSetPeriodicity - Set the description of mesh periodicity 4185 4186 Input Parameters: 4187 + dm - The DM object 4188 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4189 . L - If we assume the mesh is a torus, this is the length of each coordinate 4190 - bd - This describes the type of periodicity in each topological dimension 4191 4192 Level: developer 4193 4194 .seealso: DMGetPeriodicity() 4195 @*/ 4196 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4197 { 4198 PetscInt dim, d; 4199 PetscErrorCode ierr; 4200 4201 PetscFunctionBegin; 4202 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4203 PetscValidPointer(L,3);PetscValidPointer(maxCell,2);PetscValidPointer(bd,4); 4204 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4205 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4206 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4207 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4208 PetscFunctionReturn(0); 4209 } 4210 4211 #undef __FUNCT__ 4212 #define __FUNCT__ "DMLocatePoints" 4213 /*@ 4214 DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells 4215 4216 Not collective 4217 4218 Input Parameters: 4219 + dm - The DM 4220 - v - The Vec of points 4221 4222 Output Parameter: 4223 . cells - The local cell numbers for cells which contain the points 4224 4225 Level: developer 4226 4227 .keywords: point location, mesh 4228 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4229 @*/ 4230 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells) 4231 { 4232 PetscErrorCode ierr; 4233 4234 PetscFunctionBegin; 4235 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4236 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4237 PetscValidPointer(cells,3); 4238 if (dm->ops->locatepoints) { 4239 ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr); 4240 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4241 PetscFunctionReturn(0); 4242 } 4243 4244 #undef __FUNCT__ 4245 #define __FUNCT__ "DMGetOutputDM" 4246 /*@ 4247 DMGetOutputDM - Retrieve the DM associated with the layout for output 4248 4249 Input Parameter: 4250 . dm - The original DM 4251 4252 Output Parameter: 4253 . odm - The DM which provides the layout for output 4254 4255 Level: intermediate 4256 4257 .seealso: VecView(), DMGetDefaultGlobalSection() 4258 @*/ 4259 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4260 { 4261 PetscSection section; 4262 PetscBool hasConstraints; 4263 PetscErrorCode ierr; 4264 4265 PetscFunctionBegin; 4266 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4267 PetscValidPointer(odm,2); 4268 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4269 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4270 if (!hasConstraints) { 4271 *odm = dm; 4272 PetscFunctionReturn(0); 4273 } 4274 if (!dm->dmBC) { 4275 PetscSection newSection, gsection; 4276 PetscSF sf; 4277 4278 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4279 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4280 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4281 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4282 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4283 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, &gsection);CHKERRQ(ierr); 4284 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4285 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4286 } 4287 *odm = dm->dmBC; 4288 PetscFunctionReturn(0); 4289 } 4290 4291 #undef __FUNCT__ 4292 #define __FUNCT__ "DMGetOutputSequenceNumber" 4293 /*@ 4294 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 4295 4296 Input Parameter: 4297 . dm - The original DM 4298 4299 Output Parameters: 4300 + num - The output sequence number 4301 - val - The output sequence value 4302 4303 Level: intermediate 4304 4305 Note: This is intended for output that should appear in sequence, for instance 4306 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4307 4308 .seealso: VecView() 4309 @*/ 4310 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 4311 { 4312 PetscFunctionBegin; 4313 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4314 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 4315 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 4316 PetscFunctionReturn(0); 4317 } 4318 4319 #undef __FUNCT__ 4320 #define __FUNCT__ "DMSetOutputSequenceNumber" 4321 /*@ 4322 DMSetOutputSequenceNumber - Set the sequence number/value for output 4323 4324 Input Parameters: 4325 + dm - The original DM 4326 . num - The output sequence number 4327 - val - The output sequence value 4328 4329 Level: intermediate 4330 4331 Note: This is intended for output that should appear in sequence, for instance 4332 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4333 4334 .seealso: VecView() 4335 @*/ 4336 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 4337 { 4338 PetscFunctionBegin; 4339 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4340 dm->outputSequenceNum = num; 4341 dm->outputSequenceVal = val; 4342 PetscFunctionReturn(0); 4343 } 4344 4345 #undef __FUNCT__ 4346 #define __FUNCT__ "DMOutputSequenceLoad" 4347 /*@C 4348 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 4349 4350 Input Parameters: 4351 + dm - The original DM 4352 . name - The sequence name 4353 - num - The output sequence number 4354 4355 Output Parameter: 4356 . val - The output sequence value 4357 4358 Level: intermediate 4359 4360 Note: This is intended for output that should appear in sequence, for instance 4361 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4362 4363 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 4364 @*/ 4365 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 4366 { 4367 PetscBool ishdf5; 4368 PetscErrorCode ierr; 4369 4370 PetscFunctionBegin; 4371 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4372 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4373 PetscValidPointer(val,4); 4374 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4375 if (ishdf5) { 4376 #if defined(PETSC_HAVE_HDF5) 4377 PetscScalar value; 4378 4379 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 4380 *val = PetscRealPart(value); 4381 #endif 4382 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 4383 PetscFunctionReturn(0); 4384 } 4385