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