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__ "DMGetDefaultGlobalSection" 2955 /*@ 2956 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 2957 2958 Collective on DM 2959 2960 Input Parameter: 2961 . dm - The DM 2962 2963 Output Parameter: 2964 . section - The PetscSection 2965 2966 Level: intermediate 2967 2968 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 2969 2970 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 2971 @*/ 2972 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 2973 { 2974 PetscErrorCode ierr; 2975 2976 PetscFunctionBegin; 2977 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2978 PetscValidPointer(section, 2); 2979 if (!dm->defaultGlobalSection) { 2980 PetscSection s; 2981 2982 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 2983 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 2984 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 2985 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 2986 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 2987 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 2988 } 2989 *section = dm->defaultGlobalSection; 2990 PetscFunctionReturn(0); 2991 } 2992 2993 #undef __FUNCT__ 2994 #define __FUNCT__ "DMSetDefaultGlobalSection" 2995 /*@ 2996 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 2997 2998 Input Parameters: 2999 + dm - The DM 3000 - section - The PetscSection, or NULL 3001 3002 Level: intermediate 3003 3004 Note: Any existing Section will be destroyed 3005 3006 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3007 @*/ 3008 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3009 { 3010 PetscErrorCode ierr; 3011 3012 PetscFunctionBegin; 3013 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3014 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3015 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3016 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3017 dm->defaultGlobalSection = section; 3018 PetscFunctionReturn(0); 3019 } 3020 3021 #undef __FUNCT__ 3022 #define __FUNCT__ "DMGetDefaultSF" 3023 /*@ 3024 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3025 it is created from the default PetscSection layouts in the DM. 3026 3027 Input Parameter: 3028 . dm - The DM 3029 3030 Output Parameter: 3031 . sf - The PetscSF 3032 3033 Level: intermediate 3034 3035 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3036 3037 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3038 @*/ 3039 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3040 { 3041 PetscInt nroots; 3042 PetscErrorCode ierr; 3043 3044 PetscFunctionBegin; 3045 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3046 PetscValidPointer(sf, 2); 3047 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3048 if (nroots < 0) { 3049 PetscSection section, gSection; 3050 3051 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3052 if (section) { 3053 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3054 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3055 } else { 3056 *sf = NULL; 3057 PetscFunctionReturn(0); 3058 } 3059 } 3060 *sf = dm->defaultSF; 3061 PetscFunctionReturn(0); 3062 } 3063 3064 #undef __FUNCT__ 3065 #define __FUNCT__ "DMSetDefaultSF" 3066 /*@ 3067 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3068 3069 Input Parameters: 3070 + dm - The DM 3071 - sf - The PetscSF 3072 3073 Level: intermediate 3074 3075 Note: Any previous SF is destroyed 3076 3077 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3078 @*/ 3079 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3080 { 3081 PetscErrorCode ierr; 3082 3083 PetscFunctionBegin; 3084 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3085 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3086 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3087 dm->defaultSF = sf; 3088 PetscFunctionReturn(0); 3089 } 3090 3091 #undef __FUNCT__ 3092 #define __FUNCT__ "DMCreateDefaultSF" 3093 /*@C 3094 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3095 describing the data layout. 3096 3097 Input Parameters: 3098 + dm - The DM 3099 . localSection - PetscSection describing the local data layout 3100 - globalSection - PetscSection describing the global data layout 3101 3102 Level: intermediate 3103 3104 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3105 @*/ 3106 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3107 { 3108 MPI_Comm comm; 3109 PetscLayout layout; 3110 const PetscInt *ranges; 3111 PetscInt *local; 3112 PetscSFNode *remote; 3113 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3114 PetscMPIInt size, rank; 3115 PetscErrorCode ierr; 3116 3117 PetscFunctionBegin; 3118 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3119 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3120 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3121 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3122 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3123 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3124 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3125 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3126 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3127 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3128 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3129 for (p = pStart; p < pEnd; ++p) { 3130 PetscInt gdof, gcdof; 3131 3132 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3133 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3134 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)); 3135 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3136 } 3137 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3138 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3139 for (p = pStart, l = 0; p < pEnd; ++p) { 3140 const PetscInt *cind; 3141 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3142 3143 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3144 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3145 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3146 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3147 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3148 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3149 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3150 if (!gdof) continue; /* Censored point */ 3151 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3152 if (gsize != dof-cdof) { 3153 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); 3154 cdof = 0; /* Ignore constraints */ 3155 } 3156 for (d = 0, c = 0; d < dof; ++d) { 3157 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3158 local[l+d-c] = off+d; 3159 } 3160 if (gdof < 0) { 3161 for (d = 0; d < gsize; ++d, ++l) { 3162 PetscInt offset = -(goff+1) + d, r; 3163 3164 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3165 if (r < 0) r = -(r+2); 3166 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); 3167 remote[l].rank = r; 3168 remote[l].index = offset - ranges[r]; 3169 } 3170 } else { 3171 for (d = 0; d < gsize; ++d, ++l) { 3172 remote[l].rank = rank; 3173 remote[l].index = goff+d - ranges[rank]; 3174 } 3175 } 3176 } 3177 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3178 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3179 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3180 PetscFunctionReturn(0); 3181 } 3182 3183 #undef __FUNCT__ 3184 #define __FUNCT__ "DMGetPointSF" 3185 /*@ 3186 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3187 3188 Input Parameter: 3189 . dm - The DM 3190 3191 Output Parameter: 3192 . sf - The PetscSF 3193 3194 Level: intermediate 3195 3196 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3197 3198 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3199 @*/ 3200 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3201 { 3202 PetscFunctionBegin; 3203 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3204 PetscValidPointer(sf, 2); 3205 *sf = dm->sf; 3206 PetscFunctionReturn(0); 3207 } 3208 3209 #undef __FUNCT__ 3210 #define __FUNCT__ "DMSetPointSF" 3211 /*@ 3212 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3213 3214 Input Parameters: 3215 + dm - The DM 3216 - sf - The PetscSF 3217 3218 Level: intermediate 3219 3220 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3221 @*/ 3222 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3223 { 3224 PetscErrorCode ierr; 3225 3226 PetscFunctionBegin; 3227 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3228 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3229 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3230 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3231 dm->sf = sf; 3232 PetscFunctionReturn(0); 3233 } 3234 3235 #undef __FUNCT__ 3236 #define __FUNCT__ "DMGetDS" 3237 /*@ 3238 DMGetDS - Get the PetscDS 3239 3240 Input Parameter: 3241 . dm - The DM 3242 3243 Output Parameter: 3244 . prob - The PetscDS 3245 3246 Level: developer 3247 3248 .seealso: DMSetDS() 3249 @*/ 3250 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3251 { 3252 PetscFunctionBegin; 3253 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3254 PetscValidPointer(prob, 2); 3255 *prob = dm->prob; 3256 PetscFunctionReturn(0); 3257 } 3258 3259 #undef __FUNCT__ 3260 #define __FUNCT__ "DMSetDS" 3261 /*@ 3262 DMSetDS - Set the PetscDS 3263 3264 Input Parameters: 3265 + dm - The DM 3266 - prob - The PetscDS 3267 3268 Level: developer 3269 3270 .seealso: DMGetDS() 3271 @*/ 3272 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3273 { 3274 PetscErrorCode ierr; 3275 3276 PetscFunctionBegin; 3277 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3278 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3279 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3280 dm->prob = prob; 3281 ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr); 3282 PetscFunctionReturn(0); 3283 } 3284 3285 #undef __FUNCT__ 3286 #define __FUNCT__ "DMGetNumFields" 3287 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3288 { 3289 PetscErrorCode ierr; 3290 3291 PetscFunctionBegin; 3292 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3293 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3294 PetscFunctionReturn(0); 3295 } 3296 3297 #undef __FUNCT__ 3298 #define __FUNCT__ "DMSetNumFields" 3299 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3300 { 3301 PetscInt Nf, f; 3302 PetscErrorCode ierr; 3303 3304 PetscFunctionBegin; 3305 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3306 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3307 for (f = Nf; f < numFields; ++f) { 3308 PetscContainer obj; 3309 3310 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3311 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3312 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3313 } 3314 PetscFunctionReturn(0); 3315 } 3316 3317 #undef __FUNCT__ 3318 #define __FUNCT__ "DMGetField" 3319 /*@ 3320 DMGetField - Return the discretization object for a given DM field 3321 3322 Not collective 3323 3324 Input Parameters: 3325 + dm - The DM 3326 - f - The field number 3327 3328 Output Parameter: 3329 . field - The discretization object 3330 3331 Level: developer 3332 3333 .seealso: DMSetField() 3334 @*/ 3335 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3336 { 3337 PetscErrorCode ierr; 3338 3339 PetscFunctionBegin; 3340 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3341 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3342 PetscFunctionReturn(0); 3343 } 3344 3345 #undef __FUNCT__ 3346 #define __FUNCT__ "DMSetField" 3347 /*@ 3348 DMSetField - Set the discretization object for a given DM field 3349 3350 Logically collective on DM 3351 3352 Input Parameters: 3353 + dm - The DM 3354 . f - The field number 3355 - field - The discretization object 3356 3357 Level: developer 3358 3359 .seealso: DMGetField() 3360 @*/ 3361 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3362 { 3363 PetscErrorCode ierr; 3364 3365 PetscFunctionBegin; 3366 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3367 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3368 PetscFunctionReturn(0); 3369 } 3370 3371 #undef __FUNCT__ 3372 #define __FUNCT__ "DMRestrictHook_Coordinates" 3373 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3374 { 3375 DM dm_coord,dmc_coord; 3376 PetscErrorCode ierr; 3377 Vec coords,ccoords; 3378 VecScatter scat; 3379 PetscFunctionBegin; 3380 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3381 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3382 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3383 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3384 if (coords && !ccoords) { 3385 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3386 ierr = DMCreateInjection(dmc_coord,dm_coord,&scat);CHKERRQ(ierr); 3387 ierr = VecScatterBegin(scat,coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3388 ierr = VecScatterEnd(scat,coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3389 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3390 ierr = VecScatterDestroy(&scat);CHKERRQ(ierr); 3391 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3392 } 3393 PetscFunctionReturn(0); 3394 } 3395 3396 #undef __FUNCT__ 3397 #define __FUNCT__ "DMSubDomainHook_Coordinates" 3398 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 3399 { 3400 DM dm_coord,subdm_coord; 3401 PetscErrorCode ierr; 3402 Vec coords,ccoords,clcoords; 3403 VecScatter *scat_i,*scat_g; 3404 PetscFunctionBegin; 3405 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3406 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 3407 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3408 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 3409 if (coords && !ccoords) { 3410 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 3411 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 3412 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 3413 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3414 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3415 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3416 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3417 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 3418 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 3419 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 3420 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 3421 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3422 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 3423 ierr = PetscFree(scat_i);CHKERRQ(ierr); 3424 ierr = PetscFree(scat_g);CHKERRQ(ierr); 3425 } 3426 PetscFunctionReturn(0); 3427 } 3428 3429 #undef __FUNCT__ 3430 #define __FUNCT__ "DMGetDimension" 3431 /*@ 3432 DMGetDimension - Return the topological dimension of the DM 3433 3434 Not collective 3435 3436 Input Parameter: 3437 . dm - The DM 3438 3439 Output Parameter: 3440 . dim - The topological dimension 3441 3442 Level: beginner 3443 3444 .seealso: DMSetDimension(), DMCreate() 3445 @*/ 3446 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 3447 { 3448 PetscFunctionBegin; 3449 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3450 PetscValidPointer(dim, 2); 3451 *dim = dm->dim; 3452 PetscFunctionReturn(0); 3453 } 3454 3455 #undef __FUNCT__ 3456 #define __FUNCT__ "DMSetDimension" 3457 /*@ 3458 DMSetDimension - Set the topological dimension of the DM 3459 3460 Collective on dm 3461 3462 Input Parameters: 3463 + dm - The DM 3464 - dim - The topological dimension 3465 3466 Level: beginner 3467 3468 .seealso: DMGetDimension(), DMCreate() 3469 @*/ 3470 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 3471 { 3472 PetscFunctionBegin; 3473 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3474 PetscValidLogicalCollectiveInt(dm, dim, 2); 3475 dm->dim = dim; 3476 PetscFunctionReturn(0); 3477 } 3478 3479 #undef __FUNCT__ 3480 #define __FUNCT__ "DMGetDimPoints" 3481 /*@ 3482 DMGetDimPoints - Get the half-open interval for all points of a given dimension 3483 3484 Collective on DM 3485 3486 Input Parameters: 3487 + dm - the DM 3488 - dim - the dimension 3489 3490 Output Parameters: 3491 + pStart - The first point of the given dimension 3492 . pEnd - The first point following points of the given dimension 3493 3494 Note: 3495 The points are vertices in the Hasse diagram encoding the topology. This is explained in 3496 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 3497 then the interval is empty. 3498 3499 Level: intermediate 3500 3501 .keywords: point, Hasse Diagram, dimension 3502 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 3503 @*/ 3504 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 3505 { 3506 PetscInt d; 3507 PetscErrorCode ierr; 3508 3509 PetscFunctionBegin; 3510 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3511 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 3512 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 3513 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 3514 PetscFunctionReturn(0); 3515 } 3516 3517 #undef __FUNCT__ 3518 #define __FUNCT__ "DMSetCoordinates" 3519 /*@ 3520 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 3521 3522 Collective on DM 3523 3524 Input Parameters: 3525 + dm - the DM 3526 - c - coordinate vector 3527 3528 Note: 3529 The coordinates do include those for ghost points, which are in the local vector 3530 3531 Level: intermediate 3532 3533 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3534 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 3535 @*/ 3536 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 3537 { 3538 PetscErrorCode ierr; 3539 3540 PetscFunctionBegin; 3541 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3542 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3543 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3544 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3545 dm->coordinates = c; 3546 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3547 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3548 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3549 PetscFunctionReturn(0); 3550 } 3551 3552 #undef __FUNCT__ 3553 #define __FUNCT__ "DMSetCoordinatesLocal" 3554 /*@ 3555 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 3556 3557 Collective on DM 3558 3559 Input Parameters: 3560 + dm - the DM 3561 - c - coordinate vector 3562 3563 Note: 3564 The coordinates of ghost points can be set using DMSetCoordinates() 3565 followed by DMGetCoordinatesLocal(). This is intended to enable the 3566 setting of ghost coordinates outside of the domain. 3567 3568 Level: intermediate 3569 3570 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3571 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 3572 @*/ 3573 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 3574 { 3575 PetscErrorCode ierr; 3576 3577 PetscFunctionBegin; 3578 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3579 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3580 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3581 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3582 3583 dm->coordinatesLocal = c; 3584 3585 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3586 PetscFunctionReturn(0); 3587 } 3588 3589 #undef __FUNCT__ 3590 #define __FUNCT__ "DMGetCoordinates" 3591 /*@ 3592 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 3593 3594 Not Collective 3595 3596 Input Parameter: 3597 . dm - the DM 3598 3599 Output Parameter: 3600 . c - global coordinate vector 3601 3602 Note: 3603 This is a borrowed reference, so the user should NOT destroy this vector 3604 3605 Each process has only the local coordinates (does NOT have the ghost coordinates). 3606 3607 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3608 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3609 3610 Level: intermediate 3611 3612 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3613 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 3614 @*/ 3615 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 3616 { 3617 PetscErrorCode ierr; 3618 3619 PetscFunctionBegin; 3620 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3621 PetscValidPointer(c,2); 3622 if (!dm->coordinates && dm->coordinatesLocal) { 3623 DM cdm = NULL; 3624 3625 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3626 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 3627 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 3628 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3629 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 3630 } 3631 *c = dm->coordinates; 3632 PetscFunctionReturn(0); 3633 } 3634 3635 #undef __FUNCT__ 3636 #define __FUNCT__ "DMGetCoordinatesLocal" 3637 /*@ 3638 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 3639 3640 Collective on DM 3641 3642 Input Parameter: 3643 . dm - the DM 3644 3645 Output Parameter: 3646 . c - coordinate vector 3647 3648 Note: 3649 This is a borrowed reference, so the user should NOT destroy this vector 3650 3651 Each process has the local and ghost coordinates 3652 3653 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3654 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3655 3656 Level: intermediate 3657 3658 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3659 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 3660 @*/ 3661 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 3662 { 3663 PetscErrorCode ierr; 3664 3665 PetscFunctionBegin; 3666 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3667 PetscValidPointer(c,2); 3668 if (!dm->coordinatesLocal && dm->coordinates) { 3669 DM cdm = NULL; 3670 3671 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3672 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 3673 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 3674 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3675 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 3676 } 3677 *c = dm->coordinatesLocal; 3678 PetscFunctionReturn(0); 3679 } 3680 3681 #undef __FUNCT__ 3682 #define __FUNCT__ "DMGetCoordinateDM" 3683 /*@ 3684 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 3685 3686 Collective on DM 3687 3688 Input Parameter: 3689 . dm - the DM 3690 3691 Output Parameter: 3692 . cdm - coordinate DM 3693 3694 Level: intermediate 3695 3696 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3697 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3698 @*/ 3699 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 3700 { 3701 PetscErrorCode ierr; 3702 3703 PetscFunctionBegin; 3704 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3705 PetscValidPointer(cdm,2); 3706 if (!dm->coordinateDM) { 3707 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 3708 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 3709 } 3710 *cdm = dm->coordinateDM; 3711 PetscFunctionReturn(0); 3712 } 3713 3714 #undef __FUNCT__ 3715 #define __FUNCT__ "DMSetCoordinateDM" 3716 /*@ 3717 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 3718 3719 Logically Collective on DM 3720 3721 Input Parameters: 3722 + dm - the DM 3723 - cdm - coordinate DM 3724 3725 Level: intermediate 3726 3727 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3728 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3729 @*/ 3730 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 3731 { 3732 PetscErrorCode ierr; 3733 3734 PetscFunctionBegin; 3735 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3736 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 3737 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 3738 dm->coordinateDM = cdm; 3739 ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr); 3740 PetscFunctionReturn(0); 3741 } 3742 3743 #undef __FUNCT__ 3744 #define __FUNCT__ "DMGetCoordinateDim" 3745 /*@ 3746 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 3747 3748 Not Collective 3749 3750 Input Parameter: 3751 . dm - The DM object 3752 3753 Output Parameter: 3754 . dim - The embedding dimension 3755 3756 Level: intermediate 3757 3758 .keywords: mesh, coordinates 3759 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 3760 @*/ 3761 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 3762 { 3763 PetscFunctionBegin; 3764 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3765 PetscValidPointer(dim, 2); 3766 if (dm->dimEmbed == PETSC_DEFAULT) { 3767 dm->dimEmbed = dm->dim; 3768 } 3769 *dim = dm->dimEmbed; 3770 PetscFunctionReturn(0); 3771 } 3772 3773 #undef __FUNCT__ 3774 #define __FUNCT__ "DMSetCoordinateDim" 3775 /*@ 3776 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 3777 3778 Not Collective 3779 3780 Input Parameters: 3781 + dm - The DM object 3782 - dim - The embedding dimension 3783 3784 Level: intermediate 3785 3786 .keywords: mesh, coordinates 3787 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 3788 @*/ 3789 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 3790 { 3791 PetscFunctionBegin; 3792 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3793 dm->dimEmbed = dim; 3794 PetscFunctionReturn(0); 3795 } 3796 3797 #undef __FUNCT__ 3798 #define __FUNCT__ "DMGetCoordinateSection" 3799 /*@ 3800 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 3801 3802 Not Collective 3803 3804 Input Parameter: 3805 . dm - The DM object 3806 3807 Output Parameter: 3808 . section - The PetscSection object 3809 3810 Level: intermediate 3811 3812 .keywords: mesh, coordinates 3813 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 3814 @*/ 3815 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 3816 { 3817 DM cdm; 3818 PetscErrorCode ierr; 3819 3820 PetscFunctionBegin; 3821 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3822 PetscValidPointer(section, 2); 3823 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3824 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 3825 PetscFunctionReturn(0); 3826 } 3827 3828 #undef __FUNCT__ 3829 #define __FUNCT__ "DMSetCoordinateSection" 3830 /*@ 3831 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 3832 3833 Not Collective 3834 3835 Input Parameters: 3836 + dm - The DM object 3837 . dim - The embedding dimension, or PETSC_DETERMINE 3838 - section - The PetscSection object 3839 3840 Level: intermediate 3841 3842 .keywords: mesh, coordinates 3843 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 3844 @*/ 3845 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 3846 { 3847 DM cdm; 3848 PetscErrorCode ierr; 3849 3850 PetscFunctionBegin; 3851 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3852 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 3853 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3854 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 3855 if (dim == PETSC_DETERMINE) { 3856 PetscInt d = dim; 3857 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 3858 3859 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3860 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3861 pStart = PetscMax(vStart, pStart); 3862 pEnd = PetscMin(vEnd, pEnd); 3863 for (v = pStart; v < pEnd; ++v) { 3864 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 3865 if (dd) {d = dd; break;} 3866 } 3867 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 3868 } 3869 PetscFunctionReturn(0); 3870 } 3871 3872 #undef __FUNCT__ 3873 #define __FUNCT__ "DMGetPeriodicity" 3874 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L) 3875 { 3876 PetscFunctionBegin; 3877 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3878 if (L) *L = dm->L; 3879 if (maxCell) *maxCell = dm->maxCell; 3880 PetscFunctionReturn(0); 3881 } 3882 3883 #undef __FUNCT__ 3884 #define __FUNCT__ "DMSetPeriodicity" 3885 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[]) 3886 { 3887 Vec coordinates; 3888 PetscInt dim, d; 3889 PetscErrorCode ierr; 3890 3891 PetscFunctionBegin; 3892 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3893 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3894 ierr = VecGetBlockSize(coordinates, &dim);CHKERRQ(ierr); 3895 ierr = PetscMalloc1(dim,&dm->L);CHKERRQ(ierr); 3896 ierr = PetscMalloc1(dim,&dm->maxCell);CHKERRQ(ierr); 3897 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d];} 3898 PetscFunctionReturn(0); 3899 } 3900 3901 #undef __FUNCT__ 3902 #define __FUNCT__ "DMLocatePoints" 3903 /*@ 3904 DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells 3905 3906 Not collective 3907 3908 Input Parameters: 3909 + dm - The DM 3910 - v - The Vec of points 3911 3912 Output Parameter: 3913 . cells - The local cell numbers for cells which contain the points 3914 3915 Level: developer 3916 3917 .keywords: point location, mesh 3918 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 3919 @*/ 3920 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells) 3921 { 3922 PetscErrorCode ierr; 3923 3924 PetscFunctionBegin; 3925 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3926 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 3927 PetscValidPointer(cells,3); 3928 if (dm->ops->locatepoints) { 3929 ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr); 3930 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 3931 PetscFunctionReturn(0); 3932 } 3933 3934 #undef __FUNCT__ 3935 #define __FUNCT__ "DMGetOutputDM" 3936 /*@ 3937 DMGetOutputDM - Retrieve the DM associated with the layout for output 3938 3939 Input Parameter: 3940 . dm - The original DM 3941 3942 Output Parameter: 3943 . odm - The DM which provides the layout for output 3944 3945 Level: intermediate 3946 3947 .seealso: VecView(), DMGetDefaultGlobalSection() 3948 @*/ 3949 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 3950 { 3951 PetscSection section; 3952 PetscBool hasConstraints; 3953 PetscErrorCode ierr; 3954 3955 PetscFunctionBegin; 3956 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3957 PetscValidPointer(odm,2); 3958 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3959 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 3960 if (!hasConstraints) { 3961 *odm = dm; 3962 PetscFunctionReturn(0); 3963 } 3964 if (!dm->dmBC) { 3965 PetscSection newSection, gsection; 3966 PetscSF sf; 3967 3968 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 3969 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 3970 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 3971 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 3972 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 3973 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, &gsection);CHKERRQ(ierr); 3974 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 3975 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 3976 } 3977 *odm = dm->dmBC; 3978 PetscFunctionReturn(0); 3979 } 3980 3981 #undef __FUNCT__ 3982 #define __FUNCT__ "DMGetOutputSequenceNumber" 3983 /*@ 3984 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 3985 3986 Input Parameter: 3987 . dm - The original DM 3988 3989 Output Parameters: 3990 + num - The output sequence number 3991 - val - The output sequence value 3992 3993 Level: intermediate 3994 3995 Note: This is intended for output that should appear in sequence, for instance 3996 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 3997 3998 .seealso: VecView() 3999 @*/ 4000 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 4001 { 4002 PetscFunctionBegin; 4003 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4004 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 4005 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 4006 PetscFunctionReturn(0); 4007 } 4008 4009 #undef __FUNCT__ 4010 #define __FUNCT__ "DMSetOutputSequenceNumber" 4011 /*@ 4012 DMSetOutputSequenceNumber - Set the sequence number/value for output 4013 4014 Input Parameters: 4015 + dm - The original DM 4016 . num - The output sequence number 4017 - val - The output sequence value 4018 4019 Level: intermediate 4020 4021 Note: This is intended for output that should appear in sequence, for instance 4022 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4023 4024 .seealso: VecView() 4025 @*/ 4026 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 4027 { 4028 PetscFunctionBegin; 4029 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4030 dm->outputSequenceNum = num; 4031 dm->outputSequenceVal = val; 4032 PetscFunctionReturn(0); 4033 } 4034 4035 #undef __FUNCT__ 4036 #define __FUNCT__ "DMOutputSequenceLoad" 4037 /*@C 4038 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 4039 4040 Input Parameters: 4041 + dm - The original DM 4042 . name - The sequence name 4043 - num - The output sequence number 4044 4045 Output Parameter: 4046 . val - The output sequence value 4047 4048 Level: intermediate 4049 4050 Note: This is intended for output that should appear in sequence, for instance 4051 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4052 4053 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 4054 @*/ 4055 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 4056 { 4057 PetscBool ishdf5; 4058 PetscErrorCode ierr; 4059 4060 PetscFunctionBegin; 4061 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4062 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4063 PetscValidPointer(val,4); 4064 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4065 if (ishdf5) { 4066 #if defined(PETSC_HAVE_HDF5) 4067 PetscScalar value; 4068 4069 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 4070 *val = PetscRealPart(value); 4071 #endif 4072 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 4073 PetscFunctionReturn(0); 4074 } 4075