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