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