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