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