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