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