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