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 dm->coarseMesh = *dmc; 2213 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 2214 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 2215 (*dmc)->ctx = dm->ctx; 2216 (*dmc)->levelup = dm->levelup; 2217 (*dmc)->leveldown = dm->leveldown + 1; 2218 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 2219 for (link=dm->coarsenhook; link; link=link->next) { 2220 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 2221 } 2222 ierr = PetscLogEventEnd(DM_Coarsen,dm,0,0,0);CHKERRQ(ierr); 2223 PetscFunctionReturn(0); 2224 } 2225 2226 #undef __FUNCT__ 2227 #define __FUNCT__ "DMCoarsenHookAdd" 2228 /*@C 2229 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 2230 2231 Logically Collective 2232 2233 Input Arguments: 2234 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 2235 . coarsenhook - function to run when setting up a coarser level 2236 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 2237 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2238 2239 Calling sequence of coarsenhook: 2240 $ coarsenhook(DM fine,DM coarse,void *ctx); 2241 2242 + fine - fine level DM 2243 . coarse - coarse level DM to restrict problem to 2244 - ctx - optional user-defined function context 2245 2246 Calling sequence for restricthook: 2247 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 2248 2249 + fine - fine level DM 2250 . mrestrict - matrix restricting a fine-level solution to the coarse grid 2251 . rscale - scaling vector for restriction 2252 . inject - matrix restricting by injection 2253 . coarse - coarse level DM to update 2254 - ctx - optional user-defined function context 2255 2256 Level: advanced 2257 2258 Notes: 2259 This function is only needed if auxiliary data needs to be set up on coarse grids. 2260 2261 If this function is called multiple times, the hooks will be run in the order they are added. 2262 2263 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2264 extract the finest level information from its context (instead of from the SNES). 2265 2266 This function is currently not available from Fortran. 2267 2268 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2269 @*/ 2270 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 2271 { 2272 PetscErrorCode ierr; 2273 DMCoarsenHookLink link,*p; 2274 2275 PetscFunctionBegin; 2276 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 2277 for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2278 ierr = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr); 2279 link->coarsenhook = coarsenhook; 2280 link->restricthook = restricthook; 2281 link->ctx = ctx; 2282 link->next = NULL; 2283 *p = link; 2284 PetscFunctionReturn(0); 2285 } 2286 2287 #undef __FUNCT__ 2288 #define __FUNCT__ "DMRestrict" 2289 /*@ 2290 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 2291 2292 Collective if any hooks are 2293 2294 Input Arguments: 2295 + fine - finer DM to use as a base 2296 . restrct - restriction matrix, apply using MatRestrict() 2297 . inject - injection matrix, also use MatRestrict() 2298 - coarse - coarer DM to update 2299 2300 Level: developer 2301 2302 .seealso: DMCoarsenHookAdd(), MatRestrict() 2303 @*/ 2304 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 2305 { 2306 PetscErrorCode ierr; 2307 DMCoarsenHookLink link; 2308 2309 PetscFunctionBegin; 2310 for (link=fine->coarsenhook; link; link=link->next) { 2311 if (link->restricthook) { 2312 ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr); 2313 } 2314 } 2315 PetscFunctionReturn(0); 2316 } 2317 2318 #undef __FUNCT__ 2319 #define __FUNCT__ "DMSubDomainHookAdd" 2320 /*@C 2321 DMSubDomainHookAdd - adds a callback to be run when restricting a problem to the coarse grid 2322 2323 Logically Collective 2324 2325 Input Arguments: 2326 + global - global DM 2327 . ddhook - function to run to pass data to the decomposition DM upon its creation 2328 . restricthook - function to run to update data on block solve (at the beginning of the block solve) 2329 - ctx - [optional] user-defined context for provide data for the hooks (may be NULL) 2330 2331 2332 Calling sequence for ddhook: 2333 $ ddhook(DM global,DM block,void *ctx) 2334 2335 + global - global DM 2336 . block - block DM 2337 - ctx - optional user-defined function context 2338 2339 Calling sequence for restricthook: 2340 $ restricthook(DM global,VecScatter out,VecScatter in,DM block,void *ctx) 2341 2342 + global - global DM 2343 . out - scatter to the outer (with ghost and overlap points) block vector 2344 . in - scatter to block vector values only owned locally 2345 . block - block DM 2346 - ctx - optional user-defined function context 2347 2348 Level: advanced 2349 2350 Notes: 2351 This function is only needed if auxiliary data needs to be set up on subdomain DMs. 2352 2353 If this function is called multiple times, the hooks will be run in the order they are added. 2354 2355 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 2356 extract the global information from its context (instead of from the SNES). 2357 2358 This function is currently not available from Fortran. 2359 2360 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 2361 @*/ 2362 PetscErrorCode DMSubDomainHookAdd(DM global,PetscErrorCode (*ddhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,VecScatter,VecScatter,DM,void*),void *ctx) 2363 { 2364 PetscErrorCode ierr; 2365 DMSubDomainHookLink link,*p; 2366 2367 PetscFunctionBegin; 2368 PetscValidHeaderSpecific(global,DM_CLASSID,1); 2369 for (p=&global->subdomainhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 2370 ierr = PetscMalloc(sizeof(struct _DMSubDomainHookLink),&link);CHKERRQ(ierr); 2371 link->restricthook = restricthook; 2372 link->ddhook = ddhook; 2373 link->ctx = ctx; 2374 link->next = NULL; 2375 *p = link; 2376 PetscFunctionReturn(0); 2377 } 2378 2379 #undef __FUNCT__ 2380 #define __FUNCT__ "DMSubDomainRestrict" 2381 /*@ 2382 DMSubDomainRestrict - restricts user-defined problem data to a block DM by running hooks registered by DMSubDomainHookAdd() 2383 2384 Collective if any hooks are 2385 2386 Input Arguments: 2387 + fine - finer DM to use as a base 2388 . oscatter - scatter from domain global vector filling subdomain global vector with overlap 2389 . gscatter - scatter from domain global vector filling subdomain local vector with ghosts 2390 - coarse - coarer DM to update 2391 2392 Level: developer 2393 2394 .seealso: DMCoarsenHookAdd(), MatRestrict() 2395 @*/ 2396 PetscErrorCode DMSubDomainRestrict(DM global,VecScatter oscatter,VecScatter gscatter,DM subdm) 2397 { 2398 PetscErrorCode ierr; 2399 DMSubDomainHookLink link; 2400 2401 PetscFunctionBegin; 2402 for (link=global->subdomainhook; link; link=link->next) { 2403 if (link->restricthook) { 2404 ierr = (*link->restricthook)(global,oscatter,gscatter,subdm,link->ctx);CHKERRQ(ierr); 2405 } 2406 } 2407 PetscFunctionReturn(0); 2408 } 2409 2410 #undef __FUNCT__ 2411 #define __FUNCT__ "DMGetCoarsenLevel" 2412 /*@ 2413 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 2414 2415 Not Collective 2416 2417 Input Parameter: 2418 . dm - the DM object 2419 2420 Output Parameter: 2421 . level - number of coarsenings 2422 2423 Level: developer 2424 2425 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2426 2427 @*/ 2428 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 2429 { 2430 PetscFunctionBegin; 2431 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2432 *level = dm->leveldown; 2433 PetscFunctionReturn(0); 2434 } 2435 2436 2437 2438 #undef __FUNCT__ 2439 #define __FUNCT__ "DMRefineHierarchy" 2440 /*@C 2441 DMRefineHierarchy - Refines a DM object, all levels at once 2442 2443 Collective on DM 2444 2445 Input Parameter: 2446 + dm - the DM object 2447 - nlevels - the number of levels of refinement 2448 2449 Output Parameter: 2450 . dmf - the refined DM hierarchy 2451 2452 Level: developer 2453 2454 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2455 2456 @*/ 2457 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 2458 { 2459 PetscErrorCode ierr; 2460 2461 PetscFunctionBegin; 2462 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2463 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2464 if (nlevels == 0) PetscFunctionReturn(0); 2465 if (dm->ops->refinehierarchy) { 2466 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 2467 } else if (dm->ops->refine) { 2468 PetscInt i; 2469 2470 ierr = DMRefine(dm,PetscObjectComm((PetscObject)dm),&dmf[0]);CHKERRQ(ierr); 2471 for (i=1; i<nlevels; i++) { 2472 ierr = DMRefine(dmf[i-1],PetscObjectComm((PetscObject)dm),&dmf[i]);CHKERRQ(ierr); 2473 } 2474 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 2475 PetscFunctionReturn(0); 2476 } 2477 2478 #undef __FUNCT__ 2479 #define __FUNCT__ "DMCoarsenHierarchy" 2480 /*@C 2481 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 2482 2483 Collective on DM 2484 2485 Input Parameter: 2486 + dm - the DM object 2487 - nlevels - the number of levels of coarsening 2488 2489 Output Parameter: 2490 . dmc - the coarsened DM hierarchy 2491 2492 Level: developer 2493 2494 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 2495 2496 @*/ 2497 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 2498 { 2499 PetscErrorCode ierr; 2500 2501 PetscFunctionBegin; 2502 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2503 if (nlevels < 0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 2504 if (nlevels == 0) PetscFunctionReturn(0); 2505 PetscValidPointer(dmc,3); 2506 if (dm->ops->coarsenhierarchy) { 2507 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 2508 } else if (dm->ops->coarsen) { 2509 PetscInt i; 2510 2511 ierr = DMCoarsen(dm,PetscObjectComm((PetscObject)dm),&dmc[0]);CHKERRQ(ierr); 2512 for (i=1; i<nlevels; i++) { 2513 ierr = DMCoarsen(dmc[i-1],PetscObjectComm((PetscObject)dm),&dmc[i]);CHKERRQ(ierr); 2514 } 2515 } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 2516 PetscFunctionReturn(0); 2517 } 2518 2519 #undef __FUNCT__ 2520 #define __FUNCT__ "DMCreateAggregates" 2521 /*@ 2522 DMCreateAggregates - Gets the aggregates that map between 2523 grids associated with two DMs. 2524 2525 Collective on DM 2526 2527 Input Parameters: 2528 + dmc - the coarse grid DM 2529 - dmf - the fine grid DM 2530 2531 Output Parameters: 2532 . rest - the restriction matrix (transpose of the projection matrix) 2533 2534 Level: intermediate 2535 2536 .keywords: interpolation, restriction, multigrid 2537 2538 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 2539 @*/ 2540 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 2541 { 2542 PetscErrorCode ierr; 2543 2544 PetscFunctionBegin; 2545 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 2546 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 2547 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 2548 PetscFunctionReturn(0); 2549 } 2550 2551 #undef __FUNCT__ 2552 #define __FUNCT__ "DMSetApplicationContextDestroy" 2553 /*@C 2554 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 2555 2556 Not Collective 2557 2558 Input Parameters: 2559 + dm - the DM object 2560 - destroy - the destroy function 2561 2562 Level: intermediate 2563 2564 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2565 2566 @*/ 2567 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 2568 { 2569 PetscFunctionBegin; 2570 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2571 dm->ctxdestroy = destroy; 2572 PetscFunctionReturn(0); 2573 } 2574 2575 #undef __FUNCT__ 2576 #define __FUNCT__ "DMSetApplicationContext" 2577 /*@ 2578 DMSetApplicationContext - Set a user context into a DM object 2579 2580 Not Collective 2581 2582 Input Parameters: 2583 + dm - the DM object 2584 - ctx - the user context 2585 2586 Level: intermediate 2587 2588 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2589 2590 @*/ 2591 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 2592 { 2593 PetscFunctionBegin; 2594 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2595 dm->ctx = ctx; 2596 PetscFunctionReturn(0); 2597 } 2598 2599 #undef __FUNCT__ 2600 #define __FUNCT__ "DMGetApplicationContext" 2601 /*@ 2602 DMGetApplicationContext - Gets a user context from a DM object 2603 2604 Not Collective 2605 2606 Input Parameter: 2607 . dm - the DM object 2608 2609 Output Parameter: 2610 . ctx - the user context 2611 2612 Level: intermediate 2613 2614 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2615 2616 @*/ 2617 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 2618 { 2619 PetscFunctionBegin; 2620 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2621 *(void**)ctx = dm->ctx; 2622 PetscFunctionReturn(0); 2623 } 2624 2625 #undef __FUNCT__ 2626 #define __FUNCT__ "DMSetVariableBounds" 2627 /*@C 2628 DMSetVariableBounds - sets a function to compute the lower and upper bound vectors for SNESVI. 2629 2630 Logically Collective on DM 2631 2632 Input Parameter: 2633 + dm - the DM object 2634 - f - the function that computes variable bounds used by SNESVI (use NULL to cancel a previous function that was set) 2635 2636 Level: intermediate 2637 2638 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), 2639 DMSetJacobian() 2640 2641 @*/ 2642 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 2643 { 2644 PetscFunctionBegin; 2645 dm->ops->computevariablebounds = f; 2646 PetscFunctionReturn(0); 2647 } 2648 2649 #undef __FUNCT__ 2650 #define __FUNCT__ "DMHasVariableBounds" 2651 /*@ 2652 DMHasVariableBounds - does the DM object have a variable bounds function? 2653 2654 Not Collective 2655 2656 Input Parameter: 2657 . dm - the DM object to destroy 2658 2659 Output Parameter: 2660 . flg - PETSC_TRUE if the variable bounds function exists 2661 2662 Level: developer 2663 2664 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2665 2666 @*/ 2667 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 2668 { 2669 PetscFunctionBegin; 2670 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 2671 PetscFunctionReturn(0); 2672 } 2673 2674 #undef __FUNCT__ 2675 #define __FUNCT__ "DMComputeVariableBounds" 2676 /*@C 2677 DMComputeVariableBounds - compute variable bounds used by SNESVI. 2678 2679 Logically Collective on DM 2680 2681 Input Parameters: 2682 . dm - the DM object 2683 2684 Output parameters: 2685 + xl - lower bound 2686 - xu - upper bound 2687 2688 Level: advanced 2689 2690 Notes: This is generally not called by users. It calls the function provided by the user with DMSetVariableBounds() 2691 2692 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2693 2694 @*/ 2695 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 2696 { 2697 PetscErrorCode ierr; 2698 2699 PetscFunctionBegin; 2700 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 2701 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 2702 if (dm->ops->computevariablebounds) { 2703 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu);CHKERRQ(ierr); 2704 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 2705 PetscFunctionReturn(0); 2706 } 2707 2708 #undef __FUNCT__ 2709 #define __FUNCT__ "DMHasColoring" 2710 /*@ 2711 DMHasColoring - does the DM object have a method of providing a coloring? 2712 2713 Not Collective 2714 2715 Input Parameter: 2716 . dm - the DM object 2717 2718 Output Parameter: 2719 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 2720 2721 Level: developer 2722 2723 .seealso DMHasFunction(), DMCreateColoring() 2724 2725 @*/ 2726 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 2727 { 2728 PetscFunctionBegin; 2729 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 2730 PetscFunctionReturn(0); 2731 } 2732 2733 #undef __FUNCT__ 2734 #define __FUNCT__ "DMSetVec" 2735 /*@C 2736 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 2737 2738 Collective on DM 2739 2740 Input Parameter: 2741 + dm - the DM object 2742 - x - location to compute residual and Jacobian, if NULL is passed to those routines; will be NULL for linear problems. 2743 2744 Level: developer 2745 2746 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 2747 2748 @*/ 2749 PetscErrorCode DMSetVec(DM dm,Vec x) 2750 { 2751 PetscErrorCode ierr; 2752 2753 PetscFunctionBegin; 2754 if (x) { 2755 if (!dm->x) { 2756 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 2757 } 2758 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 2759 } else if (dm->x) { 2760 ierr = VecDestroy(&dm->x);CHKERRQ(ierr); 2761 } 2762 PetscFunctionReturn(0); 2763 } 2764 2765 PetscFunctionList DMList = NULL; 2766 PetscBool DMRegisterAllCalled = PETSC_FALSE; 2767 2768 #undef __FUNCT__ 2769 #define __FUNCT__ "DMSetType" 2770 /*@C 2771 DMSetType - Builds a DM, for a particular DM implementation. 2772 2773 Collective on DM 2774 2775 Input Parameters: 2776 + dm - The DM object 2777 - method - The name of the DM type 2778 2779 Options Database Key: 2780 . -dm_type <type> - Sets the DM type; use -help for a list of available types 2781 2782 Notes: 2783 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 2784 2785 Level: intermediate 2786 2787 .keywords: DM, set, type 2788 .seealso: DMGetType(), DMCreate() 2789 @*/ 2790 PetscErrorCode DMSetType(DM dm, DMType method) 2791 { 2792 PetscErrorCode (*r)(DM); 2793 PetscBool match; 2794 PetscErrorCode ierr; 2795 2796 PetscFunctionBegin; 2797 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2798 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 2799 if (match) PetscFunctionReturn(0); 2800 2801 ierr = DMRegisterAll();CHKERRQ(ierr); 2802 ierr = PetscFunctionListFind(DMList,method,&r);CHKERRQ(ierr); 2803 if (!r) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 2804 2805 if (dm->ops->destroy) { 2806 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 2807 dm->ops->destroy = NULL; 2808 } 2809 ierr = (*r)(dm);CHKERRQ(ierr); 2810 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 2811 PetscFunctionReturn(0); 2812 } 2813 2814 #undef __FUNCT__ 2815 #define __FUNCT__ "DMGetType" 2816 /*@C 2817 DMGetType - Gets the DM type name (as a string) from the DM. 2818 2819 Not Collective 2820 2821 Input Parameter: 2822 . dm - The DM 2823 2824 Output Parameter: 2825 . type - The DM type name 2826 2827 Level: intermediate 2828 2829 .keywords: DM, get, type, name 2830 .seealso: DMSetType(), DMCreate() 2831 @*/ 2832 PetscErrorCode DMGetType(DM dm, DMType *type) 2833 { 2834 PetscErrorCode ierr; 2835 2836 PetscFunctionBegin; 2837 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2838 PetscValidPointer(type,2); 2839 ierr = DMRegisterAll();CHKERRQ(ierr); 2840 *type = ((PetscObject)dm)->type_name; 2841 PetscFunctionReturn(0); 2842 } 2843 2844 #undef __FUNCT__ 2845 #define __FUNCT__ "DMConvert" 2846 /*@C 2847 DMConvert - Converts a DM to another DM, either of the same or different type. 2848 2849 Collective on DM 2850 2851 Input Parameters: 2852 + dm - the DM 2853 - newtype - new DM type (use "same" for the same type) 2854 2855 Output Parameter: 2856 . M - pointer to new DM 2857 2858 Notes: 2859 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 2860 the MPI communicator of the generated DM is always the same as the communicator 2861 of the input DM. 2862 2863 Level: intermediate 2864 2865 .seealso: DMCreate() 2866 @*/ 2867 PetscErrorCode DMConvert(DM dm, DMType newtype, DM *M) 2868 { 2869 DM B; 2870 char convname[256]; 2871 PetscBool sametype, issame; 2872 PetscErrorCode ierr; 2873 2874 PetscFunctionBegin; 2875 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2876 PetscValidType(dm,1); 2877 PetscValidPointer(M,3); 2878 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 2879 ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); 2880 { 2881 PetscErrorCode (*conv)(DM, DMType, DM*) = NULL; 2882 2883 /* 2884 Order of precedence: 2885 1) See if a specialized converter is known to the current DM. 2886 2) See if a specialized converter is known to the desired DM class. 2887 3) See if a good general converter is registered for the desired class 2888 4) See if a good general converter is known for the current matrix. 2889 5) Use a really basic converter. 2890 */ 2891 2892 /* 1) See if a specialized converter is known to the current DM and the desired class */ 2893 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2894 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2895 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2896 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2897 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2898 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,&conv);CHKERRQ(ierr); 2899 if (conv) goto foundconv; 2900 2901 /* 2) See if a specialized converter is known to the desired DM class. */ 2902 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &B);CHKERRQ(ierr); 2903 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 2904 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2905 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2906 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2907 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2908 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2909 ierr = PetscObjectQueryFunction((PetscObject)B,convname,&conv);CHKERRQ(ierr); 2910 if (conv) { 2911 ierr = DMDestroy(&B);CHKERRQ(ierr); 2912 goto foundconv; 2913 } 2914 2915 #if 0 2916 /* 3) See if a good general converter is registered for the desired class */ 2917 conv = B->ops->convertfrom; 2918 ierr = DMDestroy(&B);CHKERRQ(ierr); 2919 if (conv) goto foundconv; 2920 2921 /* 4) See if a good general converter is known for the current matrix */ 2922 if (dm->ops->convert) { 2923 conv = dm->ops->convert; 2924 } 2925 if (conv) goto foundconv; 2926 #endif 2927 2928 /* 5) Use a really basic converter. */ 2929 SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 2930 2931 foundconv: 2932 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2933 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 2934 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2935 } 2936 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 2937 PetscFunctionReturn(0); 2938 } 2939 2940 /*--------------------------------------------------------------------------------------------------------------------*/ 2941 2942 #undef __FUNCT__ 2943 #define __FUNCT__ "DMRegister" 2944 /*@C 2945 DMRegister - Adds a new DM component implementation 2946 2947 Not Collective 2948 2949 Input Parameters: 2950 + name - The name of a new user-defined creation routine 2951 - create_func - The creation routine itself 2952 2953 Notes: 2954 DMRegister() may be called multiple times to add several user-defined DMs 2955 2956 2957 Sample usage: 2958 .vb 2959 DMRegister("my_da", MyDMCreate); 2960 .ve 2961 2962 Then, your DM type can be chosen with the procedural interface via 2963 .vb 2964 DMCreate(MPI_Comm, DM *); 2965 DMSetType(DM,"my_da"); 2966 .ve 2967 or at runtime via the option 2968 .vb 2969 -da_type my_da 2970 .ve 2971 2972 Level: advanced 2973 2974 .keywords: DM, register 2975 .seealso: DMRegisterAll(), DMRegisterDestroy() 2976 2977 @*/ 2978 PetscErrorCode DMRegister(const char sname[],PetscErrorCode (*function)(DM)) 2979 { 2980 PetscErrorCode ierr; 2981 2982 PetscFunctionBegin; 2983 ierr = PetscFunctionListAdd(&DMList,sname,function);CHKERRQ(ierr); 2984 PetscFunctionReturn(0); 2985 } 2986 2987 #undef __FUNCT__ 2988 #define __FUNCT__ "DMLoad" 2989 /*@C 2990 DMLoad - Loads a DM that has been stored in binary with DMView(). 2991 2992 Collective on PetscViewer 2993 2994 Input Parameters: 2995 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 2996 some related function before a call to DMLoad(). 2997 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 2998 HDF5 file viewer, obtained from PetscViewerHDF5Open() 2999 3000 Level: intermediate 3001 3002 Notes: 3003 The type is determined by the data in the file, any type set into the DM before this call is ignored. 3004 3005 Notes for advanced users: 3006 Most users should not need to know the details of the binary storage 3007 format, since DMLoad() and DMView() completely hide these details. 3008 But for anyone who's interested, the standard binary matrix storage 3009 format is 3010 .vb 3011 has not yet been determined 3012 .ve 3013 3014 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 3015 @*/ 3016 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 3017 { 3018 PetscBool isbinary, ishdf5; 3019 PetscErrorCode ierr; 3020 3021 PetscFunctionBegin; 3022 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 3023 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 3024 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 3025 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr); 3026 if (isbinary) { 3027 PetscInt classid; 3028 char type[256]; 3029 3030 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 3031 if (classid != DM_FILE_CLASSID) SETERRQ1(PetscObjectComm((PetscObject)newdm),PETSC_ERR_ARG_WRONG,"Not DM next in file, classid found %d",(int)classid); 3032 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 3033 ierr = DMSetType(newdm, type);CHKERRQ(ierr); 3034 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3035 } else if (ishdf5) { 3036 if (newdm->ops->load) {ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr);} 3037 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen() or PetscViewerHDF5Open()"); 3038 PetscFunctionReturn(0); 3039 } 3040 3041 /******************************** FEM Support **********************************/ 3042 3043 #undef __FUNCT__ 3044 #define __FUNCT__ "DMPrintCellVector" 3045 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) 3046 { 3047 PetscInt f; 3048 PetscErrorCode ierr; 3049 3050 PetscFunctionBegin; 3051 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3052 for (f = 0; f < len; ++f) { 3053 ierr = PetscPrintf(PETSC_COMM_SELF, " | %g |\n", (double)PetscRealPart(x[f]));CHKERRQ(ierr); 3054 } 3055 PetscFunctionReturn(0); 3056 } 3057 3058 #undef __FUNCT__ 3059 #define __FUNCT__ "DMPrintCellMatrix" 3060 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) 3061 { 3062 PetscInt f, g; 3063 PetscErrorCode ierr; 3064 3065 PetscFunctionBegin; 3066 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 3067 for (f = 0; f < rows; ++f) { 3068 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 3069 for (g = 0; g < cols; ++g) { 3070 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5g", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 3071 } 3072 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3073 } 3074 PetscFunctionReturn(0); 3075 } 3076 3077 #undef __FUNCT__ 3078 #define __FUNCT__ "DMPrintLocalVec" 3079 PetscErrorCode DMPrintLocalVec(DM dm, const char name[], PetscReal tol, Vec X) 3080 { 3081 PetscMPIInt rank, numProcs; 3082 PetscInt p; 3083 PetscErrorCode ierr; 3084 3085 PetscFunctionBegin; 3086 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 3087 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);CHKERRQ(ierr); 3088 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "%s:\n", name);CHKERRQ(ierr); 3089 for (p = 0; p < numProcs; ++p) { 3090 if (p == rank) { 3091 Vec x; 3092 3093 ierr = VecDuplicate(X, &x);CHKERRQ(ierr); 3094 ierr = VecCopy(X, x);CHKERRQ(ierr); 3095 ierr = VecChop(x, tol);CHKERRQ(ierr); 3096 ierr = VecView(x, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3097 ierr = VecDestroy(&x);CHKERRQ(ierr); 3098 ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 3099 } 3100 ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 3101 } 3102 PetscFunctionReturn(0); 3103 } 3104 3105 #undef __FUNCT__ 3106 #define __FUNCT__ "DMGetDefaultSection" 3107 /*@ 3108 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 3109 3110 Input Parameter: 3111 . dm - The DM 3112 3113 Output Parameter: 3114 . section - The PetscSection 3115 3116 Level: intermediate 3117 3118 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3119 3120 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3121 @*/ 3122 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) 3123 { 3124 PetscErrorCode ierr; 3125 3126 PetscFunctionBegin; 3127 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3128 PetscValidPointer(section, 2); 3129 if (!dm->defaultSection && dm->ops->createdefaultsection) { 3130 ierr = (*dm->ops->createdefaultsection)(dm);CHKERRQ(ierr); 3131 ierr = PetscObjectViewFromOptions((PetscObject) dm->defaultSection, NULL, "-dm_petscsection_view");CHKERRQ(ierr); 3132 } 3133 *section = dm->defaultSection; 3134 PetscFunctionReturn(0); 3135 } 3136 3137 #undef __FUNCT__ 3138 #define __FUNCT__ "DMSetDefaultSection" 3139 /*@ 3140 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3141 3142 Input Parameters: 3143 + dm - The DM 3144 - section - The PetscSection 3145 3146 Level: intermediate 3147 3148 Note: Any existing Section will be destroyed 3149 3150 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3151 @*/ 3152 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) 3153 { 3154 PetscInt numFields = 0; 3155 PetscInt f; 3156 PetscErrorCode ierr; 3157 3158 PetscFunctionBegin; 3159 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3160 if (section) { 3161 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3162 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3163 } 3164 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3165 dm->defaultSection = section; 3166 if (section) {ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr);} 3167 if (numFields) { 3168 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3169 for (f = 0; f < numFields; ++f) { 3170 PetscObject disc; 3171 const char *name; 3172 3173 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3174 ierr = DMGetField(dm, f, &disc);CHKERRQ(ierr); 3175 ierr = PetscObjectSetName(disc, name);CHKERRQ(ierr); 3176 } 3177 } 3178 /* The global section will be rebuilt in the next call to DMGetDefaultGlobalSection(). */ 3179 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3180 PetscFunctionReturn(0); 3181 } 3182 3183 #undef __FUNCT__ 3184 #define __FUNCT__ "DMGetDefaultConstraints" 3185 /*@ 3186 DMGetDefaultConstraints - Get the PetscSection and Mat the specify the local constraint interpolation. See DMSetDefaultConstraints() for a description of the purpose of constraint interpolation. 3187 3188 not collective 3189 3190 Input Parameter: 3191 . dm - The DM 3192 3193 Output Parameter: 3194 + 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. 3195 - 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. 3196 3197 Level: advanced 3198 3199 Note: This gets borrowed references, so the user should not destroy the PetscSection or the Mat. 3200 3201 .seealso: DMSetDefaultConstraints() 3202 @*/ 3203 PetscErrorCode DMGetDefaultConstraints(DM dm, PetscSection *section, Mat *mat) 3204 { 3205 PetscErrorCode ierr; 3206 3207 PetscFunctionBegin; 3208 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3209 if (!dm->defaultConstraintSection && !dm->defaultConstraintMat && dm->ops->createdefaultconstraints) {ierr = (*dm->ops->createdefaultconstraints)(dm);CHKERRQ(ierr);} 3210 if (section) {*section = dm->defaultConstraintSection;} 3211 if (mat) {*mat = dm->defaultConstraintMat;} 3212 PetscFunctionReturn(0); 3213 } 3214 3215 #undef __FUNCT__ 3216 #define __FUNCT__ "DMSetDefaultConstraints" 3217 /*@ 3218 DMSetDefaultConstraints - Set the PetscSection and Mat the specify the local constraint interpolation. 3219 3220 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(). 3221 3222 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. 3223 3224 collective on dm 3225 3226 Input Parameters: 3227 + dm - The DM 3228 + 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). 3229 - 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). 3230 3231 Level: advanced 3232 3233 Note: This increments the references of the PetscSection and the Mat, so they user can destroy them 3234 3235 .seealso: DMGetDefaultConstraints() 3236 @*/ 3237 PetscErrorCode DMSetDefaultConstraints(DM dm, PetscSection section, Mat mat) 3238 { 3239 PetscMPIInt result; 3240 PetscErrorCode ierr; 3241 3242 PetscFunctionBegin; 3243 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3244 if (section) { 3245 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3246 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)section),&result);CHKERRQ(ierr); 3247 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint section must have local communicator"); 3248 } 3249 if (mat) { 3250 PetscValidHeaderSpecific(mat,MAT_CLASSID,3); 3251 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)mat),&result);CHKERRQ(ierr); 3252 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"constraint matrix must have local communicator"); 3253 } 3254 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3255 ierr = PetscSectionDestroy(&dm->defaultConstraintSection);CHKERRQ(ierr); 3256 dm->defaultConstraintSection = section; 3257 ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr); 3258 ierr = MatDestroy(&dm->defaultConstraintMat);CHKERRQ(ierr); 3259 dm->defaultConstraintMat = mat; 3260 PetscFunctionReturn(0); 3261 } 3262 3263 #ifdef PETSC_USE_DEBUG 3264 #undef __FUNCT__ 3265 #define __FUNCT__ "DMDefaultSectionCheckConsistency_Internal" 3266 /* 3267 DMDefaultSectionCheckConsistency - Check the consistentcy of the global and local sections. 3268 3269 Input Parameters: 3270 + dm - The DM 3271 . localSection - PetscSection describing the local data layout 3272 - globalSection - PetscSection describing the global data layout 3273 3274 Level: intermediate 3275 3276 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3277 */ 3278 static PetscErrorCode DMDefaultSectionCheckConsistency_Internal(DM dm, PetscSection localSection, PetscSection globalSection) 3279 { 3280 MPI_Comm comm; 3281 PetscLayout layout; 3282 const PetscInt *ranges; 3283 PetscInt pStart, pEnd, p, nroots; 3284 PetscMPIInt size, rank; 3285 PetscBool valid = PETSC_TRUE, gvalid; 3286 PetscErrorCode ierr; 3287 3288 PetscFunctionBegin; 3289 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3290 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3291 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3292 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3293 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3294 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3295 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3296 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3297 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3298 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3299 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3300 for (p = pStart; p < pEnd; ++p) { 3301 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d; 3302 3303 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3304 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3305 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3306 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3307 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3308 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3309 if (!gdof) continue; /* Censored point */ 3310 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;} 3311 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;} 3312 if (gdof < 0) { 3313 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3314 for (d = 0; d < gsize; ++d) { 3315 PetscInt offset = -(goff+1) + d, r; 3316 3317 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3318 if (r < 0) r = -(r+2); 3319 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;} 3320 } 3321 } 3322 } 3323 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3324 ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr); 3325 ierr = MPIU_Allreduce(&valid, &gvalid, 1, MPIU_BOOL, MPI_LAND, comm);CHKERRQ(ierr); 3326 if (!gvalid) { 3327 ierr = DMView(dm, NULL);CHKERRQ(ierr); 3328 SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Inconsistent local and global sections"); 3329 } 3330 PetscFunctionReturn(0); 3331 } 3332 #endif 3333 3334 #undef __FUNCT__ 3335 #define __FUNCT__ "DMGetDefaultGlobalSection" 3336 /*@ 3337 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3338 3339 Collective on DM 3340 3341 Input Parameter: 3342 . dm - The DM 3343 3344 Output Parameter: 3345 . section - The PetscSection 3346 3347 Level: intermediate 3348 3349 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3350 3351 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3352 @*/ 3353 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) 3354 { 3355 PetscErrorCode ierr; 3356 3357 PetscFunctionBegin; 3358 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3359 PetscValidPointer(section, 2); 3360 if (!dm->defaultGlobalSection) { 3361 PetscSection s; 3362 3363 ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 3364 if (!s) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSection in order to create a global PetscSection"); 3365 if (!dm->sf) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "DM must have a default PetscSF in order to create a global PetscSection"); 3366 ierr = PetscSectionCreateGlobalSection(s, dm->sf, PETSC_FALSE, PETSC_FALSE, &dm->defaultGlobalSection);CHKERRQ(ierr); 3367 ierr = PetscLayoutDestroy(&dm->map);CHKERRQ(ierr); 3368 ierr = PetscSectionGetValueLayout(PetscObjectComm((PetscObject)dm), dm->defaultGlobalSection, &dm->map);CHKERRQ(ierr); 3369 ierr = PetscSectionViewFromOptions(dm->defaultGlobalSection, NULL, "-global_section_view");CHKERRQ(ierr); 3370 } 3371 *section = dm->defaultGlobalSection; 3372 PetscFunctionReturn(0); 3373 } 3374 3375 #undef __FUNCT__ 3376 #define __FUNCT__ "DMSetDefaultGlobalSection" 3377 /*@ 3378 DMSetDefaultGlobalSection - Set the PetscSection encoding the global data layout for the DM. 3379 3380 Input Parameters: 3381 + dm - The DM 3382 - section - The PetscSection, or NULL 3383 3384 Level: intermediate 3385 3386 Note: Any existing Section will be destroyed 3387 3388 .seealso: DMGetDefaultGlobalSection(), DMSetDefaultSection() 3389 @*/ 3390 PetscErrorCode DMSetDefaultGlobalSection(DM dm, PetscSection section) 3391 { 3392 PetscErrorCode ierr; 3393 3394 PetscFunctionBegin; 3395 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3396 if (section) PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,2); 3397 ierr = PetscObjectReference((PetscObject)section);CHKERRQ(ierr); 3398 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3399 dm->defaultGlobalSection = section; 3400 #ifdef PETSC_USE_DEBUG 3401 if (section) {ierr = DMDefaultSectionCheckConsistency_Internal(dm, dm->defaultSection, section);CHKERRQ(ierr);} 3402 #endif 3403 PetscFunctionReturn(0); 3404 } 3405 3406 #undef __FUNCT__ 3407 #define __FUNCT__ "DMGetDefaultSF" 3408 /*@ 3409 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3410 it is created from the default PetscSection layouts in the DM. 3411 3412 Input Parameter: 3413 . dm - The DM 3414 3415 Output Parameter: 3416 . sf - The PetscSF 3417 3418 Level: intermediate 3419 3420 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3421 3422 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3423 @*/ 3424 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) 3425 { 3426 PetscInt nroots; 3427 PetscErrorCode ierr; 3428 3429 PetscFunctionBegin; 3430 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3431 PetscValidPointer(sf, 2); 3432 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 3433 if (nroots < 0) { 3434 PetscSection section, gSection; 3435 3436 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3437 if (section) { 3438 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3439 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3440 } else { 3441 *sf = NULL; 3442 PetscFunctionReturn(0); 3443 } 3444 } 3445 *sf = dm->defaultSF; 3446 PetscFunctionReturn(0); 3447 } 3448 3449 #undef __FUNCT__ 3450 #define __FUNCT__ "DMSetDefaultSF" 3451 /*@ 3452 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3453 3454 Input Parameters: 3455 + dm - The DM 3456 - sf - The PetscSF 3457 3458 Level: intermediate 3459 3460 Note: Any previous SF is destroyed 3461 3462 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3463 @*/ 3464 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) 3465 { 3466 PetscErrorCode ierr; 3467 3468 PetscFunctionBegin; 3469 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3470 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3471 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3472 dm->defaultSF = sf; 3473 PetscFunctionReturn(0); 3474 } 3475 3476 #undef __FUNCT__ 3477 #define __FUNCT__ "DMCreateDefaultSF" 3478 /*@C 3479 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3480 describing the data layout. 3481 3482 Input Parameters: 3483 + dm - The DM 3484 . localSection - PetscSection describing the local data layout 3485 - globalSection - PetscSection describing the global data layout 3486 3487 Level: intermediate 3488 3489 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3490 @*/ 3491 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3492 { 3493 MPI_Comm comm; 3494 PetscLayout layout; 3495 const PetscInt *ranges; 3496 PetscInt *local; 3497 PetscSFNode *remote; 3498 PetscInt pStart, pEnd, p, nroots, nleaves = 0, l; 3499 PetscMPIInt size, rank; 3500 PetscErrorCode ierr; 3501 3502 PetscFunctionBegin; 3503 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3504 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3505 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3506 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3507 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3508 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3509 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3510 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3511 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3512 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3513 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3514 for (p = pStart; p < pEnd; ++p) { 3515 PetscInt gdof, gcdof; 3516 3517 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3518 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3519 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)); 3520 nleaves += gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3521 } 3522 ierr = PetscMalloc1(nleaves, &local);CHKERRQ(ierr); 3523 ierr = PetscMalloc1(nleaves, &remote);CHKERRQ(ierr); 3524 for (p = pStart, l = 0; p < pEnd; ++p) { 3525 const PetscInt *cind; 3526 PetscInt dof, cdof, off, gdof, gcdof, goff, gsize, d, c; 3527 3528 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3529 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3530 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3531 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3532 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3533 ierr = PetscSectionGetConstraintDof(globalSection, p, &gcdof);CHKERRQ(ierr); 3534 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3535 if (!gdof) continue; /* Censored point */ 3536 gsize = gdof < 0 ? -(gdof+1)-gcdof : gdof-gcdof; 3537 if (gsize != dof-cdof) { 3538 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); 3539 cdof = 0; /* Ignore constraints */ 3540 } 3541 for (d = 0, c = 0; d < dof; ++d) { 3542 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3543 local[l+d-c] = off+d; 3544 } 3545 if (gdof < 0) { 3546 for (d = 0; d < gsize; ++d, ++l) { 3547 PetscInt offset = -(goff+1) + d, r; 3548 3549 ierr = PetscFindInt(offset,size+1,ranges,&r);CHKERRQ(ierr); 3550 if (r < 0) r = -(r+2); 3551 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); 3552 remote[l].rank = r; 3553 remote[l].index = offset - ranges[r]; 3554 } 3555 } else { 3556 for (d = 0; d < gsize; ++d, ++l) { 3557 remote[l].rank = rank; 3558 remote[l].index = goff+d - ranges[rank]; 3559 } 3560 } 3561 } 3562 if (l != nleaves) SETERRQ2(comm, PETSC_ERR_PLIB, "Iteration error, l %d != nleaves %d", l, nleaves); 3563 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3564 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3565 PetscFunctionReturn(0); 3566 } 3567 3568 #undef __FUNCT__ 3569 #define __FUNCT__ "DMGetPointSF" 3570 /*@ 3571 DMGetPointSF - Get the PetscSF encoding the parallel section point overlap for the DM. 3572 3573 Input Parameter: 3574 . dm - The DM 3575 3576 Output Parameter: 3577 . sf - The PetscSF 3578 3579 Level: intermediate 3580 3581 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3582 3583 .seealso: DMSetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3584 @*/ 3585 PetscErrorCode DMGetPointSF(DM dm, PetscSF *sf) 3586 { 3587 PetscFunctionBegin; 3588 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3589 PetscValidPointer(sf, 2); 3590 *sf = dm->sf; 3591 PetscFunctionReturn(0); 3592 } 3593 3594 #undef __FUNCT__ 3595 #define __FUNCT__ "DMSetPointSF" 3596 /*@ 3597 DMSetPointSF - Set the PetscSF encoding the parallel section point overlap for the DM. 3598 3599 Input Parameters: 3600 + dm - The DM 3601 - sf - The PetscSF 3602 3603 Level: intermediate 3604 3605 .seealso: DMGetPointSF(), DMGetDefaultSF(), DMSetDefaultSF(), DMCreateDefaultSF() 3606 @*/ 3607 PetscErrorCode DMSetPointSF(DM dm, PetscSF sf) 3608 { 3609 PetscErrorCode ierr; 3610 3611 PetscFunctionBegin; 3612 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3613 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 3614 ierr = PetscSFDestroy(&dm->sf);CHKERRQ(ierr); 3615 ierr = PetscObjectReference((PetscObject) sf);CHKERRQ(ierr); 3616 dm->sf = sf; 3617 PetscFunctionReturn(0); 3618 } 3619 3620 #undef __FUNCT__ 3621 #define __FUNCT__ "DMGetDS" 3622 /*@ 3623 DMGetDS - Get the PetscDS 3624 3625 Input Parameter: 3626 . dm - The DM 3627 3628 Output Parameter: 3629 . prob - The PetscDS 3630 3631 Level: developer 3632 3633 .seealso: DMSetDS() 3634 @*/ 3635 PetscErrorCode DMGetDS(DM dm, PetscDS *prob) 3636 { 3637 PetscFunctionBegin; 3638 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3639 PetscValidPointer(prob, 2); 3640 *prob = dm->prob; 3641 PetscFunctionReturn(0); 3642 } 3643 3644 #undef __FUNCT__ 3645 #define __FUNCT__ "DMSetDS" 3646 /*@ 3647 DMSetDS - Set the PetscDS 3648 3649 Input Parameters: 3650 + dm - The DM 3651 - prob - The PetscDS 3652 3653 Level: developer 3654 3655 .seealso: DMGetDS() 3656 @*/ 3657 PetscErrorCode DMSetDS(DM dm, PetscDS prob) 3658 { 3659 PetscErrorCode ierr; 3660 3661 PetscFunctionBegin; 3662 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3663 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 2); 3664 ierr = PetscDSDestroy(&dm->prob);CHKERRQ(ierr); 3665 dm->prob = prob; 3666 ierr = PetscObjectReference((PetscObject) dm->prob);CHKERRQ(ierr); 3667 PetscFunctionReturn(0); 3668 } 3669 3670 #undef __FUNCT__ 3671 #define __FUNCT__ "DMGetNumFields" 3672 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3673 { 3674 PetscErrorCode ierr; 3675 3676 PetscFunctionBegin; 3677 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3678 ierr = PetscDSGetNumFields(dm->prob, numFields);CHKERRQ(ierr); 3679 PetscFunctionReturn(0); 3680 } 3681 3682 #undef __FUNCT__ 3683 #define __FUNCT__ "DMSetNumFields" 3684 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3685 { 3686 PetscInt Nf, f; 3687 PetscErrorCode ierr; 3688 3689 PetscFunctionBegin; 3690 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3691 ierr = PetscDSGetNumFields(dm->prob, &Nf);CHKERRQ(ierr); 3692 for (f = Nf; f < numFields; ++f) { 3693 PetscContainer obj; 3694 3695 ierr = PetscContainerCreate(PetscObjectComm((PetscObject) dm), &obj);CHKERRQ(ierr); 3696 ierr = PetscDSSetDiscretization(dm->prob, f, (PetscObject) obj);CHKERRQ(ierr); 3697 ierr = PetscContainerDestroy(&obj);CHKERRQ(ierr); 3698 } 3699 PetscFunctionReturn(0); 3700 } 3701 3702 #undef __FUNCT__ 3703 #define __FUNCT__ "DMGetField" 3704 /*@ 3705 DMGetField - Return the discretization object for a given DM field 3706 3707 Not collective 3708 3709 Input Parameters: 3710 + dm - The DM 3711 - f - The field number 3712 3713 Output Parameter: 3714 . field - The discretization object 3715 3716 Level: developer 3717 3718 .seealso: DMSetField() 3719 @*/ 3720 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3721 { 3722 PetscErrorCode ierr; 3723 3724 PetscFunctionBegin; 3725 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3726 ierr = PetscDSGetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3727 PetscFunctionReturn(0); 3728 } 3729 3730 #undef __FUNCT__ 3731 #define __FUNCT__ "DMSetField" 3732 /*@ 3733 DMSetField - Set the discretization object for a given DM field 3734 3735 Logically collective on DM 3736 3737 Input Parameters: 3738 + dm - The DM 3739 . f - The field number 3740 - field - The discretization object 3741 3742 Level: developer 3743 3744 .seealso: DMGetField() 3745 @*/ 3746 PetscErrorCode DMSetField(DM dm, PetscInt f, PetscObject field) 3747 { 3748 PetscErrorCode ierr; 3749 3750 PetscFunctionBegin; 3751 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3752 ierr = PetscDSSetDiscretization(dm->prob, f, field);CHKERRQ(ierr); 3753 PetscFunctionReturn(0); 3754 } 3755 3756 #undef __FUNCT__ 3757 #define __FUNCT__ "DMRestrictHook_Coordinates" 3758 PetscErrorCode DMRestrictHook_Coordinates(DM dm,DM dmc,void *ctx) 3759 { 3760 DM dm_coord,dmc_coord; 3761 PetscErrorCode ierr; 3762 Vec coords,ccoords; 3763 Mat inject; 3764 PetscFunctionBegin; 3765 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3766 ierr = DMGetCoordinateDM(dmc,&dmc_coord);CHKERRQ(ierr); 3767 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3768 ierr = DMGetCoordinates(dmc,&ccoords);CHKERRQ(ierr); 3769 if (coords && !ccoords) { 3770 ierr = DMCreateGlobalVector(dmc_coord,&ccoords);CHKERRQ(ierr); 3771 ierr = DMCreateInjection(dmc_coord,dm_coord,&inject);CHKERRQ(ierr); 3772 ierr = MatRestrict(inject,coords,ccoords);CHKERRQ(ierr); 3773 ierr = MatDestroy(&inject);CHKERRQ(ierr); 3774 ierr = DMSetCoordinates(dmc,ccoords);CHKERRQ(ierr); 3775 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3776 } 3777 PetscFunctionReturn(0); 3778 } 3779 3780 #undef __FUNCT__ 3781 #define __FUNCT__ "DMSubDomainHook_Coordinates" 3782 static PetscErrorCode DMSubDomainHook_Coordinates(DM dm,DM subdm,void *ctx) 3783 { 3784 DM dm_coord,subdm_coord; 3785 PetscErrorCode ierr; 3786 Vec coords,ccoords,clcoords; 3787 VecScatter *scat_i,*scat_g; 3788 PetscFunctionBegin; 3789 ierr = DMGetCoordinateDM(dm,&dm_coord);CHKERRQ(ierr); 3790 ierr = DMGetCoordinateDM(subdm,&subdm_coord);CHKERRQ(ierr); 3791 ierr = DMGetCoordinates(dm,&coords);CHKERRQ(ierr); 3792 ierr = DMGetCoordinates(subdm,&ccoords);CHKERRQ(ierr); 3793 if (coords && !ccoords) { 3794 ierr = DMCreateGlobalVector(subdm_coord,&ccoords);CHKERRQ(ierr); 3795 ierr = DMCreateLocalVector(subdm_coord,&clcoords);CHKERRQ(ierr); 3796 ierr = PetscObjectSetName((PetscObject)clcoords,"coordinates");CHKERRQ(ierr); 3797 ierr = DMCreateDomainDecompositionScatters(dm_coord,1,&subdm_coord,NULL,&scat_i,&scat_g);CHKERRQ(ierr); 3798 ierr = VecScatterBegin(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3799 ierr = VecScatterBegin(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3800 ierr = VecScatterEnd(scat_i[0],coords,ccoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3801 ierr = VecScatterEnd(scat_g[0],coords,clcoords,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3802 ierr = DMSetCoordinates(subdm,ccoords);CHKERRQ(ierr); 3803 ierr = DMSetCoordinatesLocal(subdm,clcoords);CHKERRQ(ierr); 3804 ierr = VecScatterDestroy(&scat_i[0]);CHKERRQ(ierr); 3805 ierr = VecScatterDestroy(&scat_g[0]);CHKERRQ(ierr); 3806 ierr = VecDestroy(&ccoords);CHKERRQ(ierr); 3807 ierr = VecDestroy(&clcoords);CHKERRQ(ierr); 3808 ierr = PetscFree(scat_i);CHKERRQ(ierr); 3809 ierr = PetscFree(scat_g);CHKERRQ(ierr); 3810 } 3811 PetscFunctionReturn(0); 3812 } 3813 3814 #undef __FUNCT__ 3815 #define __FUNCT__ "DMGetDimension" 3816 /*@ 3817 DMGetDimension - Return the topological dimension of the DM 3818 3819 Not collective 3820 3821 Input Parameter: 3822 . dm - The DM 3823 3824 Output Parameter: 3825 . dim - The topological dimension 3826 3827 Level: beginner 3828 3829 .seealso: DMSetDimension(), DMCreate() 3830 @*/ 3831 PetscErrorCode DMGetDimension(DM dm, PetscInt *dim) 3832 { 3833 PetscFunctionBegin; 3834 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3835 PetscValidPointer(dim, 2); 3836 *dim = dm->dim; 3837 PetscFunctionReturn(0); 3838 } 3839 3840 #undef __FUNCT__ 3841 #define __FUNCT__ "DMSetDimension" 3842 /*@ 3843 DMSetDimension - Set the topological dimension of the DM 3844 3845 Collective on dm 3846 3847 Input Parameters: 3848 + dm - The DM 3849 - dim - The topological dimension 3850 3851 Level: beginner 3852 3853 .seealso: DMGetDimension(), DMCreate() 3854 @*/ 3855 PetscErrorCode DMSetDimension(DM dm, PetscInt dim) 3856 { 3857 PetscFunctionBegin; 3858 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3859 PetscValidLogicalCollectiveInt(dm, dim, 2); 3860 dm->dim = dim; 3861 PetscFunctionReturn(0); 3862 } 3863 3864 #undef __FUNCT__ 3865 #define __FUNCT__ "DMGetDimPoints" 3866 /*@ 3867 DMGetDimPoints - Get the half-open interval for all points of a given dimension 3868 3869 Collective on DM 3870 3871 Input Parameters: 3872 + dm - the DM 3873 - dim - the dimension 3874 3875 Output Parameters: 3876 + pStart - The first point of the given dimension 3877 . pEnd - The first point following points of the given dimension 3878 3879 Note: 3880 The points are vertices in the Hasse diagram encoding the topology. This is explained in 3881 http://arxiv.org/abs/0908.4427. If not points exist of this dimension in the storage scheme, 3882 then the interval is empty. 3883 3884 Level: intermediate 3885 3886 .keywords: point, Hasse Diagram, dimension 3887 .seealso: DMPLEX, DMPlexGetDepthStratum(), DMPlexGetHeightStratum() 3888 @*/ 3889 PetscErrorCode DMGetDimPoints(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 3890 { 3891 PetscInt d; 3892 PetscErrorCode ierr; 3893 3894 PetscFunctionBegin; 3895 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3896 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 3897 if ((dim < 0) || (dim > d)) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d 1", dim, d); 3898 ierr = (*dm->ops->getdimpoints)(dm, dim, pStart, pEnd);CHKERRQ(ierr); 3899 PetscFunctionReturn(0); 3900 } 3901 3902 #undef __FUNCT__ 3903 #define __FUNCT__ "DMSetCoordinates" 3904 /*@ 3905 DMSetCoordinates - Sets into the DM a global vector that holds the coordinates 3906 3907 Collective on DM 3908 3909 Input Parameters: 3910 + dm - the DM 3911 - c - coordinate vector 3912 3913 Note: 3914 The coordinates do include those for ghost points, which are in the local vector 3915 3916 Level: intermediate 3917 3918 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3919 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLoca(), DMGetCoordinateDM() 3920 @*/ 3921 PetscErrorCode DMSetCoordinates(DM dm, Vec c) 3922 { 3923 PetscErrorCode ierr; 3924 3925 PetscFunctionBegin; 3926 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3927 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3928 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3929 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3930 dm->coordinates = c; 3931 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3932 ierr = DMCoarsenHookAdd(dm,DMRestrictHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3933 ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_Coordinates,NULL,NULL);CHKERRQ(ierr); 3934 PetscFunctionReturn(0); 3935 } 3936 3937 #undef __FUNCT__ 3938 #define __FUNCT__ "DMSetCoordinatesLocal" 3939 /*@ 3940 DMSetCoordinatesLocal - Sets into the DM a local vector that holds the coordinates 3941 3942 Collective on DM 3943 3944 Input Parameters: 3945 + dm - the DM 3946 - c - coordinate vector 3947 3948 Note: 3949 The coordinates of ghost points can be set using DMSetCoordinates() 3950 followed by DMGetCoordinatesLocal(). This is intended to enable the 3951 setting of ghost coordinates outside of the domain. 3952 3953 Level: intermediate 3954 3955 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3956 .seealso: DMGetCoordinatesLocal(), DMSetCoordinates(), DMGetCoordinates(), DMGetCoordinateDM() 3957 @*/ 3958 PetscErrorCode DMSetCoordinatesLocal(DM dm, Vec c) 3959 { 3960 PetscErrorCode ierr; 3961 3962 PetscFunctionBegin; 3963 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 3964 PetscValidHeaderSpecific(c,VEC_CLASSID,2); 3965 ierr = PetscObjectReference((PetscObject) c);CHKERRQ(ierr); 3966 ierr = VecDestroy(&dm->coordinatesLocal);CHKERRQ(ierr); 3967 3968 dm->coordinatesLocal = c; 3969 3970 ierr = VecDestroy(&dm->coordinates);CHKERRQ(ierr); 3971 PetscFunctionReturn(0); 3972 } 3973 3974 #undef __FUNCT__ 3975 #define __FUNCT__ "DMGetCoordinates" 3976 /*@ 3977 DMGetCoordinates - Gets a global vector with the coordinates associated with the DM. 3978 3979 Not Collective 3980 3981 Input Parameter: 3982 . dm - the DM 3983 3984 Output Parameter: 3985 . c - global coordinate vector 3986 3987 Note: 3988 This is a borrowed reference, so the user should NOT destroy this vector 3989 3990 Each process has only the local coordinates (does NOT have the ghost coordinates). 3991 3992 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 3993 and (x_0,y_0,z_0,x_1,y_1,z_1...) 3994 3995 Level: intermediate 3996 3997 .keywords: distributed array, get, corners, nodes, local indices, coordinates 3998 .seealso: DMSetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM() 3999 @*/ 4000 PetscErrorCode DMGetCoordinates(DM dm, Vec *c) 4001 { 4002 PetscErrorCode ierr; 4003 4004 PetscFunctionBegin; 4005 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4006 PetscValidPointer(c,2); 4007 if (!dm->coordinates && dm->coordinatesLocal) { 4008 DM cdm = NULL; 4009 4010 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4011 ierr = DMCreateGlobalVector(cdm, &dm->coordinates);CHKERRQ(ierr); 4012 ierr = PetscObjectSetName((PetscObject) dm->coordinates, "coordinates");CHKERRQ(ierr); 4013 ierr = DMLocalToGlobalBegin(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4014 ierr = DMLocalToGlobalEnd(cdm, dm->coordinatesLocal, INSERT_VALUES, dm->coordinates);CHKERRQ(ierr); 4015 } 4016 *c = dm->coordinates; 4017 PetscFunctionReturn(0); 4018 } 4019 4020 #undef __FUNCT__ 4021 #define __FUNCT__ "DMGetCoordinatesLocal" 4022 /*@ 4023 DMGetCoordinatesLocal - Gets a local vector with the coordinates associated with the DM. 4024 4025 Collective on DM 4026 4027 Input Parameter: 4028 . dm - the DM 4029 4030 Output Parameter: 4031 . c - coordinate vector 4032 4033 Note: 4034 This is a borrowed reference, so the user should NOT destroy this vector 4035 4036 Each process has the local and ghost coordinates 4037 4038 For DMDA, in two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...) 4039 and (x_0,y_0,z_0,x_1,y_1,z_1...) 4040 4041 Level: intermediate 4042 4043 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4044 .seealso: DMSetCoordinatesLocal(), DMGetCoordinates(), DMSetCoordinates(), DMGetCoordinateDM() 4045 @*/ 4046 PetscErrorCode DMGetCoordinatesLocal(DM dm, Vec *c) 4047 { 4048 PetscErrorCode ierr; 4049 4050 PetscFunctionBegin; 4051 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4052 PetscValidPointer(c,2); 4053 if (!dm->coordinatesLocal && dm->coordinates) { 4054 DM cdm = NULL; 4055 4056 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4057 ierr = DMCreateLocalVector(cdm, &dm->coordinatesLocal);CHKERRQ(ierr); 4058 ierr = PetscObjectSetName((PetscObject) dm->coordinatesLocal, "coordinates");CHKERRQ(ierr); 4059 ierr = DMGlobalToLocalBegin(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4060 ierr = DMGlobalToLocalEnd(cdm, dm->coordinates, INSERT_VALUES, dm->coordinatesLocal);CHKERRQ(ierr); 4061 } 4062 *c = dm->coordinatesLocal; 4063 PetscFunctionReturn(0); 4064 } 4065 4066 #undef __FUNCT__ 4067 #define __FUNCT__ "DMGetCoordinateDM" 4068 /*@ 4069 DMGetCoordinateDM - Gets the DM that prescribes coordinate layout and scatters between global and local coordinates 4070 4071 Collective on DM 4072 4073 Input Parameter: 4074 . dm - the DM 4075 4076 Output Parameter: 4077 . cdm - coordinate DM 4078 4079 Level: intermediate 4080 4081 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4082 .seealso: DMSetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4083 @*/ 4084 PetscErrorCode DMGetCoordinateDM(DM dm, DM *cdm) 4085 { 4086 PetscErrorCode ierr; 4087 4088 PetscFunctionBegin; 4089 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4090 PetscValidPointer(cdm,2); 4091 if (!dm->coordinateDM) { 4092 if (!dm->ops->createcoordinatedm) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unable to create coordinates for this DM"); 4093 ierr = (*dm->ops->createcoordinatedm)(dm, &dm->coordinateDM);CHKERRQ(ierr); 4094 } 4095 *cdm = dm->coordinateDM; 4096 PetscFunctionReturn(0); 4097 } 4098 4099 #undef __FUNCT__ 4100 #define __FUNCT__ "DMSetCoordinateDM" 4101 /*@ 4102 DMSetCoordinateDM - Sets the DM that prescribes coordinate layout and scatters between global and local coordinates 4103 4104 Logically Collective on DM 4105 4106 Input Parameters: 4107 + dm - the DM 4108 - cdm - coordinate DM 4109 4110 Level: intermediate 4111 4112 .keywords: distributed array, get, corners, nodes, local indices, coordinates 4113 .seealso: DMGetCoordinateDM(), DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4114 @*/ 4115 PetscErrorCode DMSetCoordinateDM(DM dm, DM cdm) 4116 { 4117 PetscErrorCode ierr; 4118 4119 PetscFunctionBegin; 4120 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4121 PetscValidHeaderSpecific(cdm,DM_CLASSID,2); 4122 ierr = DMDestroy(&dm->coordinateDM);CHKERRQ(ierr); 4123 dm->coordinateDM = cdm; 4124 ierr = PetscObjectReference((PetscObject) dm->coordinateDM);CHKERRQ(ierr); 4125 PetscFunctionReturn(0); 4126 } 4127 4128 #undef __FUNCT__ 4129 #define __FUNCT__ "DMGetCoordinateDim" 4130 /*@ 4131 DMGetCoordinateDim - Retrieve the dimension of embedding space for coordinate values. 4132 4133 Not Collective 4134 4135 Input Parameter: 4136 . dm - The DM object 4137 4138 Output Parameter: 4139 . dim - The embedding dimension 4140 4141 Level: intermediate 4142 4143 .keywords: mesh, coordinates 4144 .seealso: DMSetCoordinateDim(), DMGetCoordinateSection(), DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4145 @*/ 4146 PetscErrorCode DMGetCoordinateDim(DM dm, PetscInt *dim) 4147 { 4148 PetscFunctionBegin; 4149 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4150 PetscValidPointer(dim, 2); 4151 if (dm->dimEmbed == PETSC_DEFAULT) { 4152 dm->dimEmbed = dm->dim; 4153 } 4154 *dim = dm->dimEmbed; 4155 PetscFunctionReturn(0); 4156 } 4157 4158 #undef __FUNCT__ 4159 #define __FUNCT__ "DMSetCoordinateDim" 4160 /*@ 4161 DMSetCoordinateDim - Set the dimension of the embedding space for coordinate values. 4162 4163 Not Collective 4164 4165 Input Parameters: 4166 + dm - The DM object 4167 - dim - The embedding dimension 4168 4169 Level: intermediate 4170 4171 .keywords: mesh, coordinates 4172 .seealso: DMGetCoordinateDim(), DMSetCoordinateSection(), DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4173 @*/ 4174 PetscErrorCode DMSetCoordinateDim(DM dm, PetscInt dim) 4175 { 4176 PetscFunctionBegin; 4177 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4178 dm->dimEmbed = dim; 4179 PetscFunctionReturn(0); 4180 } 4181 4182 #undef __FUNCT__ 4183 #define __FUNCT__ "DMGetCoordinateSection" 4184 /*@ 4185 DMGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 4186 4187 Not Collective 4188 4189 Input Parameter: 4190 . dm - The DM object 4191 4192 Output Parameter: 4193 . section - The PetscSection object 4194 4195 Level: intermediate 4196 4197 .keywords: mesh, coordinates 4198 .seealso: DMGetCoordinateDM(), DMGetDefaultSection(), DMSetDefaultSection() 4199 @*/ 4200 PetscErrorCode DMGetCoordinateSection(DM dm, PetscSection *section) 4201 { 4202 DM cdm; 4203 PetscErrorCode ierr; 4204 4205 PetscFunctionBegin; 4206 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4207 PetscValidPointer(section, 2); 4208 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4209 ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 4210 PetscFunctionReturn(0); 4211 } 4212 4213 #undef __FUNCT__ 4214 #define __FUNCT__ "DMSetCoordinateSection" 4215 /*@ 4216 DMSetCoordinateSection - Set the layout of coordinate values over the mesh. 4217 4218 Not Collective 4219 4220 Input Parameters: 4221 + dm - The DM object 4222 . dim - The embedding dimension, or PETSC_DETERMINE 4223 - section - The PetscSection object 4224 4225 Level: intermediate 4226 4227 .keywords: mesh, coordinates 4228 .seealso: DMGetCoordinateSection(), DMGetDefaultSection(), DMSetDefaultSection() 4229 @*/ 4230 PetscErrorCode DMSetCoordinateSection(DM dm, PetscInt dim, PetscSection section) 4231 { 4232 DM cdm; 4233 PetscErrorCode ierr; 4234 4235 PetscFunctionBegin; 4236 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4237 PetscValidHeaderSpecific(section,PETSC_SECTION_CLASSID,3); 4238 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4239 ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 4240 if (dim == PETSC_DETERMINE) { 4241 PetscInt d = dim; 4242 PetscInt pStart, pEnd, vStart, vEnd, v, dd; 4243 4244 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4245 ierr = DMGetDimPoints(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4246 pStart = PetscMax(vStart, pStart); 4247 pEnd = PetscMin(vEnd, pEnd); 4248 for (v = pStart; v < pEnd; ++v) { 4249 ierr = PetscSectionGetDof(section, v, &dd);CHKERRQ(ierr); 4250 if (dd) {d = dd; break;} 4251 } 4252 ierr = DMSetCoordinateDim(dm, d);CHKERRQ(ierr); 4253 } 4254 PetscFunctionReturn(0); 4255 } 4256 4257 #undef __FUNCT__ 4258 #define __FUNCT__ "DMGetPeriodicity" 4259 /*@C 4260 DMSetPeriodicity - Set the description of mesh periodicity 4261 4262 Input Parameters: 4263 + dm - The DM object 4264 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4265 . L - If we assume the mesh is a torus, this is the length of each coordinate 4266 - bd - This describes the type of periodicity in each topological dimension 4267 4268 Level: developer 4269 4270 .seealso: DMGetPeriodicity() 4271 @*/ 4272 PetscErrorCode DMGetPeriodicity(DM dm, const PetscReal **maxCell, const PetscReal **L, const DMBoundaryType **bd) 4273 { 4274 PetscFunctionBegin; 4275 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4276 if (L) *L = dm->L; 4277 if (maxCell) *maxCell = dm->maxCell; 4278 if (bd) *bd = dm->bdtype; 4279 PetscFunctionReturn(0); 4280 } 4281 4282 #undef __FUNCT__ 4283 #define __FUNCT__ "DMSetPeriodicity" 4284 /*@C 4285 DMSetPeriodicity - Set the description of mesh periodicity 4286 4287 Input Parameters: 4288 + dm - The DM object 4289 . maxCell - Over distances greater than this, we can assume a point has crossed over to another sheet, when trying to localize cell coordinates 4290 . L - If we assume the mesh is a torus, this is the length of each coordinate 4291 - bd - This describes the type of periodicity in each topological dimension 4292 4293 Level: developer 4294 4295 .seealso: DMGetPeriodicity() 4296 @*/ 4297 PetscErrorCode DMSetPeriodicity(DM dm, const PetscReal maxCell[], const PetscReal L[], const DMBoundaryType bd[]) 4298 { 4299 PetscInt dim, d; 4300 PetscErrorCode ierr; 4301 4302 PetscFunctionBegin; 4303 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4304 PetscValidPointer(L,3);PetscValidPointer(maxCell,2);PetscValidPointer(bd,4); 4305 ierr = PetscFree3(dm->L,dm->maxCell,dm->bdtype);CHKERRQ(ierr); 4306 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4307 ierr = PetscMalloc3(dim,&dm->L,dim,&dm->maxCell,dim,&dm->bdtype);CHKERRQ(ierr); 4308 for (d = 0; d < dim; ++d) {dm->L[d] = L[d]; dm->maxCell[d] = maxCell[d]; dm->bdtype[d] = bd[d];} 4309 PetscFunctionReturn(0); 4310 } 4311 4312 #undef __FUNCT__ 4313 #define __FUNCT__ "DMLocatePoints" 4314 /*@ 4315 DMLocatePoints - Locate the points in v in the mesh and return an IS of the containing cells 4316 4317 Not collective 4318 4319 Input Parameters: 4320 + dm - The DM 4321 - v - The Vec of points 4322 4323 Output Parameter: 4324 . cells - The local cell numbers for cells which contain the points 4325 4326 Level: developer 4327 4328 .keywords: point location, mesh 4329 .seealso: DMSetCoordinates(), DMSetCoordinatesLocal(), DMGetCoordinates(), DMGetCoordinatesLocal() 4330 @*/ 4331 PetscErrorCode DMLocatePoints(DM dm, Vec v, IS *cells) 4332 { 4333 PetscErrorCode ierr; 4334 4335 PetscFunctionBegin; 4336 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4337 PetscValidHeaderSpecific(v,VEC_CLASSID,2); 4338 PetscValidPointer(cells,3); 4339 ierr = PetscLogEventBegin(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4340 if (dm->ops->locatepoints) { 4341 ierr = (*dm->ops->locatepoints)(dm,v,cells);CHKERRQ(ierr); 4342 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Point location not available for this DM"); 4343 ierr = PetscLogEventEnd(DM_LocatePoints,dm,0,0,0);CHKERRQ(ierr); 4344 PetscFunctionReturn(0); 4345 } 4346 4347 #undef __FUNCT__ 4348 #define __FUNCT__ "DMGetOutputDM" 4349 /*@ 4350 DMGetOutputDM - Retrieve the DM associated with the layout for output 4351 4352 Input Parameter: 4353 . dm - The original DM 4354 4355 Output Parameter: 4356 . odm - The DM which provides the layout for output 4357 4358 Level: intermediate 4359 4360 .seealso: VecView(), DMGetDefaultGlobalSection() 4361 @*/ 4362 PetscErrorCode DMGetOutputDM(DM dm, DM *odm) 4363 { 4364 PetscSection section; 4365 PetscBool hasConstraints; 4366 PetscErrorCode ierr; 4367 4368 PetscFunctionBegin; 4369 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4370 PetscValidPointer(odm,2); 4371 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 4372 ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr); 4373 if (!hasConstraints) { 4374 *odm = dm; 4375 PetscFunctionReturn(0); 4376 } 4377 if (!dm->dmBC) { 4378 PetscSection newSection, gsection; 4379 PetscSF sf; 4380 4381 ierr = DMClone(dm, &dm->dmBC);CHKERRQ(ierr); 4382 ierr = PetscSectionClone(section, &newSection);CHKERRQ(ierr); 4383 ierr = DMSetDefaultSection(dm->dmBC, newSection);CHKERRQ(ierr); 4384 ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr); 4385 ierr = DMGetPointSF(dm->dmBC, &sf);CHKERRQ(ierr); 4386 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr); 4387 ierr = DMSetDefaultGlobalSection(dm->dmBC, gsection);CHKERRQ(ierr); 4388 ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr); 4389 } 4390 *odm = dm->dmBC; 4391 PetscFunctionReturn(0); 4392 } 4393 4394 #undef __FUNCT__ 4395 #define __FUNCT__ "DMGetOutputSequenceNumber" 4396 /*@ 4397 DMGetOutputSequenceNumber - Retrieve the sequence number/value for output 4398 4399 Input Parameter: 4400 . dm - The original DM 4401 4402 Output Parameters: 4403 + num - The output sequence number 4404 - val - The output sequence value 4405 4406 Level: intermediate 4407 4408 Note: This is intended for output that should appear in sequence, for instance 4409 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4410 4411 .seealso: VecView() 4412 @*/ 4413 PetscErrorCode DMGetOutputSequenceNumber(DM dm, PetscInt *num, PetscReal *val) 4414 { 4415 PetscFunctionBegin; 4416 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4417 if (num) {PetscValidPointer(num,2); *num = dm->outputSequenceNum;} 4418 if (val) {PetscValidPointer(val,3);*val = dm->outputSequenceVal;} 4419 PetscFunctionReturn(0); 4420 } 4421 4422 #undef __FUNCT__ 4423 #define __FUNCT__ "DMSetOutputSequenceNumber" 4424 /*@ 4425 DMSetOutputSequenceNumber - Set the sequence number/value for output 4426 4427 Input Parameters: 4428 + dm - The original DM 4429 . num - The output sequence number 4430 - val - The output sequence value 4431 4432 Level: intermediate 4433 4434 Note: This is intended for output that should appear in sequence, for instance 4435 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4436 4437 .seealso: VecView() 4438 @*/ 4439 PetscErrorCode DMSetOutputSequenceNumber(DM dm, PetscInt num, PetscReal val) 4440 { 4441 PetscFunctionBegin; 4442 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4443 dm->outputSequenceNum = num; 4444 dm->outputSequenceVal = val; 4445 PetscFunctionReturn(0); 4446 } 4447 4448 #undef __FUNCT__ 4449 #define __FUNCT__ "DMOutputSequenceLoad" 4450 /*@C 4451 DMOutputSequenceLoad - Retrieve the sequence value from a Viewer 4452 4453 Input Parameters: 4454 + dm - The original DM 4455 . name - The sequence name 4456 - num - The output sequence number 4457 4458 Output Parameter: 4459 . val - The output sequence value 4460 4461 Level: intermediate 4462 4463 Note: This is intended for output that should appear in sequence, for instance 4464 a set of timesteps in an HDF5 file, or a set of realizations of a stochastic system. 4465 4466 .seealso: DMGetOutputSequenceNumber(), DMSetOutputSequenceNumber(), VecView() 4467 @*/ 4468 PetscErrorCode DMOutputSequenceLoad(DM dm, PetscViewer viewer, const char *name, PetscInt num, PetscReal *val) 4469 { 4470 PetscBool ishdf5; 4471 PetscErrorCode ierr; 4472 4473 PetscFunctionBegin; 4474 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 4475 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 4476 PetscValidPointer(val,4); 4477 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 4478 if (ishdf5) { 4479 #if defined(PETSC_HAVE_HDF5) 4480 PetscScalar value; 4481 4482 ierr = DMSequenceLoad_HDF5(dm, name, num, &value, viewer);CHKERRQ(ierr); 4483 *val = PetscRealPart(value); 4484 #endif 4485 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerHDF5Open()"); 4486 PetscFunctionReturn(0); 4487 } 4488 4489 #undef __FUNCT__ 4490 #define __FUNCT__ "DMGetUseNatural" 4491 /*@ 4492 DMGetUseNatural - Get the flag for creating a mapping to the natural order on distribution 4493 4494 Not collective 4495 4496 Input Parameter: 4497 . dm - The DM 4498 4499 Output Parameter: 4500 . useNatural - The flag to build the mapping to a natural order during distribution 4501 4502 Level: beginner 4503 4504 .seealso: DMSetUseNatural(), DMCreate() 4505 @*/ 4506 PetscErrorCode DMGetUseNatural(DM dm, PetscBool *useNatural) 4507 { 4508 PetscFunctionBegin; 4509 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4510 PetscValidPointer(useNatural, 2); 4511 *useNatural = dm->useNatural; 4512 PetscFunctionReturn(0); 4513 } 4514 4515 #undef __FUNCT__ 4516 #define __FUNCT__ "DMSetUseNatural" 4517 /*@ 4518 DMSetUseNatural - Set the flag for creating a mapping to the natural order on distribution 4519 4520 Collective on dm 4521 4522 Input Parameters: 4523 + dm - The DM 4524 - useNatural - The flag to build the mapping to a natural order during distribution 4525 4526 Level: beginner 4527 4528 .seealso: DMGetUseNatural(), DMCreate() 4529 @*/ 4530 PetscErrorCode DMSetUseNatural(DM dm, PetscBool useNatural) 4531 { 4532 PetscFunctionBegin; 4533 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4534 PetscValidLogicalCollectiveInt(dm, useNatural, 2); 4535 dm->useNatural = useNatural; 4536 PetscFunctionReturn(0); 4537 } 4538 4539 #undef __FUNCT__ 4540 #define __FUNCT__ 4541 4542 #undef __FUNCT__ 4543 #define __FUNCT__ "DMCreateLabel" 4544 /*@C 4545 DMCreateLabel - Create a label of the given name if it does not already exist 4546 4547 Not Collective 4548 4549 Input Parameters: 4550 + dm - The DM object 4551 - name - The label name 4552 4553 Level: intermediate 4554 4555 .keywords: mesh 4556 .seealso: DMLabelCreate(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 4557 @*/ 4558 PetscErrorCode DMCreateLabel(DM dm, const char name[]) 4559 { 4560 DMLabelLink next = dm->labels->next; 4561 PetscBool flg = PETSC_FALSE; 4562 PetscErrorCode ierr; 4563 4564 PetscFunctionBegin; 4565 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4566 PetscValidCharPointer(name, 2); 4567 while (next) { 4568 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 4569 if (flg) break; 4570 next = next->next; 4571 } 4572 if (!flg) { 4573 DMLabelLink tmpLabel; 4574 4575 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 4576 ierr = DMLabelCreate(name, &tmpLabel->label);CHKERRQ(ierr); 4577 tmpLabel->output = PETSC_TRUE; 4578 tmpLabel->next = dm->labels->next; 4579 dm->labels->next = tmpLabel; 4580 } 4581 PetscFunctionReturn(0); 4582 } 4583 4584 #undef __FUNCT__ 4585 #define __FUNCT__ "DMGetLabelValue" 4586 /*@C 4587 DMGetLabelValue - Get the value in a Sieve Label for the given point, with 0 as the default 4588 4589 Not Collective 4590 4591 Input Parameters: 4592 + dm - The DM object 4593 . name - The label name 4594 - point - The mesh point 4595 4596 Output Parameter: 4597 . value - The label value for this point, or -1 if the point is not in the label 4598 4599 Level: beginner 4600 4601 .keywords: mesh 4602 .seealso: DMLabelGetValue(), DMSetLabelValue(), DMGetStratumIS() 4603 @*/ 4604 PetscErrorCode DMGetLabelValue(DM dm, const char name[], PetscInt point, PetscInt *value) 4605 { 4606 DMLabel label; 4607 PetscErrorCode ierr; 4608 4609 PetscFunctionBegin; 4610 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4611 PetscValidCharPointer(name, 2); 4612 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4613 if (!label) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No label named %s was found", name);CHKERRQ(ierr); 4614 ierr = DMLabelGetValue(label, point, value);CHKERRQ(ierr); 4615 PetscFunctionReturn(0); 4616 } 4617 4618 #undef __FUNCT__ 4619 #define __FUNCT__ "DMSetLabelValue" 4620 /*@C 4621 DMSetLabelValue - Add a point to a Sieve Label with given value 4622 4623 Not Collective 4624 4625 Input Parameters: 4626 + dm - The DM object 4627 . name - The label name 4628 . point - The mesh point 4629 - value - The label value for this point 4630 4631 Output Parameter: 4632 4633 Level: beginner 4634 4635 .keywords: mesh 4636 .seealso: DMLabelSetValue(), DMGetStratumIS(), DMClearLabelValue() 4637 @*/ 4638 PetscErrorCode DMSetLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 4639 { 4640 DMLabel label; 4641 PetscErrorCode ierr; 4642 4643 PetscFunctionBegin; 4644 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4645 PetscValidCharPointer(name, 2); 4646 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4647 if (!label) { 4648 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 4649 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4650 } 4651 ierr = DMLabelSetValue(label, point, value);CHKERRQ(ierr); 4652 PetscFunctionReturn(0); 4653 } 4654 4655 #undef __FUNCT__ 4656 #define __FUNCT__ "DMClearLabelValue" 4657 /*@C 4658 DMClearLabelValue - Remove a point from a Sieve Label with given value 4659 4660 Not Collective 4661 4662 Input Parameters: 4663 + dm - The DM object 4664 . name - The label name 4665 . point - The mesh point 4666 - value - The label value for this point 4667 4668 Output Parameter: 4669 4670 Level: beginner 4671 4672 .keywords: mesh 4673 .seealso: DMLabelClearValue(), DMSetLabelValue(), DMGetStratumIS() 4674 @*/ 4675 PetscErrorCode DMClearLabelValue(DM dm, const char name[], PetscInt point, PetscInt value) 4676 { 4677 DMLabel label; 4678 PetscErrorCode ierr; 4679 4680 PetscFunctionBegin; 4681 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4682 PetscValidCharPointer(name, 2); 4683 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4684 if (!label) PetscFunctionReturn(0); 4685 ierr = DMLabelClearValue(label, point, value);CHKERRQ(ierr); 4686 PetscFunctionReturn(0); 4687 } 4688 4689 #undef __FUNCT__ 4690 #define __FUNCT__ "DMGetLabelSize" 4691 /*@C 4692 DMGetLabelSize - Get the number of different integer ids in a Label 4693 4694 Not Collective 4695 4696 Input Parameters: 4697 + dm - The DM object 4698 - name - The label name 4699 4700 Output Parameter: 4701 . size - The number of different integer ids, or 0 if the label does not exist 4702 4703 Level: beginner 4704 4705 .keywords: mesh 4706 .seealso: DMLabeGetNumValues(), DMSetLabelValue() 4707 @*/ 4708 PetscErrorCode DMGetLabelSize(DM dm, const char name[], PetscInt *size) 4709 { 4710 DMLabel label; 4711 PetscErrorCode ierr; 4712 4713 PetscFunctionBegin; 4714 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4715 PetscValidCharPointer(name, 2); 4716 PetscValidPointer(size, 3); 4717 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4718 *size = 0; 4719 if (!label) PetscFunctionReturn(0); 4720 ierr = DMLabelGetNumValues(label, size);CHKERRQ(ierr); 4721 PetscFunctionReturn(0); 4722 } 4723 4724 #undef __FUNCT__ 4725 #define __FUNCT__ "DMGetLabelIdIS" 4726 /*@C 4727 DMGetLabelIdIS - Get the integer ids in a label 4728 4729 Not Collective 4730 4731 Input Parameters: 4732 + mesh - The DM object 4733 - name - The label name 4734 4735 Output Parameter: 4736 . ids - The integer ids, or NULL if the label does not exist 4737 4738 Level: beginner 4739 4740 .keywords: mesh 4741 .seealso: DMLabelGetValueIS(), DMGetLabelSize() 4742 @*/ 4743 PetscErrorCode DMGetLabelIdIS(DM dm, const char name[], IS *ids) 4744 { 4745 DMLabel label; 4746 PetscErrorCode ierr; 4747 4748 PetscFunctionBegin; 4749 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4750 PetscValidCharPointer(name, 2); 4751 PetscValidPointer(ids, 3); 4752 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4753 *ids = NULL; 4754 if (!label) PetscFunctionReturn(0); 4755 ierr = DMLabelGetValueIS(label, ids);CHKERRQ(ierr); 4756 PetscFunctionReturn(0); 4757 } 4758 4759 #undef __FUNCT__ 4760 #define __FUNCT__ "DMGetStratumSize" 4761 /*@C 4762 DMGetStratumSize - Get the number of points in a label stratum 4763 4764 Not Collective 4765 4766 Input Parameters: 4767 + dm - The DM object 4768 . name - The label name 4769 - value - The stratum value 4770 4771 Output Parameter: 4772 . size - The stratum size 4773 4774 Level: beginner 4775 4776 .keywords: mesh 4777 .seealso: DMLabelGetStratumSize(), DMGetLabelSize(), DMGetLabelIds() 4778 @*/ 4779 PetscErrorCode DMGetStratumSize(DM dm, const char name[], PetscInt value, PetscInt *size) 4780 { 4781 DMLabel label; 4782 PetscErrorCode ierr; 4783 4784 PetscFunctionBegin; 4785 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4786 PetscValidCharPointer(name, 2); 4787 PetscValidPointer(size, 4); 4788 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4789 *size = 0; 4790 if (!label) PetscFunctionReturn(0); 4791 ierr = DMLabelGetStratumSize(label, value, size);CHKERRQ(ierr); 4792 PetscFunctionReturn(0); 4793 } 4794 4795 #undef __FUNCT__ 4796 #define __FUNCT__ "DMGetStratumIS" 4797 /*@C 4798 DMGetStratumIS - Get the points in a label stratum 4799 4800 Not Collective 4801 4802 Input Parameters: 4803 + dm - The DM object 4804 . name - The label name 4805 - value - The stratum value 4806 4807 Output Parameter: 4808 . points - The stratum points, or NULL if the label does not exist or does not have that value 4809 4810 Level: beginner 4811 4812 .keywords: mesh 4813 .seealso: DMLabelGetStratumIS(), DMGetStratumSize() 4814 @*/ 4815 PetscErrorCode DMGetStratumIS(DM dm, const char name[], PetscInt value, IS *points) 4816 { 4817 DMLabel label; 4818 PetscErrorCode ierr; 4819 4820 PetscFunctionBegin; 4821 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4822 PetscValidCharPointer(name, 2); 4823 PetscValidPointer(points, 4); 4824 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4825 *points = NULL; 4826 if (!label) PetscFunctionReturn(0); 4827 ierr = DMLabelGetStratumIS(label, value, points);CHKERRQ(ierr); 4828 PetscFunctionReturn(0); 4829 } 4830 4831 #undef __FUNCT__ 4832 #define __FUNCT__ "DMClearLabelStratum" 4833 /*@C 4834 DMClearLabelStratum - Remove all points from a stratum from a Sieve Label 4835 4836 Not Collective 4837 4838 Input Parameters: 4839 + dm - The DM object 4840 . name - The label name 4841 - value - The label value for this point 4842 4843 Output Parameter: 4844 4845 Level: beginner 4846 4847 .keywords: mesh 4848 .seealso: DMLabelClearStratum(), DMSetLabelValue(), DMGetStratumIS(), DMClearLabelValue() 4849 @*/ 4850 PetscErrorCode DMClearLabelStratum(DM dm, const char name[], PetscInt value) 4851 { 4852 DMLabel label; 4853 PetscErrorCode ierr; 4854 4855 PetscFunctionBegin; 4856 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4857 PetscValidCharPointer(name, 2); 4858 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 4859 if (!label) PetscFunctionReturn(0); 4860 ierr = DMLabelClearStratum(label, value);CHKERRQ(ierr); 4861 PetscFunctionReturn(0); 4862 } 4863 4864 #undef __FUNCT__ 4865 #define __FUNCT__ "DMGetNumLabels" 4866 /*@ 4867 DMGetNumLabels - Return the number of labels defined by the mesh 4868 4869 Not Collective 4870 4871 Input Parameter: 4872 . dm - The DM object 4873 4874 Output Parameter: 4875 . numLabels - the number of Labels 4876 4877 Level: intermediate 4878 4879 .keywords: mesh 4880 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 4881 @*/ 4882 PetscErrorCode DMGetNumLabels(DM dm, PetscInt *numLabels) 4883 { 4884 DMLabelLink next = dm->labels->next; 4885 PetscInt n = 0; 4886 4887 PetscFunctionBegin; 4888 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4889 PetscValidPointer(numLabels, 2); 4890 while (next) {++n; next = next->next;} 4891 *numLabels = n; 4892 PetscFunctionReturn(0); 4893 } 4894 4895 #undef __FUNCT__ 4896 #define __FUNCT__ "DMGetLabelName" 4897 /*@C 4898 DMGetLabelName - Return the name of nth label 4899 4900 Not Collective 4901 4902 Input Parameters: 4903 + dm - The DM object 4904 - n - the label number 4905 4906 Output Parameter: 4907 . name - the label name 4908 4909 Level: intermediate 4910 4911 .keywords: mesh 4912 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 4913 @*/ 4914 PetscErrorCode DMGetLabelName(DM dm, PetscInt n, const char **name) 4915 { 4916 DMLabelLink next = dm->labels->next; 4917 PetscInt l = 0; 4918 4919 PetscFunctionBegin; 4920 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4921 PetscValidPointer(name, 3); 4922 while (next) { 4923 if (l == n) { 4924 *name = next->label->name; 4925 PetscFunctionReturn(0); 4926 } 4927 ++l; 4928 next = next->next; 4929 } 4930 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 4931 } 4932 4933 #undef __FUNCT__ 4934 #define __FUNCT__ "DMHasLabel" 4935 /*@C 4936 DMHasLabel - Determine whether the mesh has a label of a given name 4937 4938 Not Collective 4939 4940 Input Parameters: 4941 + dm - The DM object 4942 - name - The label name 4943 4944 Output Parameter: 4945 . hasLabel - PETSC_TRUE if the label is present 4946 4947 Level: intermediate 4948 4949 .keywords: mesh 4950 .seealso: DMCreateLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 4951 @*/ 4952 PetscErrorCode DMHasLabel(DM dm, const char name[], PetscBool *hasLabel) 4953 { 4954 DMLabelLink next = dm->labels->next; 4955 PetscErrorCode ierr; 4956 4957 PetscFunctionBegin; 4958 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4959 PetscValidCharPointer(name, 2); 4960 PetscValidPointer(hasLabel, 3); 4961 *hasLabel = PETSC_FALSE; 4962 while (next) { 4963 ierr = PetscStrcmp(name, next->label->name, hasLabel);CHKERRQ(ierr); 4964 if (*hasLabel) break; 4965 next = next->next; 4966 } 4967 PetscFunctionReturn(0); 4968 } 4969 4970 #undef __FUNCT__ 4971 #define __FUNCT__ "DMGetLabel" 4972 /*@C 4973 DMGetLabel - Return the label of a given name, or NULL 4974 4975 Not Collective 4976 4977 Input Parameters: 4978 + dm - The DM object 4979 - name - The label name 4980 4981 Output Parameter: 4982 . label - The DMLabel, or NULL if the label is absent 4983 4984 Level: intermediate 4985 4986 .keywords: mesh 4987 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 4988 @*/ 4989 PetscErrorCode DMGetLabel(DM dm, const char name[], DMLabel *label) 4990 { 4991 DMLabelLink next = dm->labels->next; 4992 PetscBool hasLabel; 4993 PetscErrorCode ierr; 4994 4995 PetscFunctionBegin; 4996 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4997 PetscValidCharPointer(name, 2); 4998 PetscValidPointer(label, 3); 4999 *label = NULL; 5000 while (next) { 5001 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5002 if (hasLabel) { 5003 *label = next->label; 5004 break; 5005 } 5006 next = next->next; 5007 } 5008 PetscFunctionReturn(0); 5009 } 5010 5011 #undef __FUNCT__ 5012 #define __FUNCT__ "DMGetLabelByNum" 5013 /*@C 5014 DMGetLabelByNum - Return the nth label 5015 5016 Not Collective 5017 5018 Input Parameters: 5019 + dm - The DM object 5020 - n - the label number 5021 5022 Output Parameter: 5023 . label - the label 5024 5025 Level: intermediate 5026 5027 .keywords: mesh 5028 .seealso: DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5029 @*/ 5030 PetscErrorCode DMGetLabelByNum(DM dm, PetscInt n, DMLabel *label) 5031 { 5032 DMLabelLink next = dm->labels->next; 5033 PetscInt l = 0; 5034 5035 PetscFunctionBegin; 5036 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5037 PetscValidPointer(label, 3); 5038 while (next) { 5039 if (l == n) { 5040 *label = next->label; 5041 PetscFunctionReturn(0); 5042 } 5043 ++l; 5044 next = next->next; 5045 } 5046 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %D does not exist in this DM", n); 5047 } 5048 5049 #undef __FUNCT__ 5050 #define __FUNCT__ "DMAddLabel" 5051 /*@C 5052 DMAddLabel - Add the label to this mesh 5053 5054 Not Collective 5055 5056 Input Parameters: 5057 + dm - The DM object 5058 - label - The DMLabel 5059 5060 Level: developer 5061 5062 .keywords: mesh 5063 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5064 @*/ 5065 PetscErrorCode DMAddLabel(DM dm, DMLabel label) 5066 { 5067 DMLabelLink tmpLabel; 5068 PetscBool hasLabel; 5069 PetscErrorCode ierr; 5070 5071 PetscFunctionBegin; 5072 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5073 ierr = DMHasLabel(dm, label->name, &hasLabel);CHKERRQ(ierr); 5074 if (hasLabel) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Label %s already exists in this DM", label->name); 5075 ierr = PetscCalloc1(1, &tmpLabel);CHKERRQ(ierr); 5076 tmpLabel->label = label; 5077 tmpLabel->output = PETSC_TRUE; 5078 tmpLabel->next = dm->labels->next; 5079 dm->labels->next = tmpLabel; 5080 PetscFunctionReturn(0); 5081 } 5082 5083 #undef __FUNCT__ 5084 #define __FUNCT__ "DMRemoveLabel" 5085 /*@C 5086 DMRemoveLabel - Remove the label from this mesh 5087 5088 Not Collective 5089 5090 Input Parameters: 5091 + dm - The DM object 5092 - name - The label name 5093 5094 Output Parameter: 5095 . label - The DMLabel, or NULL if the label is absent 5096 5097 Level: developer 5098 5099 .keywords: mesh 5100 .seealso: DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5101 @*/ 5102 PetscErrorCode DMRemoveLabel(DM dm, const char name[], DMLabel *label) 5103 { 5104 DMLabelLink next = dm->labels->next; 5105 DMLabelLink last = NULL; 5106 PetscBool hasLabel; 5107 PetscErrorCode ierr; 5108 5109 PetscFunctionBegin; 5110 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5111 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 5112 *label = NULL; 5113 if (!hasLabel) PetscFunctionReturn(0); 5114 while (next) { 5115 ierr = PetscStrcmp(name, next->label->name, &hasLabel);CHKERRQ(ierr); 5116 if (hasLabel) { 5117 if (last) last->next = next->next; 5118 else dm->labels->next = next->next; 5119 next->next = NULL; 5120 *label = next->label; 5121 ierr = PetscStrcmp(name, "depth", &hasLabel);CHKERRQ(ierr); 5122 if (hasLabel) { 5123 dm->depthLabel = NULL; 5124 } 5125 ierr = PetscFree(next);CHKERRQ(ierr); 5126 break; 5127 } 5128 last = next; 5129 next = next->next; 5130 } 5131 PetscFunctionReturn(0); 5132 } 5133 5134 #undef __FUNCT__ 5135 #define __FUNCT__ "DMGetLabelOutput" 5136 /*@C 5137 DMGetLabelOutput - Get the output flag for a given label 5138 5139 Not Collective 5140 5141 Input Parameters: 5142 + dm - The DM object 5143 - name - The label name 5144 5145 Output Parameter: 5146 . output - The flag for output 5147 5148 Level: developer 5149 5150 .keywords: mesh 5151 .seealso: DMSetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5152 @*/ 5153 PetscErrorCode DMGetLabelOutput(DM dm, const char name[], PetscBool *output) 5154 { 5155 DMLabelLink next = dm->labels->next; 5156 PetscErrorCode ierr; 5157 5158 PetscFunctionBegin; 5159 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5160 PetscValidPointer(name, 2); 5161 PetscValidPointer(output, 3); 5162 while (next) { 5163 PetscBool flg; 5164 5165 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5166 if (flg) {*output = next->output; PetscFunctionReturn(0);} 5167 next = next->next; 5168 } 5169 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5170 } 5171 5172 #undef __FUNCT__ 5173 #define __FUNCT__ "DMSetLabelOutput" 5174 /*@C 5175 DMSetLabelOutput - Set the output flag for a given label 5176 5177 Not Collective 5178 5179 Input Parameters: 5180 + dm - The DM object 5181 . name - The label name 5182 - output - The flag for output 5183 5184 Level: developer 5185 5186 .keywords: mesh 5187 .seealso: DMGetLabelOutput(), DMCreateLabel(), DMHasLabel(), DMGetLabelValue(), DMSetLabelValue(), DMGetStratumIS() 5188 @*/ 5189 PetscErrorCode DMSetLabelOutput(DM dm, const char name[], PetscBool output) 5190 { 5191 DMLabelLink next = dm->labels->next; 5192 PetscErrorCode ierr; 5193 5194 PetscFunctionBegin; 5195 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5196 PetscValidPointer(name, 2); 5197 while (next) { 5198 PetscBool flg; 5199 5200 ierr = PetscStrcmp(name, next->label->name, &flg);CHKERRQ(ierr); 5201 if (flg) {next->output = output; PetscFunctionReturn(0);} 5202 next = next->next; 5203 } 5204 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No label named %s was present in this dm", name); 5205 } 5206 5207 5208 #undef __FUNCT__ 5209 #define __FUNCT__ "DMCopyLabels" 5210 /*@ 5211 DMCopyLabels - Copy labels from one mesh to another with a superset of the points 5212 5213 Collective on DM 5214 5215 Input Parameter: 5216 . dmA - The DMPlex object with initial labels 5217 5218 Output Parameter: 5219 . dmB - The DMPlex object with copied labels 5220 5221 Level: intermediate 5222 5223 Note: This is typically used when interpolating or otherwise adding to a mesh 5224 5225 .keywords: mesh 5226 .seealso: DMCopyCoordinates(), DMGetCoordinates(), DMGetCoordinatesLocal(), DMGetCoordinateDM(), DMGetCoordinateSection() 5227 @*/ 5228 PetscErrorCode DMCopyLabels(DM dmA, DM dmB) 5229 { 5230 PetscInt numLabels, l; 5231 PetscErrorCode ierr; 5232 5233 PetscFunctionBegin; 5234 if (dmA == dmB) PetscFunctionReturn(0); 5235 ierr = DMGetNumLabels(dmA, &numLabels);CHKERRQ(ierr); 5236 for (l = 0; l < numLabels; ++l) { 5237 DMLabel label, labelNew; 5238 const char *name; 5239 PetscBool flg; 5240 5241 ierr = DMGetLabelName(dmA, l, &name);CHKERRQ(ierr); 5242 ierr = PetscStrcmp(name, "depth", &flg);CHKERRQ(ierr); 5243 if (flg) continue; 5244 ierr = DMGetLabel(dmA, name, &label);CHKERRQ(ierr); 5245 ierr = DMLabelDuplicate(label, &labelNew);CHKERRQ(ierr); 5246 ierr = DMAddLabel(dmB, labelNew);CHKERRQ(ierr); 5247 } 5248 PetscFunctionReturn(0); 5249 } 5250 5251 #undef __FUNCT__ 5252 #define __FUNCT__ "DMGetCoarseDM" 5253 /*@ 5254 DMGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5255 5256 Input Parameter: 5257 . dm - The DM object 5258 5259 Output Parameter: 5260 . cdm - The coarse DM 5261 5262 Level: intermediate 5263 5264 .seealso: DMSetCoarseDM() 5265 @*/ 5266 PetscErrorCode DMGetCoarseDM(DM dm, DM *cdm) 5267 { 5268 PetscFunctionBegin; 5269 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5270 PetscValidPointer(cdm, 2); 5271 *cdm = dm->coarseMesh; 5272 PetscFunctionReturn(0); 5273 } 5274 5275 #undef __FUNCT__ 5276 #define __FUNCT__ "DMSetCoarseDM" 5277 /*@ 5278 DMSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5279 5280 Input Parameters: 5281 + dm - The DM object 5282 - cdm - The coarse DM 5283 5284 Level: intermediate 5285 5286 .seealso: DMGetCoarseDM() 5287 @*/ 5288 PetscErrorCode DMSetCoarseDM(DM dm, DM cdm) 5289 { 5290 PetscErrorCode ierr; 5291 5292 PetscFunctionBegin; 5293 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5294 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5295 ierr = PetscObjectReference((PetscObject)cdm);CHKERRQ(ierr); 5296 ierr = DMDestroy(&dm->coarseMesh);CHKERRQ(ierr); 5297 dm->coarseMesh = cdm; 5298 PetscFunctionReturn(0); 5299 } 5300 5301