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