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