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