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