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