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