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